diff --git a/Cargo.lock b/Cargo.lock index 908bfa355571b..03b47346b4be2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1747,7 +1747,7 @@ checksum = "5b31c9b90731276fdd24d896f31bb10aecf2e5151733364ae81123186643d939" dependencies = [ "jsonrpc-core", "log", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "serde", ] @@ -1866,9 +1866,9 @@ checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" [[package]] name = "lock_api" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" dependencies = [ "scopeguard", ] @@ -2406,12 +2406,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" +checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" dependencies = [ "lock_api", - "parking_lot_core 0.7.0", + "parking_lot_core 0.7.1", ] [[package]] @@ -2431,9 +2431,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" +checksum = "0e136c1904604defe99ce5fd71a28d473fa60a12255d511aa78a9ddf11237aeb" dependencies = [ "cfg-if", "cloudabi", @@ -3251,7 +3251,7 @@ dependencies = [ "lazy_static 1.4.0", "log", "measureme", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "rustc-ap-graphviz", "rustc-ap-rustc_index", "rustc-ap-serialize", @@ -3696,7 +3696,7 @@ dependencies = [ "lazy_static 1.4.0", "log", "measureme", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "rustc-hash", "rustc-rayon", "rustc-rayon-core", @@ -3991,7 +3991,7 @@ dependencies = [ "jobserver", "log", "measureme", - "parking_lot 0.10.0", + "parking_lot 0.10.2", "polonius-engine", "rustc-rayon", "rustc-rayon-core", @@ -4140,7 +4140,7 @@ name = "rustc_query_system" version = "0.0.0" dependencies = [ "log", - "parking_lot 0.9.0", + "parking_lot 0.10.2", "rustc-rayon-core", "rustc_data_structures", "rustc_errors", diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 38fa3d736246c..3fc1b5e16b372 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -2361,6 +2361,34 @@ impl<'a, K: Ord, V> Entry<'a, K, V> { } } + #[unstable(feature = "or_insert_with_key", issue = "71024")] + /// Ensures a value is in the entry by inserting, if empty, the result of the default function, + /// which takes the key as its argument, and returns a mutable reference to the value in the + /// entry. + /// + /// # Examples + /// + /// ``` + /// #![feature(or_insert_with_key)] + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// map.entry("poneyland").or_insert_with_key(|key| key.chars().count()); + /// + /// assert_eq!(map["poneyland"], 9); + /// ``` + #[inline] + pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => { + let value = default(entry.key()); + entry.insert(value) + } + } + } + /// Returns a reference to this entry's key. /// /// # Examples diff --git a/src/libcore/char/mod.rs b/src/libcore/char/mod.rs index cf5576e549cdf..715ad8992ad6b 100644 --- a/src/libcore/char/mod.rs +++ b/src/libcore/char/mod.rs @@ -37,8 +37,6 @@ pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error}; // unstable re-exports #[unstable(feature = "unicode_version", issue = "49726")] -pub use crate::unicode::version::UnicodeVersion; -#[unstable(feature = "unicode_version", issue = "49726")] pub use crate::unicode::UNICODE_VERSION; use crate::fmt::{self, Write}; diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs index 9c885ef99a980..73404a73e3d00 100644 --- a/src/libcore/macros/mod.rs +++ b/src/libcore/macros/mod.rs @@ -1316,6 +1316,14 @@ pub(crate) mod builtin { issue = "70173", reason = "inline assembly is not stable enough for use and is subject to change" )] + #[cfg_attr( + not(bootstrap), + rustc_deprecated( + since = "1.44.0", + reason = "the syntax of asm! will change soon, use llvm_asm! to avoid breakage", + suggestion = "llvm_asm", + ) + )] #[rustc_builtin_macro] #[macro_export] macro_rules! asm { diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 9b4ed4e820512..6a51d39ab9d4e 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -54,6 +54,7 @@ pub use crate::fmt::macros::Debug; pub use crate::hash::macros::Hash; #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow(deprecated)] #[doc(no_inline)] pub use crate::{ asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args, diff --git a/src/libcore/unicode/mod.rs b/src/libcore/unicode/mod.rs index 94a2507e26ccb..3952ae4482e9f 100644 --- a/src/libcore/unicode/mod.rs +++ b/src/libcore/unicode/mod.rs @@ -3,19 +3,14 @@ pub(crate) mod printable; mod unicode_data; -pub(crate) mod version; - -use version::UnicodeVersion; /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of /// `char` and `str` methods are based on. +/// +/// The version numbering scheme is explained in +/// [Unicode 11.0 or later, Section 3.1 Versions of the Unicode Standard](https://www.unicode.org/versions/Unicode11.0.0/ch03.pdf#page=4). #[unstable(feature = "unicode_version", issue = "49726")] -pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion { - major: unicode_data::UNICODE_VERSION.0, - minor: unicode_data::UNICODE_VERSION.1, - micro: unicode_data::UNICODE_VERSION.2, - _priv: (), -}; +pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION; // For use in liballoc, not re-exported in libstd. pub mod derived_property { diff --git a/src/libcore/unicode/unicode_data.rs b/src/libcore/unicode/unicode_data.rs index 48caa21fb0aa1..9c92a8ba28ae4 100644 --- a/src/libcore/unicode/unicode_data.rs +++ b/src/libcore/unicode/unicode_data.rs @@ -94,7 +94,7 @@ fn skip_search( offset_idx % 2 == 1 } -pub const UNICODE_VERSION: (u32, u32, u32) = (13, 0, 0); +pub const UNICODE_VERSION: (u8, u8, u8) = (13, 0, 0); #[rustfmt::skip] pub mod alphabetic { diff --git a/src/libcore/unicode/version.rs b/src/libcore/unicode/version.rs deleted file mode 100644 index 4d68d2e8c2ef7..0000000000000 --- a/src/libcore/unicode/version.rs +++ /dev/null @@ -1,18 +0,0 @@ -/// Represents a Unicode Version. -/// -/// See also: -#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] -#[unstable(feature = "unicode_version", issue = "49726")] -pub struct UnicodeVersion { - /// Major version. - pub major: u32, - - /// Minor version. - pub minor: u32, - - /// Micro (or Update) version. - pub micro: u32, - - // Private field to keep struct expandable. - pub(crate) _priv: (), -} diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index 9984eb4e2825f..2fc58efbf0e7f 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -590,6 +590,7 @@ impl<'hir> LoweringContext<'_, 'hir> { await_span, self.allow_gen_future.clone(), ); + let expr = self.lower_expr(expr); let pinned_ident = Ident::with_dummy_span(sym::pinned); let (pinned_pat, pinned_pat_hid) = @@ -671,7 +672,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unit = self.expr_unit(span); let yield_expr = self.expr( span, - hir::ExprKind::Yield(unit, hir::YieldSource::Await), + hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr.hir_id) }), ThinVec::new(), ); let yield_expr = self.arena.alloc(yield_expr); @@ -704,7 +705,6 @@ impl<'hir> LoweringContext<'_, 'hir> { // match { // mut pinned => loop { .. } // } - let expr = self.lower_expr(expr); hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar) } diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index ca349a7890a58..b1fb1ef0e331c 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -104,6 +104,7 @@ pub struct ModuleConfig { pub emit_ir: bool, pub emit_asm: bool, pub emit_obj: EmitObj, + // Miscellaneous flags. These are mostly copied from command-line // options. pub verify_llvm_ir: bool, @@ -118,77 +119,144 @@ pub struct ModuleConfig { } impl ModuleConfig { - fn new(passes: Vec) -> ModuleConfig { - ModuleConfig { - passes, - opt_level: None, - opt_size: None, - - pgo_gen: SwitchWithOptPath::Disabled, - pgo_use: None, - - sanitizer: None, - sanitizer_recover: Default::default(), - sanitizer_memory_track_origins: 0, - - emit_no_opt_bc: false, - emit_pre_lto_bc: false, - emit_bc: false, - emit_bc_compressed: false, - emit_ir: false, - emit_asm: false, - emit_obj: EmitObj::None, - - verify_llvm_ir: false, - no_prepopulate_passes: false, - no_builtins: false, - time_module: true, - vectorize_loop: false, - vectorize_slp: false, - merge_functions: false, - inline_threshold: None, - new_llvm_pass_manager: None, + fn new(kind: ModuleKind, sess: &Session, no_builtins: bool) -> ModuleConfig { + // If it's a regular module, use `$regular`, otherwise use `$other`. + // `$regular` and `$other` are evaluated lazily. + macro_rules! if_regular { + ($regular: expr, $other: expr) => { + if let ModuleKind::Regular = kind { $regular } else { $other } + }; } - } - fn set_flags(&mut self, sess: &Session, no_builtins: bool) { - self.verify_llvm_ir = sess.verify_llvm_ir(); - self.no_prepopulate_passes = sess.opts.cg.no_prepopulate_passes; - self.no_builtins = no_builtins || sess.target.target.options.no_builtins; - self.inline_threshold = sess.opts.cg.inline_threshold; - self.new_llvm_pass_manager = sess.opts.debugging_opts.new_llvm_pass_manager; - - // Copy what clang does by turning on loop vectorization at O2 and - // slp vectorization at O3. Otherwise configure other optimization aspects - // of this pass manager builder. - self.vectorize_loop = !sess.opts.cg.no_vectorize_loops - && (sess.opts.optimize == config::OptLevel::Default - || sess.opts.optimize == config::OptLevel::Aggressive); - - self.vectorize_slp = - !sess.opts.cg.no_vectorize_slp && sess.opts.optimize == config::OptLevel::Aggressive; - - // Some targets (namely, NVPTX) interact badly with the MergeFunctions - // pass. This is because MergeFunctions can generate new function calls - // which may interfere with the target calling convention; e.g. for the - // NVPTX target, PTX kernels should not call other PTX kernels. - // MergeFunctions can also be configured to generate aliases instead, - // but aliases are not supported by some backends (again, NVPTX). - // Therefore, allow targets to opt out of the MergeFunctions pass, - // but otherwise keep the pass enabled (at O2 and O3) since it can be - // useful for reducing code size. - self.merge_functions = match sess - .opts - .debugging_opts - .merge_functions - .unwrap_or(sess.target.target.options.merge_functions) + let opt_level_and_size = if_regular!(Some(sess.opts.optimize), None); + + let save_temps = sess.opts.cg.save_temps; + + let should_emit_obj = sess.opts.output_types.contains_key(&OutputType::Exe) + || match kind { + ModuleKind::Regular => sess.opts.output_types.contains_key(&OutputType::Object), + ModuleKind::Allocator => false, + ModuleKind::Metadata => sess.opts.output_types.contains_key(&OutputType::Metadata), + }; + + let emit_obj = if !should_emit_obj { + EmitObj::None + } else if sess.target.target.options.obj_is_bitcode + || sess.opts.cg.linker_plugin_lto.enabled() { - MergeFunctions::Disabled => false, - MergeFunctions::Trampolines | MergeFunctions::Aliases => { - sess.opts.optimize == config::OptLevel::Default - || sess.opts.optimize == config::OptLevel::Aggressive + EmitObj::Bitcode + } else if sess.opts.debugging_opts.embed_bitcode { + match sess.opts.optimize { + config::OptLevel::No | config::OptLevel::Less => { + EmitObj::ObjectCode(BitcodeSection::Marker) + } + _ => EmitObj::ObjectCode(BitcodeSection::Full), } + } else { + EmitObj::ObjectCode(BitcodeSection::None) }; + + ModuleConfig { + passes: if_regular!( + { + let mut passes = sess.opts.cg.passes.clone(); + if sess.opts.debugging_opts.profile { + passes.push("insert-gcov-profiling".to_owned()); + } + passes + }, + vec![] + ), + + opt_level: opt_level_and_size, + opt_size: opt_level_and_size, + + pgo_gen: if_regular!( + sess.opts.cg.profile_generate.clone(), + SwitchWithOptPath::Disabled + ), + pgo_use: if_regular!(sess.opts.cg.profile_use.clone(), None), + + sanitizer: if_regular!(sess.opts.debugging_opts.sanitizer.clone(), None), + sanitizer_recover: if_regular!( + sess.opts.debugging_opts.sanitizer_recover.clone(), + vec![] + ), + sanitizer_memory_track_origins: if_regular!( + sess.opts.debugging_opts.sanitizer_memory_track_origins, + 0 + ), + + emit_pre_lto_bc: if_regular!( + save_temps || need_pre_lto_bitcode_for_incr_comp(sess), + false + ), + emit_no_opt_bc: if_regular!(save_temps, false), + emit_bc: if_regular!( + save_temps || sess.opts.output_types.contains_key(&OutputType::Bitcode), + save_temps + ), + emit_bc_compressed: match kind { + ModuleKind::Regular | ModuleKind::Allocator => { + // Emit compressed bitcode files for the crate if we're + // emitting an rlib. Whenever an rlib is created, the + // bitcode is inserted into the archive in order to allow + // LTO against it. + need_crate_bitcode_for_rlib(sess) + } + ModuleKind::Metadata => false, + }, + emit_ir: if_regular!( + sess.opts.output_types.contains_key(&OutputType::LlvmAssembly), + false + ), + emit_asm: if_regular!( + sess.opts.output_types.contains_key(&OutputType::Assembly), + false + ), + emit_obj, + + verify_llvm_ir: sess.verify_llvm_ir(), + no_prepopulate_passes: sess.opts.cg.no_prepopulate_passes, + no_builtins: no_builtins || sess.target.target.options.no_builtins, + + // Exclude metadata and allocator modules from time_passes output, + // since they throw off the "LLVM passes" measurement. + time_module: if_regular!(true, false), + + // Copy what clang does by turning on loop vectorization at O2 and + // slp vectorization at O3. + vectorize_loop: !sess.opts.cg.no_vectorize_loops + && (sess.opts.optimize == config::OptLevel::Default + || sess.opts.optimize == config::OptLevel::Aggressive), + vectorize_slp: !sess.opts.cg.no_vectorize_slp + && sess.opts.optimize == config::OptLevel::Aggressive, + + // Some targets (namely, NVPTX) interact badly with the + // MergeFunctions pass. This is because MergeFunctions can generate + // new function calls which may interfere with the target calling + // convention; e.g. for the NVPTX target, PTX kernels should not + // call other PTX kernels. MergeFunctions can also be configured to + // generate aliases instead, but aliases are not supported by some + // backends (again, NVPTX). Therefore, allow targets to opt out of + // the MergeFunctions pass, but otherwise keep the pass enabled (at + // O2 and O3) since it can be useful for reducing code size. + merge_functions: match sess + .opts + .debugging_opts + .merge_functions + .unwrap_or(sess.target.target.options.merge_functions) + { + MergeFunctions::Disabled => false, + MergeFunctions::Trampolines | MergeFunctions::Aliases => { + sess.opts.optimize == config::OptLevel::Default + || sess.opts.optimize == config::OptLevel::Aggressive + } + }, + + inline_threshold: sess.opts.cg.inline_threshold, + new_llvm_pass_manager: sess.opts.debugging_opts.new_llvm_pass_manager, + } } pub fn bitcode_needed(&self) -> bool { @@ -353,99 +421,9 @@ pub fn start_async_codegen( let linker_info = LinkerInfo::new(tcx); let crate_info = CrateInfo::new(tcx); - // Figure out what we actually need to build. - let mut modules_config = ModuleConfig::new(sess.opts.cg.passes.clone()); - let mut metadata_config = ModuleConfig::new(vec![]); - let mut allocator_config = ModuleConfig::new(vec![]); - - if sess.opts.debugging_opts.profile { - modules_config.passes.push("insert-gcov-profiling".to_owned()) - } - - modules_config.pgo_gen = sess.opts.cg.profile_generate.clone(); - modules_config.pgo_use = sess.opts.cg.profile_use.clone(); - modules_config.sanitizer = sess.opts.debugging_opts.sanitizer.clone(); - modules_config.sanitizer_recover = sess.opts.debugging_opts.sanitizer_recover.clone(); - modules_config.sanitizer_memory_track_origins = - sess.opts.debugging_opts.sanitizer_memory_track_origins; - modules_config.opt_level = Some(sess.opts.optimize); - modules_config.opt_size = Some(sess.opts.optimize); - - // Save all versions of the bytecode if we're saving our temporaries. - if sess.opts.cg.save_temps { - modules_config.emit_no_opt_bc = true; - modules_config.emit_pre_lto_bc = true; - modules_config.emit_bc = true; - metadata_config.emit_bc = true; - allocator_config.emit_bc = true; - } - - // Emit compressed bitcode files for the crate if we're emitting an rlib. - // Whenever an rlib is created, the bitcode is inserted into the archive in - // order to allow LTO against it. - if need_crate_bitcode_for_rlib(sess) { - modules_config.emit_bc_compressed = true; - allocator_config.emit_bc_compressed = true; - } - - let emit_obj = - if sess.target.target.options.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() { - EmitObj::Bitcode - } else if sess.opts.debugging_opts.embed_bitcode { - match sess.opts.optimize { - config::OptLevel::No | config::OptLevel::Less => { - EmitObj::ObjectCode(BitcodeSection::Marker) - } - _ => EmitObj::ObjectCode(BitcodeSection::Full), - } - } else { - EmitObj::ObjectCode(BitcodeSection::None) - }; - - modules_config.emit_pre_lto_bc = need_pre_lto_bitcode_for_incr_comp(sess); - - for output_type in sess.opts.output_types.keys() { - match *output_type { - OutputType::Bitcode => { - modules_config.emit_bc = true; - } - OutputType::LlvmAssembly => { - modules_config.emit_ir = true; - } - OutputType::Assembly => { - modules_config.emit_asm = true; - // If we're not using the LLVM assembler, this function - // could be invoked specially with output_type_assembly, so - // in this case we still want the metadata object file. - if !sess.opts.output_types.contains_key(&OutputType::Assembly) { - metadata_config.emit_obj = emit_obj; - allocator_config.emit_obj = emit_obj; - } - } - OutputType::Object => { - modules_config.emit_obj = emit_obj; - } - OutputType::Metadata => { - metadata_config.emit_obj = emit_obj; - } - OutputType::Exe => { - modules_config.emit_obj = emit_obj; - metadata_config.emit_obj = emit_obj; - allocator_config.emit_obj = emit_obj; - } - OutputType::Mir => {} - OutputType::DepInfo => {} - } - } - - modules_config.set_flags(sess, no_builtins); - metadata_config.set_flags(sess, no_builtins); - allocator_config.set_flags(sess, no_builtins); - - // Exclude metadata and allocator modules from time_passes output, since - // they throw off the "LLVM passes" measurement. - metadata_config.time_module = false; - allocator_config.time_module = false; + let regular_config = ModuleConfig::new(ModuleKind::Regular, sess, no_builtins); + let metadata_config = ModuleConfig::new(ModuleKind::Metadata, sess, no_builtins); + let allocator_config = ModuleConfig::new(ModuleKind::Allocator, sess, no_builtins); let (shared_emitter, shared_emitter_main) = SharedEmitter::new(); let (codegen_worker_send, codegen_worker_receive) = channel(); @@ -459,7 +437,7 @@ pub fn start_async_codegen( coordinator_receive, total_cgus, sess.jobserver.clone(), - Arc::new(modules_config), + Arc::new(regular_config), Arc::new(metadata_config), Arc::new(allocator_config), coordinator_send.clone(), @@ -959,7 +937,7 @@ fn start_executing_work( coordinator_receive: Receiver>, total_cgus: usize, jobserver: Client, - modules_config: Arc, + regular_config: Arc, metadata_config: Arc, allocator_config: Arc, tx_to_llvm_workers: Sender>, @@ -1042,7 +1020,7 @@ fn start_executing_work( coordinator_send, diag_emitter: shared_emitter.clone(), output_filenames: tcx.output_filenames(LOCAL_CRATE), - regular_module_config: modules_config, + regular_module_config: regular_config, metadata_module_config: metadata_config, allocator_module_config: allocator_config, tm_factory: TargetMachineFactory(backend.target_machine_factory(tcx.sess, ol, false)), diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index b719d576d6f67..440fdc662862e 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -1736,15 +1736,24 @@ pub struct Destination { #[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)] pub enum YieldSource { /// An `.await`. - Await, + Await { expr: Option }, /// A plain `yield`. Yield, } +impl YieldSource { + pub fn is_await(&self) -> bool { + match self { + YieldSource::Await { .. } => true, + YieldSource::Yield => false, + } + } +} + impl fmt::Display for YieldSource { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(match self { - YieldSource::Await => "`await`", + YieldSource::Await { .. } => "`await`", YieldSource::Yield => "`yield`", }) } @@ -1755,7 +1764,7 @@ impl From for YieldSource { match kind { // Guess based on the kind of the current generator. GeneratorKind::Gen => Self::Yield, - GeneratorKind::Async(_) => Self::Await, + GeneratorKind::Async(_) => Self::Await { expr: None }, } } } diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index b82008f429fa4..212061cfd824f 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -1403,6 +1403,21 @@ impl AssertKind { BoundsCheck { .. } => bug!("Unexpected AssertKind"), } } + + /// Format the message arguments for the `assert(cond, msg..)` terminator in MIR printing. + fn fmt_assert_args(&self, f: &mut W) -> fmt::Result + where + O: Debug, + { + match self { + AssertKind::BoundsCheck { ref len, ref index } => write!( + f, + "\"index out of bounds: the len is {{}} but the index is {{}}\", {:?}, {:?}", + len, index + ), + _ => write!(f, "\"{}\"", self.description()), + } + } } impl fmt::Debug for AssertKind { @@ -1480,7 +1495,9 @@ impl<'tcx> TerminatorKind<'tcx> { if !expected { write!(fmt, "!")?; } - write!(fmt, "{:?}, \"{:?}\")", cond, msg) + write!(fmt, "{:?}, ", cond)?; + msg.fmt_assert_args(fmt)?; + write!(fmt, ")") } FalseEdges { .. } => write!(fmt, "falseEdges"), FalseUnwind { .. } => write!(fmt, "falseUnwind"), diff --git a/src/librustc_query_system/Cargo.toml b/src/librustc_query_system/Cargo.toml index e1657a8f3c607..7520da1f32bcd 100644 --- a/src/librustc_query_system/Cargo.toml +++ b/src/librustc_query_system/Cargo.toml @@ -18,5 +18,5 @@ rustc_index = { path = "../librustc_index" } rustc_macros = { path = "../librustc_macros" } rustc_serialize = { path = "../libserialize", package = "serialize" } rustc_span = { path = "../librustc_span" } -parking_lot = "0.9" +parking_lot = "0.10" smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 3edc066d49a60..36ad0ab6fcde2 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -10,7 +10,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; -use rustc_hir::Node; +use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; use rustc_middle::ty::TypeckTables; use rustc_middle::ty::{ self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, @@ -127,13 +127,14 @@ pub trait InferCtxtExt<'tcx> { scope_span: &Option, expr: Option, snippet: String, - first_generator: DefId, - last_generator: Option, + inner_generator_body: Option<&hir::Body<'_>>, + outer_generator: Option, trait_ref: ty::TraitRef<'_>, target_ty: Ty<'tcx>, tables: &ty::TypeckTables<'_>, obligation: &PredicateObligation<'tcx>, next_code: Option<&ObligationCauseCode<'tcx>>, + from_awaited_ty: Option, ); fn note_obligation_cause_code( @@ -978,6 +979,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation.predicate, obligation.cause.span ); let source_map = self.tcx.sess.source_map(); + let hir = self.tcx.hir(); // Attempt to detect an async-await error by looking at the obligation causes, looking // for a generator to be present. @@ -1002,8 +1004,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // - `BindingObligation` with `impl_send (Send requirement) // // The first obligation in the chain is the most useful and has the generator that captured - // the type. The last generator has information about where the bound was introduced. At - // least one generator should be present for this diagnostic to be modified. + // the type. The last generator (`outer_generator` below) has information about where the + // bound was introduced. At least one generator should be present for this diagnostic to be + // modified. let (mut trait_ref, mut target_ty) = match obligation.predicate { ty::Predicate::Trait(p, _) => { (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty())) @@ -1011,7 +1014,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { _ => (None, None), }; let mut generator = None; - let mut last_generator = None; + let mut outer_generator = None; let mut next_code = Some(&obligation.cause.code); while let Some(code) = next_code { debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code); @@ -1028,7 +1031,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { match ty.kind { ty::Generator(did, ..) => { generator = generator.or(Some(did)); - last_generator = Some(did); + outer_generator = Some(did); } ty::GeneratorWitness(..) => {} _ if generator.is_none() => { @@ -1060,7 +1063,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let span = self.tcx.def_span(generator_did); // Do not ICE on closure typeck (#66868). - if self.tcx.hir().as_local_hir_id(generator_did).is_none() { + if hir.as_local_hir_id(generator_did).is_none() { return false; } @@ -1086,37 +1089,63 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } }; + let generator_body = hir + .as_local_hir_id(generator_did) + .and_then(|hir_id| hir.maybe_body_owned_by(hir_id)) + .map(|body_id| hir.body(body_id)); + let mut visitor = AwaitsVisitor::default(); + if let Some(body) = generator_body { + visitor.visit_body(body); + } + debug!("maybe_note_obligation_cause_for_async_await: awaits = {:?}", visitor.awaits); + // Look for a type inside the generator interior that matches the target type to get // a span. let target_ty_erased = self.tcx.erase_regions(&target_ty); + let ty_matches = |ty| -> bool { + // Careful: the regions for types that appear in the + // generator interior are not generally known, so we + // want to erase them when comparing (and anyway, + // `Send` and other bounds are generally unaffected by + // the choice of region). When erasing regions, we + // also have to erase late-bound regions. This is + // because the types that appear in the generator + // interior generally contain "bound regions" to + // represent regions that are part of the suspended + // generator frame. Bound regions are preserved by + // `erase_regions` and so we must also call + // `erase_late_bound_regions`. + let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(ty)); + let ty_erased = self.tcx.erase_regions(&ty_erased); + let eq = ty::TyS::same_type(ty_erased, target_ty_erased); + debug!( + "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \ + target_ty_erased={:?} eq={:?}", + ty_erased, target_ty_erased, eq + ); + eq + }; let target_span = tables .generator_interior_types .iter() - .find(|ty::GeneratorInteriorTypeCause { ty, .. }| { - // Careful: the regions for types that appear in the - // generator interior are not generally known, so we - // want to erase them when comparing (and anyway, - // `Send` and other bounds are generally unaffected by - // the choice of region). When erasing regions, we - // also have to erase late-bound regions. This is - // because the types that appear in the generator - // interior generally contain "bound regions" to - // represent regions that are part of the suspended - // generator frame. Bound regions are preserved by - // `erase_regions` and so we must also call - // `erase_late_bound_regions`. - let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty)); - let ty_erased = self.tcx.erase_regions(&ty_erased); - let eq = ty::TyS::same_type(ty_erased, target_ty_erased); - debug!( - "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \ - target_ty_erased={:?} eq={:?}", - ty_erased, target_ty_erased, eq - ); - eq - }) - .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| { - (span, source_map.span_to_snippet(*span), scope_span, expr) + .find(|ty::GeneratorInteriorTypeCause { ty, .. }| ty_matches(ty)) + .map(|cause| { + // Check to see if any awaited expressions have the target type. + let from_awaited_ty = visitor + .awaits + .into_iter() + .map(|id| hir.expect_expr(id)) + .find(|await_expr| { + let ty = tables.expr_ty_adjusted(&await_expr); + debug!( + "maybe_note_obligation_cause_for_async_await: await_expr={:?}", + await_expr + ); + ty_matches(ty) + }) + .map(|expr| expr.span); + let ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. } = cause; + (span, source_map.span_to_snippet(*span), scope_span, expr, from_awaited_ty) }); debug!( @@ -1124,20 +1153,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { generator_interior_types={:?} target_span={:?}", target_ty, tables.generator_interior_types, target_span ); - if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span { + if let Some((target_span, Ok(snippet), scope_span, expr, from_awaited_ty)) = target_span { self.note_obligation_cause_for_async_await( err, *target_span, scope_span, *expr, snippet, - generator_did, - last_generator, + generator_body, + outer_generator, trait_ref, target_ty, tables, obligation, next_code, + from_awaited_ty, ); true } else { @@ -1154,35 +1184,27 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { scope_span: &Option, expr: Option, snippet: String, - first_generator: DefId, - last_generator: Option, + inner_generator_body: Option<&hir::Body<'_>>, + outer_generator: Option, trait_ref: ty::TraitRef<'_>, target_ty: Ty<'tcx>, tables: &ty::TypeckTables<'_>, obligation: &PredicateObligation<'tcx>, next_code: Option<&ObligationCauseCode<'tcx>>, + from_awaited_ty: Option, ) { let source_map = self.tcx.sess.source_map(); - let is_async_fn = self - .tcx - .parent(first_generator) - .map(|parent_did| self.tcx.asyncness(parent_did)) - .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async) - .unwrap_or(false); - let is_async_move = self - .tcx - .hir() - .as_local_hir_id(first_generator) - .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id)) - .map(|body_id| self.tcx.hir().body(body_id)) + let is_async = inner_generator_body .and_then(|body| body.generator_kind()) .map(|generator_kind| match generator_kind { hir::GeneratorKind::Async(..) => true, _ => false, }) .unwrap_or(false); - let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" }; + let (await_or_yield, an_await_or_yield) = + if is_async { ("await", "an await") } else { ("yield", "a yield") }; + let future_or_generator = if is_async { "future" } else { "generator" }; // Special case the primary error message when send or sync is the trait that was // not implemented. @@ -1195,22 +1217,34 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.clear_code(); err.set_primary_message(format!( - "future cannot be {} between threads safely", - trait_verb + "{} cannot be {} between threads safely", + future_or_generator, trait_verb )); let original_span = err.span.primary_span().unwrap(); let mut span = MultiSpan::from_span(original_span); - let message = if let Some(name) = last_generator - .and_then(|generator_did| self.tcx.parent(generator_did)) - .and_then(|parent_did| hir.as_local_hir_id(parent_did)) - .and_then(|parent_hir_id| hir.opt_name(parent_hir_id)) - { - format!("future returned by `{}` is not {}", name, trait_name) - } else { - format!("future is not {}", trait_name) - }; + let message = outer_generator + .and_then(|generator_did| { + Some(match self.tcx.generator_kind(generator_did).unwrap() { + GeneratorKind::Gen => format!("generator is not {}", trait_name), + GeneratorKind::Async(AsyncGeneratorKind::Fn) => self + .tcx + .parent(generator_did) + .and_then(|parent_did| hir.as_local_hir_id(parent_did)) + .and_then(|parent_hir_id| hir.opt_name(parent_hir_id)) + .map(|name| { + format!("future returned by `{}` is not {}", name, trait_name) + })?, + GeneratorKind::Async(AsyncGeneratorKind::Block) => { + format!("future created by async block is not {}", trait_name) + } + GeneratorKind::Async(AsyncGeneratorKind::Closure) => { + format!("future created by async closure is not {}", trait_name) + } + }) + }) + .unwrap_or_else(|| format!("{} is not {}", future_or_generator, trait_name)); span.push_span_label(original_span, message); err.set_span(span); @@ -1220,31 +1254,56 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { format!("does not implement `{}`", trait_ref.print_only_trait_path()) }; - // Look at the last interior type to get a span for the `.await`. - let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap(); - let mut span = MultiSpan::from_span(await_span); - span.push_span_label( - await_span, - format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet), - ); + if let Some(await_span) = from_awaited_ty { + // The type causing this obligation is one being awaited at await_span. + let mut span = MultiSpan::from_span(await_span); - span.push_span_label(target_span, format!("has type `{}`", target_ty)); + span.push_span_label( + await_span, + format!("await occurs here on type `{}`, which {}", target_ty, trait_explanation), + ); - // If available, use the scope span to annotate the drop location. - if let Some(scope_span) = scope_span { + err.span_note( + span, + &format!( + "future {not_trait} as it awaits another future which {not_trait}", + not_trait = trait_explanation + ), + ); + } else { + // Look at the last interior type to get a span for the `.await`. + debug!( + "note_obligation_cause_for_async_await generator_interior_types: {:#?}", + tables.generator_interior_types + ); + let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap(); + let mut span = MultiSpan::from_span(await_span); span.push_span_label( - source_map.end_point(*scope_span), - format!("`{}` is later dropped here", snippet), + await_span, + format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet), ); - } - err.span_note( - span, - &format!( - "future {} as this value is used across an {}", - trait_explanation, await_or_yield, - ), - ); + span.push_span_label( + target_span, + format!("has type `{}` which {}", target_ty, trait_explanation), + ); + + // If available, use the scope span to annotate the drop location. + if let Some(scope_span) = scope_span { + span.push_span_label( + source_map.end_point(*scope_span), + format!("`{}` is later dropped here", snippet), + ); + } + + err.span_note( + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), + ); + } if let Some(expr_id) = expr { let expr = hir.expect_expr(expr_id); @@ -1588,3 +1647,24 @@ impl<'v> Visitor<'v> for ReturnsVisitor<'v> { hir::intravisit::walk_body(self, body); } } + +/// Collect all the awaited expressions within the input expression. +#[derive(Default)] +struct AwaitsVisitor { + awaits: Vec, +} + +impl<'v> Visitor<'v> for AwaitsVisitor { + type Map = hir::intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { + hir::intravisit::NestedVisitorMap::None + } + + fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { + if let hir::ExprKind::Yield(_, hir::YieldSource::Await { expr: Some(id) }) = ex.kind { + self.awaits.push(id) + } + hir::intravisit::walk_expr(self, ex) + } +} diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 57e2349bb2e80..7cb51b4d6d833 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1797,7 +1797,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // we know that the yield type must be `()`; however, the context won't contain this // information. Hence, we check the source of the yield expression here and check its // value's type against `()` (this check should always hold). - None if src == &hir::YieldSource::Await => { + None if src.is_await() => { self.check_expr_coercable_to_type(&value, self.tcx.mk_unit()); self.tcx.mk_unit() } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index d1cb8e92d5688..706b388f78323 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1943,6 +1943,34 @@ impl<'a, K, V> Entry<'a, K, V> { } } + #[unstable(feature = "or_insert_with_key", issue = "71024")] + /// Ensures a value is in the entry by inserting, if empty, the result of the default function, + /// which takes the key as its argument, and returns a mutable reference to the value in the + /// entry. + /// + /// # Examples + /// + /// ``` + /// #![feature(or_insert_with_key)] + /// use std::collections::HashMap; + /// + /// let mut map: HashMap<&str, usize> = HashMap::new(); + /// + /// map.entry("poneyland").or_insert_with_key(|key| key.chars().count()); + /// + /// assert_eq!(map["poneyland"], 9); + /// ``` + #[inline] + pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { + match self { + Occupied(entry) => entry.into_mut(), + Vacant(entry) => { + let value = default(entry.key()); + entry.insert(value) + } + } + } + /// Returns a reference to this entry's key. /// /// # Examples diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index a9a519f0a3a71..dfb5177bf6725 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -523,6 +523,7 @@ pub use core::{ // Re-export built-in macros defined through libcore. #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow(deprecated)] pub use core::{ asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args, format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, log_syntax, diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 03686d789d721..92e3ea8485036 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -36,6 +36,7 @@ pub use crate::result::Result::{self, Err, Ok}; // Re-exported built-in macros #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[allow(deprecated)] #[doc(no_inline)] pub use core::prelude::v1::{ asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args, diff --git a/src/stdarch b/src/stdarch index 1a577bd78e84e..b00ecbeb268ee 160000 --- a/src/stdarch +++ b/src/stdarch @@ -1 +1 @@ -Subproject commit 1a577bd78e84e357e29c5336ff8beb432873046b +Subproject commit b00ecbeb268ee97cef9fa9b2375e6f6cf0864db2 diff --git a/src/test/mir-opt/array-index-is-temporary/32bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/array-index-is-temporary/32bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir index 052a335d00be6..0016cebbb4c06 100644 --- a/src/test/mir-opt/array-index-is-temporary/32bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/array-index-is-temporary/32bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir @@ -75,7 +75,7 @@ fn main() -> () { _7 = _2; // bb1[2]: scope 3 at $DIR/array-index-is-temporary.rs:16:7: 16:8 _8 = Len(_1); // bb1[3]: scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9 _9 = Lt(_7, _8); // bb1[4]: scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9 - assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2; // bb1[5]: scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9 + assert(move _9, "index out of bounds: the len is {} but the index is {}", move _8, _7) -> bb2; // bb1[5]: scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9 } bb2: { diff --git a/src/test/mir-opt/array-index-is-temporary/64bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/array-index-is-temporary/64bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir index e180f44969548..a004ab4a06aed 100644 --- a/src/test/mir-opt/array-index-is-temporary/64bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/array-index-is-temporary/64bit/rustc.main.SimplifyCfg-elaborate-drops.after.mir @@ -75,7 +75,7 @@ fn main() -> () { _7 = _2; // bb1[2]: scope 3 at $DIR/array-index-is-temporary.rs:16:7: 16:8 _8 = Len(_1); // bb1[3]: scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9 _9 = Lt(_7, _8); // bb1[4]: scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9 - assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2; // bb1[5]: scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9 + assert(move _9, "index out of bounds: the len is {} but the index is {}", move _8, _7) -> bb2; // bb1[5]: scope 3 at $DIR/array-index-is-temporary.rs:16:5: 16:9 } bb2: { diff --git a/src/test/mir-opt/combine_array_len/32bit/rustc.norm2.InstCombine.diff b/src/test/mir-opt/combine_array_len/32bit/rustc.norm2.InstCombine.diff index 7ec1c9ac637b3..1deeee0f61239 100644 --- a/src/test/mir-opt/combine_array_len/32bit/rustc.norm2.InstCombine.diff +++ b/src/test/mir-opt/combine_array_len/32bit/rustc.norm2.InstCombine.diff @@ -44,7 +44,7 @@ + // + span: $DIR/combine_array_len.rs:5:13: 5:17 + // + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) } _5 = Lt(_3, _4); // bb0[4]: scope 0 at $DIR/combine_array_len.rs:5:13: 5:17 - assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1; // bb0[5]: scope 0 at $DIR/combine_array_len.rs:5:13: 5:17 + assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // bb0[5]: scope 0 at $DIR/combine_array_len.rs:5:13: 5:17 } bb1: { @@ -68,7 +68,7 @@ + // + span: $DIR/combine_array_len.rs:6:13: 6:17 + // + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) } _9 = Lt(_7, _8); // bb1[6]: scope 1 at $DIR/combine_array_len.rs:6:13: 6:17 - assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2; // bb1[7]: scope 1 at $DIR/combine_array_len.rs:6:13: 6:17 + assert(move _9, "index out of bounds: the len is {} but the index is {}", move _8, _7) -> bb2; // bb1[7]: scope 1 at $DIR/combine_array_len.rs:6:13: 6:17 } bb2: { diff --git a/src/test/mir-opt/combine_array_len/64bit/rustc.norm2.InstCombine.diff b/src/test/mir-opt/combine_array_len/64bit/rustc.norm2.InstCombine.diff index 0bab28738d8ac..7120829e2b54a 100644 --- a/src/test/mir-opt/combine_array_len/64bit/rustc.norm2.InstCombine.diff +++ b/src/test/mir-opt/combine_array_len/64bit/rustc.norm2.InstCombine.diff @@ -44,7 +44,7 @@ + // + span: $DIR/combine_array_len.rs:5:13: 5:17 + // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) } _5 = Lt(_3, _4); // bb0[4]: scope 0 at $DIR/combine_array_len.rs:5:13: 5:17 - assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1; // bb0[5]: scope 0 at $DIR/combine_array_len.rs:5:13: 5:17 + assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // bb0[5]: scope 0 at $DIR/combine_array_len.rs:5:13: 5:17 } bb1: { @@ -68,7 +68,7 @@ + // + span: $DIR/combine_array_len.rs:6:13: 6:17 + // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) } _9 = Lt(_7, _8); // bb1[6]: scope 1 at $DIR/combine_array_len.rs:6:13: 6:17 - assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2; // bb1[7]: scope 1 at $DIR/combine_array_len.rs:6:13: 6:17 + assert(move _9, "index out of bounds: the len is {} but the index is {}", move _8, _7) -> bb2; // bb1[7]: scope 1 at $DIR/combine_array_len.rs:6:13: 6:17 } bb2: { diff --git a/src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff index f956ef82707bc..99d79b23e9e60 100644 --- a/src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff @@ -56,7 +56,7 @@ // + span: $DIR/array_index.rs:5:18: 5:33 // + literal: Const { ty: usize, val: Value(Scalar(0x00000004)) } - _5 = Lt(_3, _4); // bb0[6]: scope 0 at $DIR/array_index.rs:5:18: 5:33 -- assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1; // bb0[7]: scope 0 at $DIR/array_index.rs:5:18: 5:33 +- assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // bb0[7]: scope 0 at $DIR/array_index.rs:5:18: 5:33 + _5 = const true; // bb0[6]: scope 0 at $DIR/array_index.rs:5:18: 5:33 + // ty::Const + // + ty: bool @@ -64,7 +64,7 @@ + // mir::Constant + // + span: $DIR/array_index.rs:5:18: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is move _4 but the index is _3") -> bb1; // bb0[7]: scope 0 at $DIR/array_index.rs:5:18: 5:33 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // bb0[7]: scope 0 at $DIR/array_index.rs:5:18: 5:33 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) diff --git a/src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff index c336d6e66ae4d..629ca226f2ad6 100644 --- a/src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff @@ -56,7 +56,7 @@ // + span: $DIR/array_index.rs:5:18: 5:33 // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000004)) } - _5 = Lt(_3, _4); // bb0[6]: scope 0 at $DIR/array_index.rs:5:18: 5:33 -- assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1; // bb0[7]: scope 0 at $DIR/array_index.rs:5:18: 5:33 +- assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // bb0[7]: scope 0 at $DIR/array_index.rs:5:18: 5:33 + _5 = const true; // bb0[6]: scope 0 at $DIR/array_index.rs:5:18: 5:33 + // ty::Const + // + ty: bool @@ -64,7 +64,7 @@ + // mir::Constant + // + span: $DIR/array_index.rs:5:18: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is move _4 but the index is _3") -> bb1; // bb0[7]: scope 0 at $DIR/array_index.rs:5:18: 5:33 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // bb0[7]: scope 0 at $DIR/array_index.rs:5:18: 5:33 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff index d8bd397d74a65..41ffedf06bc98 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff @@ -119,7 +119,7 @@ // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 // + literal: Const { ty: usize, val: Value(Scalar(0x00000006)) } - _7 = Lt(_5, _6); // bb1[7]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 -- assert(move _7, "index out of bounds: the len is move _6 but the index is _5") -> bb2; // bb1[8]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 +- assert(move _7, "index out of bounds: the len is {} but the index is {}", move _6, _5) -> bb2; // bb1[8]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 + _7 = const true; // bb1[7]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 + // ty::Const + // + ty: bool @@ -127,7 +127,7 @@ + // mir::Constant + // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is move _6 but the index is _5") -> bb2; // bb1[8]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", move _6, _5) -> bb2; // bb1[8]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff index 9e646e7336d80..fd3281f527372 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff @@ -119,7 +119,7 @@ // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000006)) } - _7 = Lt(_5, _6); // bb1[7]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 -- assert(move _7, "index out of bounds: the len is move _6 but the index is _5") -> bb2; // bb1[8]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 +- assert(move _7, "index out of bounds: the len is {} but the index is {}", move _6, _5) -> bb2; // bb1[8]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 + _7 = const true; // bb1[7]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 + // ty::Const + // + ty: bool @@ -127,7 +127,7 @@ + // mir::Constant + // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is move _6 but the index is _5") -> bb2; // bb1[8]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", move _6, _5) -> bb2; // bb1[8]: scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) diff --git a/src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff index dce98d88e3d92..9d62fa31a4565 100644 --- a/src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff @@ -40,7 +40,7 @@ // + span: $DIR/repeat.rs:6:18: 6:28 // + literal: Const { ty: usize, val: Value(Scalar(0x00000008)) } - _6 = Lt(_4, _5); // bb0[7]: scope 0 at $DIR/repeat.rs:6:18: 6:28 -- assert(move _6, "index out of bounds: the len is move _5 but the index is _4") -> bb1; // bb0[8]: scope 0 at $DIR/repeat.rs:6:18: 6:28 +- assert(move _6, "index out of bounds: the len is {} but the index is {}", move _5, _4) -> bb1; // bb0[8]: scope 0 at $DIR/repeat.rs:6:18: 6:28 + _6 = const true; // bb0[7]: scope 0 at $DIR/repeat.rs:6:18: 6:28 + // ty::Const + // + ty: bool @@ -48,7 +48,7 @@ + // mir::Constant + // + span: $DIR/repeat.rs:6:18: 6:28 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is move _5 but the index is _4") -> bb1; // bb0[8]: scope 0 at $DIR/repeat.rs:6:18: 6:28 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", move _5, _4) -> bb1; // bb0[8]: scope 0 at $DIR/repeat.rs:6:18: 6:28 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) diff --git a/src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff index c9e640291f2f5..cb84ee82cfea8 100644 --- a/src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff @@ -40,7 +40,7 @@ // + span: $DIR/repeat.rs:6:18: 6:28 // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000008)) } - _6 = Lt(_4, _5); // bb0[7]: scope 0 at $DIR/repeat.rs:6:18: 6:28 -- assert(move _6, "index out of bounds: the len is move _5 but the index is _4") -> bb1; // bb0[8]: scope 0 at $DIR/repeat.rs:6:18: 6:28 +- assert(move _6, "index out of bounds: the len is {} but the index is {}", move _5, _4) -> bb1; // bb0[8]: scope 0 at $DIR/repeat.rs:6:18: 6:28 + _6 = const true; // bb0[7]: scope 0 at $DIR/repeat.rs:6:18: 6:28 + // ty::Const + // + ty: bool @@ -48,7 +48,7 @@ + // mir::Constant + // + span: $DIR/repeat.rs:6:18: 6:28 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is move _5 but the index is _4") -> bb1; // bb0[8]: scope 0 at $DIR/repeat.rs:6:18: 6:28 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", move _5, _4) -> bb1; // bb0[8]: scope 0 at $DIR/repeat.rs:6:18: 6:28 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) diff --git a/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff index 5f821078b75fd..dbb4171e7f0ed 100644 --- a/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff @@ -39,7 +39,7 @@ // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) } - _7 = Len((*_2)); // bb0[11]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 - _8 = Lt(_6, _7); // bb0[12]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 -- assert(move _8, "index out of bounds: the len is move _7 but the index is _6") -> bb1; // bb0[13]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 +- assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // bb0[13]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 + _7 = const 3usize; // bb0[11]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 + // ty::Const + // + ty: usize @@ -54,7 +54,7 @@ + // mir::Constant + // + span: $DIR/slice_len.rs:5:5: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is move _7 but the index is _6") -> bb1; // bb0[13]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // bb0[13]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) diff --git a/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff index 46f98b7f0aef8..3c4415e055838 100644 --- a/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff @@ -39,7 +39,7 @@ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) } - _7 = Len((*_2)); // bb0[11]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 - _8 = Lt(_6, _7); // bb0[12]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 -- assert(move _8, "index out of bounds: the len is move _7 but the index is _6") -> bb1; // bb0[13]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 +- assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // bb0[13]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 + _7 = const 3usize; // bb0[11]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 + // ty::Const + // + ty: usize @@ -54,7 +54,7 @@ + // mir::Constant + // + span: $DIR/slice_len.rs:5:5: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is move _7 but the index is _6") -> bb1; // bb0[13]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // bb0[13]: scope 0 at $DIR/slice_len.rs:5:5: 5:33 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) diff --git a/src/test/mir-opt/nll/region-subtyping-basic/32bit/rustc.main.nll.0.mir b/src/test/mir-opt/nll/region-subtyping-basic/32bit/rustc.main.nll.0.mir index f6ec2d925021e..1f75658aa265a 100644 --- a/src/test/mir-opt/nll/region-subtyping-basic/32bit/rustc.main.nll.0.mir +++ b/src/test/mir-opt/nll/region-subtyping-basic/32bit/rustc.main.nll.0.mir @@ -75,7 +75,7 @@ fn main() -> () { // + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) } _4 = Len(_1); // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18 _5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18 - assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18 + assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18 } bb1 (cleanup): { diff --git a/src/test/mir-opt/nll/region-subtyping-basic/64bit/rustc.main.nll.0.mir b/src/test/mir-opt/nll/region-subtyping-basic/64bit/rustc.main.nll.0.mir index fa3a9a0e1222a..8305c3fe7c493 100644 --- a/src/test/mir-opt/nll/region-subtyping-basic/64bit/rustc.main.nll.0.mir +++ b/src/test/mir-opt/nll/region-subtyping-basic/64bit/rustc.main.nll.0.mir @@ -75,7 +75,7 @@ fn main() -> () { // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) } _4 = Len(_1); // bb0[6]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18 _5 = Lt(_3, _4); // bb0[7]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18 - assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18 + assert(move _5, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> [success: bb2, unwind: bb1]; // bb0[8]: scope 1 at $DIR/region-subtyping-basic.rs:16:14: 16:18 } bb1 (cleanup): { diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 04df6203e43f1..d36d59f1f68f6 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:24:5 | LL | let x = non_send(); - | - has type `impl std::fmt::Debug` + | - has type `impl std::fmt::Debug` which is not `Send` LL | drop(x); LL | fut().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later @@ -33,7 +33,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:33:20 | LL | match Some(non_send()) { - | ---------- has type `impl std::fmt::Debug` + | ---------- has type `impl std::fmt::Debug` which is not `Send` LL | Some(_) => fut().await, | ^^^^^^^^^^^ await occurs here, with `non_send()` maybe used later ... @@ -54,7 +54,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:42:9 | LL | let f: &mut std::fmt::Formatter = panic!(); - | - has type `&mut std::fmt::Formatter<'_>` + | - has type `&mut std::fmt::Formatter<'_>` which is not `Send` LL | if non_sync().fmt(f).unwrap() == () { LL | fut().await; | ^^^^^^^^^^^ await occurs here, with `f` maybe used later diff --git a/src/test/ui/async-await/issue-64130-1-sync.stderr b/src/test/ui/async-await/issue-64130-1-sync.stderr index b7a88c10e7411..42e9e4642cea5 100644 --- a/src/test/ui/async-await/issue-64130-1-sync.stderr +++ b/src/test/ui/async-await/issue-64130-1-sync.stderr @@ -12,7 +12,7 @@ note: future is not `Sync` as this value is used across an await --> $DIR/issue-64130-1-sync.rs:15:5 | LL | let x = Foo; - | - has type `Foo` + | - has type `Foo` which is not `Sync` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-64130-2-send.stderr b/src/test/ui/async-await/issue-64130-2-send.stderr index ec18308877177..f6f834618d36f 100644 --- a/src/test/ui/async-await/issue-64130-2-send.stderr +++ b/src/test/ui/async-await/issue-64130-2-send.stderr @@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-2-send.rs:15:5 | LL | let x = Foo; - | - has type `Foo` + | - has type `Foo` which is not `Send` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-64130-3-other.stderr b/src/test/ui/async-await/issue-64130-3-other.stderr index 6b40cc9184df0..3475b66b375dd 100644 --- a/src/test/ui/async-await/issue-64130-3-other.stderr +++ b/src/test/ui/async-await/issue-64130-3-other.stderr @@ -16,7 +16,7 @@ note: future does not implement `Qux` as this value is used across an await --> $DIR/issue-64130-3-other.rs:18:5 | LL | let x = Foo; - | - has type `Foo` + | - has type `Foo` which does not implement `Qux` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `x` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-64130-4-async-move.stderr b/src/test/ui/async-await/issue-64130-4-async-move.stderr index 1e52d74f1559c..fc231d394c11f 100644 --- a/src/test/ui/async-await/issue-64130-4-async-move.stderr +++ b/src/test/ui/async-await/issue-64130-4-async-move.stderr @@ -2,7 +2,7 @@ error: future cannot be sent between threads safely --> $DIR/issue-64130-4-async-move.rs:15:17 | LL | pub fn foo() -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` + | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` ... LL | / async move { LL | | match client.status() { @@ -18,7 +18,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-4-async-move.rs:21:26 | LL | match client.status() { - | ------ has type `&Client` + | ------ has type `&Client` which is not `Send` LL | 200 => { LL | let _x = get().await; | ^^^^^^^^^^^ await occurs here, with `client` maybe used later diff --git a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr index 0f4441edb1385..f72757339cc5e 100644 --- a/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/src/test/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -12,7 +12,7 @@ note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-non-send-future-diags.rs:15:5 | LL | let g = x.lock().unwrap(); - | - has type `std::sync::MutexGuard<'_, u32>` + | - has type `std::sync::MutexGuard<'_, u32>` which is not `Send` LL | baz().await; | ^^^^^^^^^^^ await occurs here, with `g` maybe used later LL | } diff --git a/src/test/ui/async-await/issue-67252-unnamed-future.stderr b/src/test/ui/async-await/issue-67252-unnamed-future.stderr index cbcc3cf5d78a7..b43478ee2070b 100644 --- a/src/test/ui/async-await/issue-67252-unnamed-future.stderr +++ b/src/test/ui/async-await/issue-67252-unnamed-future.stderr @@ -5,14 +5,14 @@ LL | fn spawn(_: T) {} | ---- required by this bound in `spawn` ... LL | spawn(async { - | ^^^^^ future is not `Send` + | ^^^^^ future created by async block is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `*mut ()` note: future is not `Send` as this value is used across an await --> $DIR/issue-67252-unnamed-future.rs:20:9 | LL | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` - | -- has type `*mut ()` + | -- has type `*mut ()` which is not `Send` LL | AFuture.await; | ^^^^^^^^^^^^^ await occurs here, with `_a` maybe used later LL | }); diff --git a/src/test/ui/async-await/issue-68112.rs b/src/test/ui/async-await/issue-68112.rs new file mode 100644 index 0000000000000..11b1783680807 --- /dev/null +++ b/src/test/ui/async-await/issue-68112.rs @@ -0,0 +1,64 @@ +// edition:2018 + +use std::{ + future::Future, + cell::RefCell, + sync::Arc, + pin::Pin, + task::{Context, Poll}, +}; + +fn require_send(_: impl Send) {} + +struct Ready(Option); +impl Future for Ready { + type Output = T; + fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Ready(self.0.take().unwrap()) + } +} +fn ready(t: T) -> Ready { + Ready(Some(t)) +} + +fn make_non_send_future1() -> impl Future>> { + ready(Arc::new(RefCell::new(0))) +} + +fn test1() { + let send_fut = async { + let non_send_fut = make_non_send_future1(); + let _ = non_send_fut.await; + ready(0).await; + }; + require_send(send_fut); + //~^ ERROR future cannot be sent between threads +} + +fn test1_no_let() { + let send_fut = async { + let _ = make_non_send_future1().await; + ready(0).await; + }; + require_send(send_fut); + //~^ ERROR future cannot be sent between threads +} + +async fn ready2(t: T) -> T { t } +fn make_non_send_future2() -> impl Future>> { + ready2(Arc::new(RefCell::new(0))) +} + +// Ideally this test would have diagnostics similar to the test above, but right +// now it doesn't. +fn test2() { + let send_fut = async { + let non_send_fut = make_non_send_future2(); + let _ = non_send_fut.await; + ready(0).await; + }; + require_send(send_fut); + //~^ ERROR `std::cell::RefCell` cannot be shared between threads safely +} + +fn main() {} diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr new file mode 100644 index 0000000000000..78462868ede53 --- /dev/null +++ b/src/test/ui/async-await/issue-68112.stderr @@ -0,0 +1,56 @@ +error: future cannot be sent between threads safely + --> $DIR/issue-68112.rs:34:5 + | +LL | fn require_send(_: impl Send) {} + | ------------ ---- required by this bound in `require_send` +... +LL | require_send(send_fut); + | ^^^^^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/issue-68112.rs:31:17 + | +LL | let _ = non_send_fut.await; + | ^^^^^^^^^^^^ await occurs here on type `impl std::future::Future`, which is not `Send` + +error: future cannot be sent between threads safely + --> $DIR/issue-68112.rs:43:5 + | +LL | fn require_send(_: impl Send) {} + | ------------ ---- required by this bound in `require_send` +... +LL | require_send(send_fut); + | ^^^^^^^^^^^^ future created by async block is not `Send` + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` +note: future is not `Send` as it awaits another future which is not `Send` + --> $DIR/issue-68112.rs:40:17 + | +LL | let _ = make_non_send_future1().await; + | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl std::future::Future`, which is not `Send` + +error[E0277]: `std::cell::RefCell` cannot be shared between threads safely + --> $DIR/issue-68112.rs:60:5 + | +LL | fn require_send(_: impl Send) {} + | ------------ ---- required by this bound in `require_send` +... +LL | require_send(send_fut); + | ^^^^^^^^^^^^ `std::cell::RefCell` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` + = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc>` + = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36 t:std::sync::Arc> {}]` + = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36 t:std::sync::Arc> {}]>` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `impl std::future::Future` + = note: required because it appears within the type `{std::future::ResumeTy, impl std::future::Future, (), i32, Ready}` + = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6 {std::future::ResumeTy, impl std::future::Future, (), i32, Ready}]` + = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6 {std::future::ResumeTy, impl std::future::Future, (), i32, Ready}]>` + = note: required because it appears within the type `impl std::future::Future` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr index 73e2a92d815c8..49cd30e11a0c1 100644 --- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr +++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr @@ -5,7 +5,7 @@ LL | fn assert_send(_: T) {} | ---- required by this bound in `assert_send` ... LL | assert_send(async { - | ^^^^^^^^^^^ future returned by `main` is not `Send` + | ^^^^^^^^^^^ future created by async block is not `Send` | = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `*const u8` note: future is not `Send` as this value is used across an await @@ -14,7 +14,7 @@ note: future is not `Send` as this value is used across an await LL | bar(Foo(std::ptr::null())).await; | ^^^^^^^^----------------^^^^^^^^- `std::ptr::null()` is later dropped here | | | - | | has type `*const u8` + | | has type `*const u8` which is not `Send` | await occurs here, with `std::ptr::null()` maybe used later help: consider moving this into a `let` binding to create a shorter lived borrow --> $DIR/issue-65436-raw-ptr-not-send.rs:14:13 diff --git a/src/test/ui/char_unicode.rs b/src/test/ui/char_unicode.rs index 93e5300e36fe9..8d28f0080dd56 100644 --- a/src/test/ui/char_unicode.rs +++ b/src/test/ui/char_unicode.rs @@ -7,6 +7,6 @@ pub fn main() { check(std::char::UNICODE_VERSION); } -pub fn check(unicode_version: std::char::UnicodeVersion) { - assert!(unicode_version.major >= 10); +pub fn check(unicode_version: (u8, u8, u8)) { + assert!(unicode_version.0 >= 10); } diff --git a/src/test/ui/feature-gates/feature-gate-asm.rs b/src/test/ui/feature-gates/feature-gate-asm.rs index 7eeeb4bc4e243..70f5845550d17 100644 --- a/src/test/ui/feature-gates/feature-gate-asm.rs +++ b/src/test/ui/feature-gates/feature-gate-asm.rs @@ -3,6 +3,7 @@ fn main() { unsafe { asm!(""); //~ ERROR inline assembly is not stable enough + //~^ WARN use of deprecated item 'asm' llvm_asm!(""); //~ ERROR inline assembly is not stable enough } } diff --git a/src/test/ui/feature-gates/feature-gate-asm.stderr b/src/test/ui/feature-gates/feature-gate-asm.stderr index 1f9eaa5632e4a..516518b5200bf 100644 --- a/src/test/ui/feature-gates/feature-gate-asm.stderr +++ b/src/test/ui/feature-gates/feature-gate-asm.stderr @@ -8,7 +8,7 @@ LL | asm!(""); = help: add `#![feature(asm)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'llvm_asm': inline assembly is not stable enough for use and is subject to change - --> $DIR/feature-gate-asm.rs:6:9 + --> $DIR/feature-gate-asm.rs:7:9 | LL | llvm_asm!(""); | ^^^^^^^^ @@ -16,6 +16,14 @@ LL | llvm_asm!(""); = note: see issue #70173 for more information = help: add `#![feature(llvm_asm)]` to the crate attributes to enable +warning: use of deprecated item 'asm': the syntax of asm! will change soon, use llvm_asm! to avoid breakage + --> $DIR/feature-gate-asm.rs:5:9 + | +LL | asm!(""); + | ^^^ help: replace the use of the deprecated item: `llvm_asm` + | + = note: `#[warn(deprecated)]` on by default + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-asm2.rs b/src/test/ui/feature-gates/feature-gate-asm2.rs index 666a4894f6275..e3e86592a480a 100644 --- a/src/test/ui/feature-gates/feature-gate-asm2.rs +++ b/src/test/ui/feature-gates/feature-gate-asm2.rs @@ -3,6 +3,7 @@ fn main() { unsafe { println!("{:?}", asm!("")); //~ ERROR inline assembly is not stable + //~^ WARN use of deprecated item 'asm' println!("{:?}", llvm_asm!("")); //~ ERROR inline assembly is not stable } } diff --git a/src/test/ui/feature-gates/feature-gate-asm2.stderr b/src/test/ui/feature-gates/feature-gate-asm2.stderr index 17ba66e9842fa..43b5f7329652e 100644 --- a/src/test/ui/feature-gates/feature-gate-asm2.stderr +++ b/src/test/ui/feature-gates/feature-gate-asm2.stderr @@ -8,7 +8,7 @@ LL | println!("{:?}", asm!("")); = help: add `#![feature(asm)]` to the crate attributes to enable error[E0658]: use of unstable library feature 'llvm_asm': inline assembly is not stable enough for use and is subject to change - --> $DIR/feature-gate-asm2.rs:6:26 + --> $DIR/feature-gate-asm2.rs:7:26 | LL | println!("{:?}", llvm_asm!("")); | ^^^^^^^^ @@ -16,6 +16,14 @@ LL | println!("{:?}", llvm_asm!("")); = note: see issue #70173 for more information = help: add `#![feature(llvm_asm)]` to the crate attributes to enable +warning: use of deprecated item 'asm': the syntax of asm! will change soon, use llvm_asm! to avoid breakage + --> $DIR/feature-gate-asm2.rs:5:26 + | +LL | println!("{:?}", asm!("")); + | ^^^ help: replace the use of the deprecated item: `llvm_asm` + | + = note: `#[warn(deprecated)]` on by default + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generator/issue-68112.rs b/src/test/ui/generator/issue-68112.rs new file mode 100644 index 0000000000000..9ab2abf740572 --- /dev/null +++ b/src/test/ui/generator/issue-68112.rs @@ -0,0 +1,56 @@ +#![feature(generators, generator_trait)] + +use std::{ + cell::RefCell, + sync::Arc, + pin::Pin, + ops::{Generator, GeneratorState}, +}; + +pub struct Ready(Option); +impl Generator<()> for Ready { + type Return = T; + type Yield = (); + fn resume(mut self: Pin<&mut Self>, _args: ()) -> GeneratorState<(), T> { + GeneratorState::Complete(self.0.take().unwrap()) + } +} +pub fn make_gen1(t: T) -> Ready { + Ready(Some(t)) +} + +fn require_send(_: impl Send) {} + +fn make_non_send_generator() -> impl Generator>> { + make_gen1(Arc::new(RefCell::new(0))) +} + +fn test1() { + let send_gen = || { + let _non_send_gen = make_non_send_generator(); + yield; + }; + require_send(send_gen); + //~^ ERROR generator cannot be sent between threads +} + +pub fn make_gen2(t: T) -> impl Generator { + || { + yield; + t + } +} +fn make_non_send_generator2() -> impl Generator>> { + make_gen2(Arc::new(RefCell::new(0))) +} + +fn test2() { + let send_gen = || { + let _non_send_gen = make_non_send_generator2(); + yield; + }; + require_send(send_gen); + //~^ ERROR `std::cell::RefCell` cannot be shared between threads safely +} + +fn main() {} diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr new file mode 100644 index 0000000000000..4148b503ba858 --- /dev/null +++ b/src/test/ui/generator/issue-68112.stderr @@ -0,0 +1,40 @@ +error: generator cannot be sent between threads safely + --> $DIR/issue-68112.rs:33:5 + | +LL | fn require_send(_: impl Send) {} + | ------------ ---- required by this bound in `require_send` +... +LL | require_send(send_gen); + | ^^^^^^^^^^^^ generator is not `Send` + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` +note: generator is not `Send` as this value is used across a yield + --> $DIR/issue-68112.rs:31:9 + | +LL | let _non_send_gen = make_non_send_generator(); + | ------------- has type `impl std::ops::Generator` which is not `Send` +LL | yield; + | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later +LL | }; + | - `_non_send_gen` is later dropped here + +error[E0277]: `std::cell::RefCell` cannot be shared between threads safely + --> $DIR/issue-68112.rs:52:5 + | +LL | fn require_send(_: impl Send) {} + | ------------ ---- required by this bound in `require_send` +... +LL | require_send(send_gen); + | ^^^^^^^^^^^^ `std::cell::RefCell` cannot be shared between threads safely + | + = help: the trait `std::marker::Sync` is not implemented for `std::cell::RefCell` + = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc>` + = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6 t:std::sync::Arc> {()}]` + = note: required because it appears within the type `impl std::ops::Generator` + = note: required because it appears within the type `impl std::ops::Generator` + = note: required because it appears within the type `{impl std::ops::Generator, ()}` + = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6 {impl std::ops::Generator, ()}]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/generator/not-send-sync.rs b/src/test/ui/generator/not-send-sync.rs index 0db01c6f756ac..8ca5565fb2ab5 100644 --- a/src/test/ui/generator/not-send-sync.rs +++ b/src/test/ui/generator/not-send-sync.rs @@ -7,7 +7,7 @@ fn main() { fn assert_send(_: T) {} assert_sync(|| { - //~^ ERROR: future cannot be shared between threads safely + //~^ ERROR: generator cannot be shared between threads safely let a = Cell::new(2); yield; }); diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 5f5211b5092f4..5df2c1b52fb8a 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -11,21 +11,21 @@ LL | assert_send(|| { = note: required because of the requirements on the impl of `std::marker::Send` for `&std::cell::Cell` = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6 a:&std::cell::Cell _]` -error: future cannot be shared between threads safely +error: generator cannot be shared between threads safely --> $DIR/not-send-sync.rs:9:5 | LL | fn assert_sync(_: T) {} | ---- required by this bound in `main::assert_sync` ... LL | assert_sync(|| { - | ^^^^^^^^^^^ future returned by `main` is not `Sync` + | ^^^^^^^^^^^ generator is not `Sync` | = help: within `[generator@$DIR/not-send-sync.rs:9:17: 13:6 {std::cell::Cell, ()}]`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell` -note: future is not `Sync` as this value is used across an yield +note: generator is not `Sync` as this value is used across a yield --> $DIR/not-send-sync.rs:12:9 | LL | let a = Cell::new(2); - | - has type `std::cell::Cell` + | - has type `std::cell::Cell` which is not `Sync` LL | yield; | ^^^^^ yield occurs here, with `a` maybe used later LL | }); diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index d5562ff91df4d..6f73b172feae3 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -295,7 +295,7 @@ fn main() { fn version() -> String { let mut out = String::new(); - out.push_str("pub const UNICODE_VERSION: (u32, u32, u32) = "); + out.push_str("pub const UNICODE_VERSION: (u8, u8, u8) = "); let readme = std::fs::read_to_string(std::path::Path::new(UNICODE_DIRECTORY).join("ReadMe.txt"))