diff options
113 files changed, 1317 insertions, 525 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index cd6614a54a4..211f5cb0a2a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -58,7 +58,7 @@ use rustc_errors::{ use rustc_fluent_macro::fluent_messages; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; -use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::DefPathData; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::{Idx, IndexSlice, IndexVec}; @@ -435,6 +435,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { // Queries that borrow `resolver_for_lowering`. tcx.ensure_with_value().output_filenames(()); tcx.ensure_with_value().early_lint_checks(()); + tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE); let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal(); let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 2a3092d3c7b..372a58857f3 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -23,8 +23,7 @@ use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause}; pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION"; pub fn rust_version_symbol() -> Symbol { - let version = option_env!("CFG_VERSION").unwrap_or("<current>"); - let version = version.split(' ').next().unwrap(); + let version = option_env!("CFG_RELEASE").unwrap_or("<current>"); Symbol::intern(&version) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index aaf5dbd9930..37f30917609 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -9,10 +9,9 @@ use rustc_ast::attr; use rustc_codegen_ssa::base::collect_debugger_visualizers_transitive; use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_middle::bug; +use rustc_middle::{bug, middle::debugger_visualizer::DebuggerVisualizerType}; use rustc_session::config::{CrateType, DebugInfo}; use rustc_span::symbol::sym; -use rustc_span::DebuggerVisualizerType; /// Inserts a side-effect free instruction sequence that makes sure that the /// .debug_gdb_scripts global is referenced, so it isn't removed by the linker. diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 25fe3cb265d..bd2fba12602 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -806,8 +806,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( name_in_debuginfo.push(codegen_unit_name); debug!("build_compile_unit_di_node: {:?}", name_in_debuginfo); - let rustc_producer = - format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"),); + let rustc_producer = format!("rustc version {}", tcx.sess.cfg_version); // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice. let producer = format!("clang LLVM ({})", rustc_producer); diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ea06cb02d8b..d1a2e705498 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -9,6 +9,7 @@ use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::find_native_static_library; use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME}; +use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip}; @@ -21,7 +22,6 @@ use rustc_session::utils::NativeLibKind; /// need out of the shared crate context before we get rid of it. use rustc_session::{filesearch, Session}; use rustc_span::symbol::Symbol; -use rustc_span::DebuggerVisualizerFile; use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault}; use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy}; use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo}; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index d9b0a152594..15c7847155d 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -23,6 +23,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; use rustc_metadata::EncodedMetadata; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; +use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}; use rustc_middle::middle::exported_symbols; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_middle::middle::lang_items; @@ -35,7 +36,6 @@ use rustc_session::config::{self, CrateType, EntryFnType, OutputType}; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::Symbol; -use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType}; use rustc_target::abi::{Align, FIRST_VARIANT}; use std::collections::BTreeSet; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index f4b9d1dea58..31854c7f4c4 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -28,6 +28,7 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_fluent_macro::fluent_messages; use rustc_hir::def_id::CrateNum; use rustc_middle::dep_graph::WorkProduct; +use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_middle::query::{ExternProviders, Providers}; @@ -36,8 +37,8 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::cstore::{self, CrateSource}; use rustc_session::utils::NativeLibKind; +use rustc_session::Session; use rustc_span::symbol::Symbol; -use rustc_span::DebuggerVisualizerFile; use std::collections::BTreeSet; use std::io; use std::path::{Path, PathBuf}; @@ -175,11 +176,11 @@ pub struct CodegenResults { pub crate_info: CrateInfo, } -pub enum CodegenErrors<'a> { +pub enum CodegenErrors { WrongFileType, EmptyVersionNumber, EncodingVersionMismatch { version_array: String, rlink_version: u32 }, - RustcVersionMismatch { rustc_version: String, current_version: &'a str }, + RustcVersionMismatch { rustc_version: String }, } pub fn provide(providers: &mut Providers) { @@ -213,10 +214,9 @@ pub fn looks_like_rust_object_file(filename: &str) -> bool { const RLINK_VERSION: u32 = 1; const RLINK_MAGIC: &[u8] = b"rustlink"; -const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION"); - impl CodegenResults { pub fn serialize_rlink( + sess: &Session, rlink_file: &Path, codegen_results: &CodegenResults, ) -> Result<usize, io::Error> { @@ -225,12 +225,12 @@ impl CodegenResults { // `emit_raw_bytes` is used to make sure that the version representation does not depend on // Encoder's inner representation of `u32`. encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes()); - encoder.emit_str(RUSTC_VERSION.unwrap()); + encoder.emit_str(sess.cfg_version); Encodable::encode(codegen_results, &mut encoder); encoder.finish() } - pub fn deserialize_rlink<'a>(data: Vec<u8>) -> Result<Self, CodegenErrors<'a>> { + pub fn deserialize_rlink(sess: &Session, data: Vec<u8>) -> Result<Self, CodegenErrors> { // The Decodable machinery is not used here because it panics if the input data is invalid // and because its internal representation may change. if !data.starts_with(RLINK_MAGIC) { @@ -252,11 +252,9 @@ impl CodegenResults { let mut decoder = MemDecoder::new(&data[4..], 0); let rustc_version = decoder.read_str(); - let current_version = RUSTC_VERSION.unwrap(); - if rustc_version != current_version { + if rustc_version != sess.cfg_version { return Err(CodegenErrors::RustcVersionMismatch { rustc_version: rustc_version.to_string(), - current_version, }); } diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index a7de709ba72..594ed1ad2e7 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -109,28 +109,27 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> { // they have been placed in the bucket. // // We compute a partial set of immediate dominators here. - let z = parent[w]; - for &v in bucket[z].iter() { + for &v in bucket[w].iter() { // This uses the result of Lemma 5 from section 2 from the original // 1979 paper, to compute either the immediate or relative dominator // for a given vertex v. // // eval returns a vertex y, for which semi[y] is minimum among - // vertices semi[v] +> y *> v. Note that semi[v] = z as we're in the - // z bucket. + // vertices semi[v] +> y *> v. Note that semi[v] = w as we're in the + // w bucket. // // Given such a vertex y, semi[y] <= semi[v] and idom[y] = idom[v]. // If semi[y] = semi[v], though, idom[v] = semi[v]. // // Using this, we can either set idom[v] to be: - // * semi[v] (i.e. z), if semi[y] is z + // * semi[v] (i.e. w), if semi[y] is w // * idom[y], otherwise // // We don't directly set to idom[y] though as it's not necessarily // known yet. The second preorder traversal will cleanup by updating // the idom for any that were missed in this pass. let y = eval(&mut parent, lastlinked, &semi, &mut label, v); - idom[v] = if semi[y] < z { y } else { z }; + idom[v] = if semi[y] < w { y } else { w }; } // This loop computes the semi[w] for w. @@ -213,10 +212,11 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> { // If we don't yet know the idom directly, then push this vertex into // our semidominator's bucket, where it will get processed at a later // stage to compute its immediate dominator. - if parent[w] != semi[w] { + let z = parent[w]; + if z != semi[w] { bucket[semi[w]].push(w); } else { - idom[w] = parent[w]; + idom[w] = z; } // Optimization: We share the parent array between processed and not diff --git a/compiler/rustc_data_structures/src/graph/dominators/tests.rs b/compiler/rustc_data_structures/src/graph/dominators/tests.rs index 8b124516623..5472bb8087e 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/tests.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/tests.rs @@ -53,3 +53,30 @@ fn immediate_dominator() { assert_eq!(dominators.immediate_dominator(2), Some(1)); assert_eq!(dominators.immediate_dominator(3), Some(2)); } + +#[test] +fn transitive_dominator() { + let graph = TestGraph::new( + 0, + &[ + // First tree branch. + (0, 1), + (1, 2), + (2, 3), + (3, 4), + // Second tree branch. + (1, 5), + (5, 6), + // Third tree branch. + (0, 7), + // These links make 0 the dominator for 2 and 3. + (7, 2), + (5, 3), + ], + ); + + let dom_tree = dominators(&graph); + let immediate_dominators = &dom_tree.immediate_dominators; + assert_eq!(immediate_dominators[2], Some(0)); + assert_eq!(immediate_dominators[3], Some(0)); // This used to return Some(1). +} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index cf2ab3c2d2a..6c204b894a6 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -572,7 +572,7 @@ pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Comp let rlink_data = fs::read(file).unwrap_or_else(|err| { sess.emit_fatal(RlinkUnableToRead { err }); }); - let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) { + let codegen_results = match CodegenResults::deserialize_rlink(sess, rlink_data) { Ok(codegen) => codegen, Err(err) => { match err { @@ -586,10 +586,10 @@ pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Comp rlink_version, }) } - CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => { + CodegenErrors::RustcVersionMismatch { rustc_version } => { sess.emit_fatal(RLinkRustcVersionMismatch { rustc_version, - current_version, + current_version: sess.cfg_version, }) } }; @@ -1250,7 +1250,8 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler)) #[cfg(windows)] if let Some(msg) = info.payload().downcast_ref::<String>() { if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") { - early_error_no_abort(ErrorOutputType::default(), msg.as_str()); + // the error code is already going to be reported when the panic unwinds up the stack + let _ = early_error_no_abort(ErrorOutputType::default(), msg.as_str()); return; } }; diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 0f360473619..d5855527242 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1740,7 +1740,7 @@ impl DelayedDiagnostic { } fn decorate(mut self) -> Diagnostic { - self.inner.note(format!("delayed at {}", self.note)); + self.inner.note(format!("delayed at {}\n{}", self.inner.emitted_at, self.note)); self.inner } } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 1f77e687bb1..5d369a1879a 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -722,7 +722,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }); } }; - if fragment_kind == AstFragmentKind::Expr && items.is_empty() { + if matches!( + fragment_kind, + AstFragmentKind::Expr | AstFragmentKind::MethodReceiverExpr + ) && items.is_empty() + { self.cx.emit_err(RemoveExprNotSupported { span }); fragment_kind.dummy(span) } else { diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs index c7ac01b3334..a40a0178710 100644 --- a/compiler/rustc_hir/src/tests.rs +++ b/compiler/rustc_hir/src/tests.rs @@ -10,13 +10,13 @@ fn def_path_hash_depends_on_crate_id() { // the crate-id of the defining crate. This is a desirable property // because the crate-id can be more easily changed than the DefPath // of an item, so, in the case of a crate-local DefPathHash collision, - // the user can simply "role the dice again" for all DefPathHashes in + // the user can simply "roll the dice again" for all DefPathHashes in // the crate by changing the crate disambiguator (e.g. via bumping the // crate's version number). create_session_if_not_set_then(Edition::Edition2024, |_| { - let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]); - let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]); + let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], ""); + let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], ""); let h0 = mk_test_hash(id0); let h1 = mk_test_hash(id1); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 940ed7349c4..adc1b090af6 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -721,7 +721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // ICE this expression in particular (see #43162). if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind { if path.segments.len() == 1 && path.segments[0].ident.name == sym::rust { - fatally_break_rust(self.tcx.sess); + fatally_break_rust(self.tcx); } } } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 54b222ade03..64426c4cbbb 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -72,7 +72,6 @@ use rustc_middle::query::Providers; use rustc_middle::traits; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::config; -use rustc_session::Session; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::{sym, Span}; @@ -438,8 +437,8 @@ enum TupleArgumentsFlag { TupleArguments, } -fn fatally_break_rust(sess: &Session) { - let handler = sess.diagnostic(); +fn fatally_break_rust(tcx: TyCtxt<'_>) { + let handler = tcx.sess.diagnostic(); handler.span_bug_no_panic( MultiSpan::new(), "It looks like you're trying to break rust; would you like some ICE?", @@ -451,7 +450,7 @@ fn fatally_break_rust(sess: &Session) { ); handler.note_without_error(format!( "rustc {} running on {}", - option_env!("CFG_VERSION").unwrap_or("unknown_version"), + tcx.sess.cfg_version, config::host_triple(), )); } diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index dc981c6179e..25bf83f64a0 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -14,6 +14,7 @@ use rustc_data_structures::memmap::Mmap; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::Encoder; use rustc_session::Session; +use std::borrow::Cow; use std::env; use std::fs; use std::io::{self, Read}; @@ -25,17 +26,12 @@ const FILE_MAGIC: &[u8] = b"RSIC"; /// Change this if the header format changes. const HEADER_FORMAT_VERSION: u16 = 0; -/// A version string that hopefully is always different for compiler versions -/// with different encodings of incremental compilation artifacts. Contains -/// the Git commit hash. -const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION"); - -pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) { +pub(crate) fn write_file_header(stream: &mut FileEncoder, sess: &Session) { stream.emit_raw_bytes(FILE_MAGIC); stream .emit_raw_bytes(&[(HEADER_FORMAT_VERSION >> 0) as u8, (HEADER_FORMAT_VERSION >> 8) as u8]); - let rustc_version = rustc_version(nightly_build); + let rustc_version = rustc_version(sess.is_nightly_build(), sess.cfg_version); assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize); stream.emit_raw_bytes(&[rustc_version.len() as u8]); stream.emit_raw_bytes(rustc_version.as_bytes()); @@ -73,7 +69,7 @@ where } }; - write_file_header(&mut encoder, sess.is_nightly_build()); + write_file_header(&mut encoder, sess); match encode(encoder) { Ok(position) => { @@ -100,9 +96,10 @@ where /// - Returns `Err(..)` if some kind of IO error occurred while reading the /// file. pub fn read_file( - report_incremental_info: bool, path: &Path, - nightly_build: bool, + report_incremental_info: bool, + is_nightly_build: bool, + cfg_version: &'static str, ) -> io::Result<Option<(Mmap, usize)>> { let file = match fs::File::open(path) { Ok(file) => file, @@ -152,7 +149,7 @@ pub fn read_file( let mut buffer = vec![0; rustc_version_str_len]; file.read_exact(&mut buffer)?; - if buffer != rustc_version(nightly_build).as_bytes() { + if buffer != rustc_version(is_nightly_build, cfg_version).as_bytes() { report_format_mismatch(report_incremental_info, path, "Different compiler version"); return Ok(None); } @@ -174,17 +171,15 @@ fn report_format_mismatch(report_incremental_info: bool, file: &Path, message: & } } -fn rustc_version(nightly_build: bool) -> String { +/// A version string that hopefully is always different for compiler versions +/// with different encodings of incremental compilation artifacts. Contains +/// the Git commit hash. +fn rustc_version(nightly_build: bool, cfg_version: &'static str) -> Cow<'static, str> { if nightly_build { - if let Some(val) = env::var_os("RUSTC_FORCE_RUSTC_VERSION") { - return val.to_string_lossy().into_owned(); + if let Ok(val) = env::var("RUSTC_FORCE_RUSTC_VERSION") { + return val.into(); } } - RUSTC_VERSION - .expect( - "Cannot use rustc without explicit version for \ - incremental compilation", - ) - .to_string() + cfg_version.into() } diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index ec7fcbdf884..a4407a93ff3 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -73,12 +73,22 @@ impl<T: Default> LoadResult<T> { } } -fn load_data( - report_incremental_info: bool, +fn load_data(path: &Path, sess: &Session) -> LoadResult<(Mmap, usize)> { + load_data_no_sess( + path, + sess.opts.unstable_opts.incremental_info, + sess.is_nightly_build(), + sess.cfg_version, + ) +} + +fn load_data_no_sess( path: &Path, - nightly_build: bool, + report_incremental_info: bool, + is_nightly_build: bool, + cfg_version: &'static str, ) -> LoadResult<(Mmap, usize)> { - match file_format::read_file(report_incremental_info, path, nightly_build) { + match file_format::read_file(path, report_incremental_info, is_nightly_build, cfg_version) { Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos }, Ok(None) => { // The file either didn't exist or was produced by an incompatible @@ -138,14 +148,13 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { let expected_hash = sess.opts.dep_tracking_hash(false); let mut prev_work_products = FxHashMap::default(); - let nightly_build = sess.is_nightly_build(); // If we are only building with -Zquery-dep-graph but without an actual // incr. comp. session directory, we skip this. Otherwise we'd fail // when trying to load work products. if sess.incr_comp_session_dir_opt().is_some() { let work_products_path = work_products_path(sess); - let load_result = load_data(report_incremental_info, &work_products_path, nightly_build); + let load_result = load_data(&work_products_path, sess); if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result { // Decode the list of work_products @@ -173,10 +182,13 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { } } + let is_nightly_build = sess.is_nightly_build(); + let cfg_version = sess.cfg_version; + MaybeAsync::Async(std::thread::spawn(move || { let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph"); - match load_data(report_incremental_info, &path, nightly_build) { + match load_data_no_sess(&path, report_incremental_info, is_nightly_build, cfg_version) { LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err), LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err), @@ -218,11 +230,7 @@ pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache<'_>> { let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache"); - match load_data( - sess.opts.unstable_opts.incremental_info, - &query_cache_path(sess), - sess.is_nightly_build(), - ) { + match load_data(&query_cache_path(sess), sess) { LoadResult::Ok { data: (bytes, start_pos) } => { Some(OnDiskCache::new(sess, bytes, start_pos)) } diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 1441e64e41f..7376be6be8b 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -164,7 +164,7 @@ pub fn build_dep_graph( } }; - file_format::write_file_header(&mut encoder, sess.is_nightly_build()); + file_format::write_file_header(&mut encoder, sess); // First encode the commandline arguments hash sess.opts.dep_tracking_hash(false).encode(&mut encoder); diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 3605e10fecd..de9afbbcaab 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -153,20 +153,22 @@ impl<'tcx> InferCtxt<'tcx> { /// Used by the new solver as that one takes the opaque types at the end of a probe /// to deal with multiple candidates without having to recompute them. - pub fn clone_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> { + pub fn clone_opaque_types_for_query_response( + &self, + ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { self.inner .borrow() .opaque_type_storage .opaque_types .iter() - .map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty)) + .map(|(k, v)| (*k, v.hidden_type.ty)) .collect() } - fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> { + fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types) .into_iter() - .map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty)) + .map(|(k, v)| (k, v.hidden_type.ty)) .collect() } @@ -507,8 +509,22 @@ impl<'tcx> InferCtxt<'tcx> { let a = substitute_value(self.tcx, &result_subst, a); let b = substitute_value(self.tcx, &result_subst, b); debug!(?a, ?b, "constrain opaque type"); - obligations - .extend(self.at(cause, param_env).eq(DefineOpaqueTypes::Yes, a, b)?.obligations); + // We use equate here instead of, for example, just registering the + // opaque type's hidden value directly, because we may be instantiating + // a query response that was canonicalized in an InferCtxt that had + // a different defining anchor. In that case, we may have inferred + // `NonLocalOpaque := LocalOpaque` but can only instantiate it in + // the other direction as `LocalOpaque := NonLocalOpaque`. Using eq + // here allows us to try both directions (in `InferCtxt::handle_opaque_type`). + obligations.extend( + self.at(cause, param_env) + .eq( + DefineOpaqueTypes::Yes, + self.tcx.mk_opaque(a.def_id.to_def_id(), a.substs), + b, + )? + .obligations, + ); } Ok(InferOk { value: result_subst, obligations }) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 545310ad351..b88ba04b273 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -530,19 +530,18 @@ impl<'tcx> InferCtxt<'tcx> { // these are the same span, but not in cases like `-> (impl // Foo, impl Bar)`. let span = cause.span; - - let mut obligations = vec![]; let prev = self.inner.borrow_mut().opaque_types().register( OpaqueTypeKey { def_id, substs }, OpaqueHiddenType { ty: hidden_ty, span }, origin, ); - if let Some(prev) = prev { - obligations = self - .at(&cause, param_env) + let mut obligations = if let Some(prev) = prev { + self.at(&cause, param_env) .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? - .obligations; - } + .obligations + } else { + Vec::new() + }; let item_bounds = tcx.explicit_item_bounds(def_id); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index bbf9d9d515d..42d8d228091 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -89,6 +89,7 @@ pub fn register_plugins<'a>( crate_name, sess.crate_types().contains(&CrateType::Executable), sess.opts.cg.metadata.clone(), + sess.cfg_version, ); sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized"); rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?; @@ -486,6 +487,11 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P files.push(normalize_path(profile_sample.as_path().to_path_buf())); } + // Debugger visualizer files + for debugger_visualizer in tcx.debugger_visualizers(LOCAL_CRATE) { + files.push(normalize_path(debugger_visualizer.path.clone().unwrap())); + } + if sess.binary_dep_depinfo() { if let Some(ref backend) = sess.opts.unstable_opts.codegen_backend { if backend.contains('.') { diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 6483d51a0b9..c441a8ffd6f 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -369,7 +369,7 @@ impl Linker { if sess.opts.unstable_opts.no_link { let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT); - CodegenResults::serialize_rlink(&rlink_file, &codegen_results) + CodegenResults::serialize_rlink(sess, &rlink_file, &codegen_results) .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?; return Ok(()); } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 1bae771e373..28e719a40e5 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -52,7 +52,8 @@ fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) { output_file: None, temps_dir, }; - let sess = build_session(sessopts, io, None, registry, vec![], Default::default(), None, None); + let sess = + build_session(sessopts, io, None, registry, vec![], Default::default(), None, None, ""); (sess, cfg) } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 910cafff769..cb19750203e 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -104,6 +104,7 @@ pub fn create_session( lint_caps, file_loader, target_override, + rustc_version_str().unwrap_or("unknown"), ); codegen_backend.init(&sess); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index eb175e96997..0fe140e08d2 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -103,8 +103,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { && let ty = cx.typeck_results().expr_ty(&await_expr) && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind() && cx.tcx.ty_is_opaque_future(ty) - // FIXME: This also includes non-async fns that return `impl Future`. && let async_fn_def_id = cx.tcx.parent(*future_def_id) + && matches!(cx.tcx.def_kind(async_fn_def_id), DefKind::Fn | DefKind::AssocFn) + // Check that this `impl Future` actually comes from an `async fn` + && cx.tcx.asyncness(async_fn_def_id).is_async() && check_must_use_def( cx, async_fn_def_id, diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 6c4d121fd01..6ec691f73b7 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -245,6 +245,7 @@ pub(crate) struct CrateLocator<'a> { only_needs_metadata: bool, sysroot: &'a Path, metadata_loader: &'a dyn MetadataLoader, + cfg_version: &'static str, // Immutable per-search configuration. crate_name: Symbol, @@ -322,6 +323,7 @@ impl<'a> CrateLocator<'a> { only_needs_metadata, sysroot: &sess.sysroot, metadata_loader, + cfg_version: sess.cfg_version, crate_name, exact_paths: if hash.is_none() { sess.opts @@ -654,7 +656,7 @@ impl<'a> CrateLocator<'a> { } fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<Svh> { - let rustc_version = rustc_version(); + let rustc_version = rustc_version(self.cfg_version); let found_version = metadata.get_rustc_version(); if found_version != rustc_version { info!("Rejecting via version: expected {} got {}", rustc_version, found_version); @@ -1096,7 +1098,7 @@ impl CrateError { crate_name, add_info, found_crates, - rustc_version: rustc_version(), + rustc_version: rustc_version(sess.cfg_version), }); } else if !locator.crate_rejections.via_invalid.is_empty() { let mut crate_rejections = Vec::new(); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index deafad394b8..834e2453ee0 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -19,6 +19,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc_hir::diagnostic_items::DiagnosticItems; use rustc_index::{Idx, IndexVec}; use rustc_middle::metadata::ModChild; +use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::ty::codec::TyDecoder; @@ -958,7 +959,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, sess)) } - fn get_debugger_visualizers(self) -> Vec<rustc_span::DebuggerVisualizerFile> { + fn get_debugger_visualizers(self) -> Vec<DebuggerVisualizerFile> { self.root.debugger_visualizers.decode(self).collect::<Vec<_>>() } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 79eb48a1a31..40723f41959 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -19,6 +19,7 @@ use rustc_hir::definitions::DefPathData; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::lang_items::LangItem; use rustc_middle::hir::nested_filter; +use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportInfo, @@ -36,9 +37,7 @@ use rustc_session::config::{CrateType, OptLevel}; use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib}; use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind}; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{ - self, DebuggerVisualizerFile, ExternalSource, FileName, SourceFile, Span, SyntaxContext, -}; +use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext}; use std::borrow::Borrow; use std::collections::hash_map::Entry; use std::hash::Hash; @@ -1855,7 +1854,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_debugger_visualizers(&mut self) -> LazyArray<DebuggerVisualizerFile> { empty_proc_macro!(self); - self.lazy_array(self.tcx.debugger_visualizers(LOCAL_CRATE).iter()) + self.lazy_array( + self.tcx + .debugger_visualizers(LOCAL_CRATE) + .iter() + // Erase the path since it may contain privacy sensitive data + // that we don't want to end up in crate metadata. + // The path is only needed for the local crate because of + // `--emit dep-info`. + .map(DebuggerVisualizerFile::path_erased), + ) } fn encode_crate_deps(&mut self) -> LazyArray<CrateDep> { @@ -2276,7 +2284,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { }; // Encode the rustc version string in a predictable location. - rustc_version().encode(&mut ecx); + rustc_version(tcx.sess.cfg_version).encode(&mut ecx); // Encode all the entries and extra information in the crate, // culminating in the `CrateRoot` which points to all of it. diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 987a484049f..97e67fcf8fd 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -2,6 +2,7 @@ use crate::creader::CrateMetadataRef; use decoder::Metadata; use def_path_hash_map::DefPathHashMapRef; use rustc_data_structures::fx::FxHashMap; +use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use table::TableBuilder; use rustc_ast as ast; @@ -48,8 +49,8 @@ mod def_path_hash_map; mod encoder; mod table; -pub(crate) fn rustc_version() -> String { - format!("rustc {}", option_env!("CFG_VERSION").unwrap_or("unknown version")) +pub(crate) fn rustc_version(cfg_version: &'static str) -> String { + format!("rustc {}", cfg_version) } /// Metadata encoding version. @@ -245,7 +246,7 @@ pub(crate) struct CrateRoot { proc_macro_data: Option<ProcMacroData>, tables: LazyTables, - debugger_visualizers: LazyArray<rustc_span::DebuggerVisualizerFile>, + debugger_visualizers: LazyArray<DebuggerVisualizerFile>, exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 5bf0938d518..3b59df778dc 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,4 +1,5 @@ use crate::hir::{ModuleItems, Owner}; +use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; use crate::ty::TyCtxt; use rustc_ast as ast; @@ -1165,11 +1166,26 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { source_file_names.sort_unstable(); + // We have to take care of debugger visualizers explicitly. The HIR (and + // thus `hir_body_hash`) contains the #[debugger_visualizer] attributes but + // these attributes only store the file path to the visualizer file, not + // their content. Yet that content is exported into crate metadata, so any + // changes to it need to be reflected in the crate hash. + let debugger_visualizers: Vec<_> = tcx + .debugger_visualizers(LOCAL_CRATE) + .iter() + // We ignore the path to the visualizer file since it's not going to be + // encoded in crate metadata and we already hash the full contents of + // the file. + .map(DebuggerVisualizerFile::path_erased) + .collect(); + let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| { let mut stable_hasher = StableHasher::new(); hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher); upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); source_file_names.hash_stable(&mut hcx, &mut stable_hasher); + debugger_visualizers.hash_stable(&mut hcx, &mut stable_hasher); if tcx.sess.opts.incremental_relative_spans() { let definitions = tcx.definitions_untracked(); let mut owner_spans: Vec<_> = krate diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index c4e41e00520..56171314944 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -280,7 +280,7 @@ pub struct QueryResponse<'tcx, R> { /// should get its hidden type inferred. So we bubble the opaque type /// and the type it was compared against upwards and let the query caller /// handle it. - pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>, + pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>, pub value: R, } diff --git a/compiler/rustc_middle/src/middle/debugger_visualizer.rs b/compiler/rustc_middle/src/middle/debugger_visualizer.rs new file mode 100644 index 00000000000..a0497d805da --- /dev/null +++ b/compiler/rustc_middle/src/middle/debugger_visualizer.rs @@ -0,0 +1,38 @@ +use rustc_data_structures::sync::Lrc; +use std::path::PathBuf; + +#[derive(HashStable)] +#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)] +pub enum DebuggerVisualizerType { + Natvis, + GdbPrettyPrinter, +} + +/// A single debugger visualizer file. +#[derive(HashStable)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)] +pub struct DebuggerVisualizerFile { + /// The complete debugger visualizer source. + pub src: Lrc<[u8]>, + /// Indicates which visualizer type this targets. + pub visualizer_type: DebuggerVisualizerType, + /// The file path to the visualizer file. This is used for reporting + /// visualizer files in dep-info. Before it is written to crate metadata, + /// the path is erased to `None`, so as not to emit potentially privacy + /// sensitive data. + pub path: Option<PathBuf>, +} + +impl DebuggerVisualizerFile { + pub fn new(src: Lrc<[u8]>, visualizer_type: DebuggerVisualizerType, path: PathBuf) -> Self { + DebuggerVisualizerFile { src, visualizer_type, path: Some(path) } + } + + pub fn path_erased(&self) -> Self { + DebuggerVisualizerFile { + src: self.src.clone(), + visualizer_type: self.visualizer_type, + path: None, + } + } +} diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index 9bb4570ef14..85c5af9ca13 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -1,4 +1,5 @@ pub mod codegen_fn_attrs; +pub mod debugger_visualizer; pub mod dependency_format; pub mod exported_symbols; pub mod lang_items; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 1da94dd7917..5c71910a955 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -101,7 +101,7 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> { /// pass will be named after the type, and it will consist of a main /// loop that goes over each available MIR and applies `run_pass`. pub trait MirPass<'tcx> { - fn name(&self) -> &str { + fn name(&self) -> &'static str { let name = std::any::type_name::<Self>(); if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name } } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index b45f7caaabe..fd02a16130f 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -28,7 +28,7 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> { }; Erased::<<T as EraseType>::Result> { - // SAFETY: Is it safe to transmute to MaybeUninit for types with the same sizes. + // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes. data: unsafe { transmute_copy(&src) }, } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 12c94dc4676..f5b42c80487 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -12,6 +12,7 @@ use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; +use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; use crate::middle::privacy::EffectiveVisibilities; @@ -1784,12 +1785,18 @@ rustc_queries! { desc { "looking at the source for a crate" } separate_provide_extern } + /// Returns the debugger visualizers defined for this crate. - query debugger_visualizers(_: CrateNum) -> &'tcx Vec<rustc_span::DebuggerVisualizerFile> { + /// NOTE: This query has to be marked `eval_always` because it reads data + /// directly from disk that is not tracked anywhere else. I.e. it + /// represents a genuine input to the query system. + query debugger_visualizers(_: CrateNum) -> &'tcx Vec<DebuggerVisualizerFile> { arena_cache desc { "looking up the debugger visualizers for this crate" } separate_provide_extern + eval_always } + query postorder_cnums(_: ()) -> &'tcx [CrateNum] { eval_always desc { "generating a postorder list of CrateNums" } diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 6b7b910a59b..1511c906d1e 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -124,7 +124,7 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> { pub struct ExternalConstraintsData<'tcx> { // FIXME: implement this. pub region_constraints: QueryRegionConstraints<'tcx>, - pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>, + pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>, } // FIXME: Having to clone `region_constraints` for folding feels bad and diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 810c388ebbe..a2e77d9cdfe 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -56,6 +56,7 @@ trivially_parameterized_over_tcx! { std::string::String, crate::metadata::ModChild, crate::middle::codegen_fn_attrs::CodegenFnAttrs, + crate::middle::debugger_visualizer::DebuggerVisualizerFile, crate::middle::exported_symbols::SymbolExportInfo, crate::middle::resolve_bound_vars::ObjectLifetimeDefault, crate::mir::ConstQualifs, @@ -91,7 +92,6 @@ trivially_parameterized_over_tcx! { rustc_session::cstore::ForeignModule, rustc_session::cstore::LinkagePreference, rustc_session::cstore::NativeLib, - rustc_span::DebuggerVisualizerFile, rustc_span::ExpnData, rustc_span::ExpnHash, rustc_span::ExpnId, diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs index 594cbd8977e..746e3d9652d 100644 --- a/compiler/rustc_mir_transform/src/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -12,7 +12,7 @@ use rustc_session::config::OutputType; pub struct Marker(pub &'static str); impl<'tcx> MirPass<'tcx> for Marker { - fn name(&self) -> &str { + fn name(&self) -> &'static str { self.0 } diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index e1b65823a5a..710eed3ed38 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -6,7 +6,7 @@ use crate::{validate, MirPass}; /// Just like `MirPass`, except it cannot mutate `Body`. pub trait MirLint<'tcx> { - fn name(&self) -> &str { + fn name(&self) -> &'static str { let name = std::any::type_name::<Self>(); if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name } } @@ -26,7 +26,7 @@ impl<'tcx, T> MirPass<'tcx> for Lint<T> where T: MirLint<'tcx>, { - fn name(&self) -> &str { + fn name(&self) -> &'static str { self.0.name() } @@ -49,7 +49,7 @@ impl<'tcx, T> MirPass<'tcx> for WithMinOptLevel<T> where T: MirPass<'tcx>, { - fn name(&self) -> &str { + fn name(&self) -> &'static str { self.1.name() } @@ -121,7 +121,7 @@ fn run_passes_inner<'tcx>( validate_body(tcx, body, format!("before pass {}", name)); } - pass.run_pass(tcx, body); + tcx.sess.time(name, || pass.run_pass(tcx, body)); if dump_enabled { dump_mir_for_pass(tcx, body, &name, true); diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 1b96df3aed5..e59219321b7 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -74,7 +74,7 @@ pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } impl<'tcx> MirPass<'tcx> for SimplifyCfg { - fn name(&self) -> &str { + fn name(&self) -> &'static str { &self.name() } diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index c10180ee3f4..eafe57a0c02 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -250,13 +250,13 @@ where cgu.create_size_estimate(tcx); } - debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter()); + debug_dump(tcx, "INITIAL PARTITIONING", &initial_partitioning.codegen_units); // Merge until we have at most `max_cgu_count` codegen units. { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus"); partitioner.merge_codegen_units(cx, &mut initial_partitioning); - debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter()); + debug_dump(tcx, "POST MERGING", &initial_partitioning.codegen_units); } // In the next step, we use the inlining map to determine which additional @@ -272,7 +272,7 @@ where cgu.create_size_estimate(tcx); } - debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter()); + debug_dump(tcx, "POST INLINING", &post_inlining.codegen_units); // Next we try to make as many symbols "internal" as possible, so LLVM has // more freedom to optimize. @@ -322,6 +322,8 @@ where result.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str())); + debug_dump(tcx, "FINAL", &result); + result } @@ -346,33 +348,37 @@ struct PostInliningPartitioning<'tcx> { internalization_candidates: FxHashSet<MonoItem<'tcx>>, } -fn debug_dump<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, label: &str, cgus: I) -where - I: Iterator<Item = &'a CodegenUnit<'tcx>>, - 'tcx: 'a, -{ +fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) { let dump = move || { use std::fmt::Write; + let num_cgus = cgus.len(); + let max = cgus.iter().map(|cgu| cgu.size_estimate()).max().unwrap(); + let min = cgus.iter().map(|cgu| cgu.size_estimate()).min().unwrap(); + let ratio = max as f64 / min as f64; + let s = &mut String::new(); - let _ = writeln!(s, "{label}"); + let _ = writeln!( + s, + "{label} ({num_cgus} CodegenUnits, max={max}, min={min}, max/min={ratio:.1}):" + ); for cgu in cgus { let _ = - writeln!(s, "CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate()); + writeln!(s, "CodegenUnit {} estimated size {}:", cgu.name(), cgu.size_estimate()); for (mono_item, linkage) in cgu.items() { let symbol_name = mono_item.symbol_name(tcx).name; let symbol_hash_start = symbol_name.rfind('h'); let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]); - let _ = writeln!( + let _ = with_no_trimmed_paths!(writeln!( s, " - {} [{:?}] [{}] estimated size {}", mono_item, linkage, symbol_hash, mono_item.size_estimate(tcx) - ); + )); } let _ = writeln!(s); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 3002f23da75..bcef0f7185f 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -238,6 +238,7 @@ impl<'a> DerefMut for SnapshotParser<'a> { impl<'a> Parser<'a> { #[rustc_lint_diagnostics] + #[track_caller] pub fn struct_span_err<S: Into<MultiSpan>>( &self, sp: S, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 455d7b89f9c..41f92227e7c 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -8,7 +8,6 @@ use crate::{errors, fluent_generated as fluent}; use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, IntoDiagnosticArg, MultiSpan}; -use rustc_expand::base::resolve_path; use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -1916,6 +1915,10 @@ impl CheckAttrVisitor<'_> { /// Checks if the items on the `#[debugger_visualizer]` attribute are valid. fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) -> bool { + // Here we only check that the #[debugger_visualizer] attribute is attached + // to nothing other than a module. All other checks are done in the + // `debugger_visualizer` query where they need to be done for decoding + // anyway. match target { Target::Mod => {} _ => { @@ -1924,53 +1927,7 @@ impl CheckAttrVisitor<'_> { } } - let Some(hints) = attr.meta_item_list() else { - self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span }); - return false; - }; - - let hint = match hints.len() { - 1 => &hints[0], - _ => { - self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span }); - return false; - } - }; - - let Some(meta_item) = hint.meta_item() else { - self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span }); - return false; - }; - - let visualizer_path = match (meta_item.name_or_empty(), meta_item.value_str()) { - (sym::natvis_file, Some(value)) => value, - (sym::gdb_script_file, Some(value)) => value, - (_, _) => { - self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: meta_item.span }); - return false; - } - }; - - let file = - match resolve_path(&self.tcx.sess.parse_sess, visualizer_path.as_str(), attr.span) { - Ok(file) => file, - Err(mut err) => { - err.emit(); - return false; - } - }; - - match std::fs::File::open(&file) { - Ok(_) => true, - Err(error) => { - self.tcx.sess.emit_err(errors::DebugVisualizerUnreadable { - span: meta_item.span, - file: &file, - error, - }); - false - } - } + true } /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 8ea95b3f383..3483f7da528 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -1,60 +1,69 @@ //! Detecting usage of the `#[debugger_visualizer]` attribute. -use hir::CRATE_HIR_ID; -use rustc_data_structures::fx::FxHashSet; +use rustc_ast::Attribute; use rustc_data_structures::sync::Lrc; use rustc_expand::base::resolve_path; -use rustc_hir as hir; -use rustc_hir::HirId; -use rustc_middle::query::{LocalCrate, Providers}; -use rustc_middle::ty::TyCtxt; -use rustc_span::{sym, DebuggerVisualizerFile, DebuggerVisualizerType}; +use rustc_middle::{ + middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}, + query::{LocalCrate, Providers}, + ty::TyCtxt, +}; +use rustc_session::Session; +use rustc_span::sym; -use crate::errors::DebugVisualizerUnreadable; +use crate::errors::{DebugVisualizerInvalid, DebugVisualizerUnreadable}; -fn check_for_debugger_visualizer( - tcx: TyCtxt<'_>, - hir_id: HirId, - debugger_visualizers: &mut FxHashSet<DebuggerVisualizerFile>, -) { - let attrs = tcx.hir().attrs(hir_id); - for attr in attrs { +impl DebuggerVisualizerCollector<'_> { + fn check_for_debugger_visualizer(&mut self, attr: &Attribute) { if attr.has_name(sym::debugger_visualizer) { - let Some(list) = attr.meta_item_list() else { - continue + let Some(hints) = attr.meta_item_list() else { + self.sess.emit_err(DebugVisualizerInvalid { span: attr.span }); + return; }; - let meta_item = match list.len() { - 1 => match list[0].meta_item() { - Some(meta_item) => meta_item, - _ => continue, - }, - _ => continue, + let hint = if hints.len() == 1 { + &hints[0] + } else { + self.sess.emit_err(DebugVisualizerInvalid { span: attr.span }); + return; }; - let visualizer_type = match meta_item.name_or_empty() { - sym::natvis_file => DebuggerVisualizerType::Natvis, - sym::gdb_script_file => DebuggerVisualizerType::GdbPrettyPrinter, - _ => continue, + let Some(meta_item) = hint.meta_item() else { + self.sess.emit_err(DebugVisualizerInvalid { span: attr.span }); + return; }; - let file = match meta_item.value_str() { - Some(value) => { - match resolve_path(&tcx.sess.parse_sess, value.as_str(), attr.span) { - Ok(file) => file, - _ => continue, + let (visualizer_type, visualizer_path) = + match (meta_item.name_or_empty(), meta_item.value_str()) { + (sym::natvis_file, Some(value)) => (DebuggerVisualizerType::Natvis, value), + (sym::gdb_script_file, Some(value)) => { + (DebuggerVisualizerType::GdbPrettyPrinter, value) } - } - None => continue, - }; + (_, _) => { + self.sess.emit_err(DebugVisualizerInvalid { span: meta_item.span }); + return; + } + }; + + let file = + match resolve_path(&self.sess.parse_sess, visualizer_path.as_str(), attr.span) { + Ok(file) => file, + Err(mut err) => { + err.emit(); + return; + } + }; match std::fs::read(&file) { Ok(contents) => { - debugger_visualizers - .insert(DebuggerVisualizerFile::new(Lrc::from(contents), visualizer_type)); + self.visualizers.push(DebuggerVisualizerFile::new( + Lrc::from(contents), + visualizer_type, + file, + )); } Err(error) => { - tcx.sess.emit_err(DebugVisualizerUnreadable { + self.sess.emit_err(DebugVisualizerUnreadable { span: meta_item.span, file: &file, error, @@ -65,29 +74,30 @@ fn check_for_debugger_visualizer( } } -/// Traverses and collects the debugger visualizers for a specific crate. -fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualizerFile> { - // Initialize the collector. - let mut debugger_visualizers = FxHashSet::default(); +struct DebuggerVisualizerCollector<'a> { + sess: &'a Session, + visualizers: Vec<DebuggerVisualizerFile>, +} - // Collect debugger visualizers in this crate. - tcx.hir().for_each_module(|id| { - check_for_debugger_visualizer( - tcx, - tcx.hir().local_def_id_to_hir_id(id), - &mut debugger_visualizers, - ) - }); +impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> { + fn visit_attribute(&mut self, attr: &'ast Attribute) { + self.check_for_debugger_visualizer(attr); + rustc_ast::visit::walk_attribute(self, attr); + } +} - // Collect debugger visualizers on the crate attributes. - check_for_debugger_visualizer(tcx, CRATE_HIR_ID, &mut debugger_visualizers); +/// Traverses and collects the debugger visualizers for a specific crate. +fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualizerFile> { + let resolver_and_krate = tcx.resolver_for_lowering(()).borrow(); + let krate = &*resolver_and_krate.1; - // Extract out the found debugger_visualizer items. - let mut visualizers = debugger_visualizers.into_iter().collect::<Vec<_>>(); + let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() }; + rustc_ast::visit::Visitor::visit_crate(&mut visitor, krate); - // Sort the visualizers so we always get a deterministic query result. - visualizers.sort(); - visualizers + // We are collecting visualizers in AST-order, which is deterministic, + // so we don't need to do any explicit sorting in order to get a + // deterministic query result + visitor.visualizers } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 3ed7580af05..ed0a792d387 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1832,7 +1832,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } (msg, None) } else if ident.name == kw::SelfUpper { - ("`Self` is only available in impls, traits, and type definitions".to_string(), None) + // As mentioned above, `opt_ns` being `None` indicates a module path in import. + // We can use this to improve a confusing error for, e.g. `use Self::Variant` in an + // impl + if opt_ns.is_none() { + ("`Self` cannot be used in imports".to_string(), None) + } else { + ( + "`Self` is only available in impls, traits, and type definitions".to_string(), + None, + ) + } } else if ident.name.as_str().chars().next().map_or(false, |c| c.is_ascii_uppercase()) { // Check whether the name refers to an item in the value namespace. let binding = if let Some(ribs) = ribs { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 0e90703faec..7c4c05d4b94 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -405,11 +405,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { t } - // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed resolution, - // also mark such failed imports as used to avoid duplicate diagnostics. - fn import_dummy_binding(&mut self, import: &'a Import<'a>) { + // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed + // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics. + fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) { if let ImportKind::Single { target, ref target_bindings, .. } = import.kind { - if target_bindings.iter().any(|binding| binding.get().is_some()) { + if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none())) + { return; // Has resolution, do not create the dummy binding } let dummy_binding = self.dummy_binding; @@ -474,7 +475,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If this import is unresolved then create a dummy import // resolution for it so that later resolve stages won't complain. - self.import_dummy_binding(import); + self.import_dummy_binding(import, is_indeterminate); if let Some(err) = unresolved_import_error { if let ImportKind::Single { source, ref source_bindings, .. } = import.kind { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 14a3671c01d..3cdc3f0ecf8 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -85,6 +85,7 @@ pub mod rustdoc; fluent_messages! { "../messages.ftl" } +#[derive(Debug)] enum Weak { Yes, No, diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 39e255104d5..a328447aca9 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -421,7 +421,7 @@ pub enum TrimmedDefPaths { GoodPath, } -#[derive(Clone, Hash)] +#[derive(Clone, Hash, Debug)] pub enum ResolveDocLinks { /// Do not resolve doc links. None, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 4abe734d372..4f593083b6f 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -211,6 +211,9 @@ pub struct Session { /// Set of enabled features for the current target, including unstable ones. pub unstable_target_features: FxIndexSet<Symbol>, + + /// The version of the rustc process, possibly including a commit hash and description. + pub cfg_version: &'static str, } pub struct PerfStats { @@ -1366,6 +1369,7 @@ pub fn build_session( driver_lint_caps: FxHashMap<lint::LintId, lint::Level>, file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>, target_override: Option<Target>, + cfg_version: &'static str, ) -> Session { // FIXME: This is not general enough to make the warning lint completely override // normal diagnostic warnings, since the warning lint can also be denied and changed @@ -1510,6 +1514,7 @@ pub fn build_session( asm_arch, target_features: Default::default(), unstable_target_features: Default::default(), + cfg_version, }; validate_commandline_args_with_session_available(&sess); @@ -1727,6 +1732,7 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] +#[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"] pub fn early_error_no_abort( output: config::ErrorOutputType, msg: impl Into<DiagnosticMessage>, diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 8c58b52a5dc..f65a6aa4fb2 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -146,7 +146,12 @@ pub struct StableCrateId(pub(crate) Hash64); impl StableCrateId { /// Computes the stable ID for a crate with the given name and /// `-Cmetadata` arguments. - pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId { + pub fn new( + crate_name: Symbol, + is_exe: bool, + mut metadata: Vec<String>, + cfg_version: &'static str, + ) -> StableCrateId { let mut hasher = StableHasher::new(); // We must hash the string text of the crate name, not the id, as the id is not stable // across builds. @@ -180,7 +185,7 @@ impl StableCrateId { if let Some(val) = std::env::var_os("RUSTC_FORCE_RUSTC_VERSION") { hasher.write(val.to_string_lossy().into_owned().as_bytes()) } else { - hasher.write(option_env!("CFG_VERSION").unwrap_or("unknown version").as_bytes()); + hasher.write(cfg_version.as_bytes()) } StableCrateId(hasher.finish()) diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 97cb734619e..8d70aa47f78 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1257,29 +1257,6 @@ impl SourceFileHash { } } -#[derive(HashStable_Generic)] -#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)] -pub enum DebuggerVisualizerType { - Natvis, - GdbPrettyPrinter, -} - -/// A single debugger visualizer file. -#[derive(HashStable_Generic)] -#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)] -pub struct DebuggerVisualizerFile { - /// The complete debugger visualizer source. - pub src: Lrc<[u8]>, - /// Indicates which visualizer type this targets. - pub visualizer_type: DebuggerVisualizerType, -} - -impl DebuggerVisualizerFile { - pub fn new(src: Lrc<[u8]>, visualizer_type: DebuggerVisualizerType) -> Self { - DebuggerVisualizerFile { src, visualizer_type } - } -} - #[derive(Clone)] pub enum SourceFileLines { /// The source file lines, in decoded (random-access) form. diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 223cdc48f0b..28dad8592a8 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -143,35 +143,36 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( fn pred_known_to_hold_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - pred: impl ToPredicate<'tcx> + TypeVisitable<TyCtxt<'tcx>>, + pred: impl ToPredicate<'tcx>, ) -> bool { - let has_non_region_infer = pred.has_non_region_infer(); let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred); let result = infcx.evaluate_obligation_no_overflow(&obligation); debug!(?result); - if result.must_apply_modulo_regions() && !has_non_region_infer { + if result.must_apply_modulo_regions() { true } else if result.may_apply() { - // Because of inference "guessing", selection can sometimes claim - // to succeed while the success requires a guess. To ensure - // this function's result remains infallible, we must confirm - // that guess. While imperfect, I believe this is sound. - - // The handling of regions in this area of the code is terrible, - // see issue #29149. We should be able to improve on this with - // NLL. - let ocx = ObligationCtxt::new(infcx); - ocx.register_obligation(obligation); - let errors = ocx.select_all_or_error(); - match errors.as_slice() { - [] => true, - errors => { - debug!(?errors); - false + // Sometimes obligations are ambiguous because the recursive evaluator + // is not smart enough, so we fall back to fulfillment when we're not certain + // that an obligation holds or not. Even still, we must make sure that + // the we do no inference in the process of checking this obligation. + let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env)); + infcx.probe(|_| { + let ocx = ObligationCtxt::new_in_snapshot(infcx); + ocx.register_obligation(obligation); + + let errors = ocx.select_all_or_error(); + match errors.as_slice() { + // Only known to hold if we did no inference. + [] => infcx.shallow_resolve(goal) == goal, + + errors => { + debug!(?errors); + false + } } - } + }) } else { false } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f1bd9f5bbf8..b366bbd531b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -537,14 +537,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PredicateObligation<'tcx>, ) -> Result<EvaluationResult, OverflowError> { self.evaluation_probe(|this| { - if this.tcx().trait_solver_next() { - this.evaluate_predicates_recursively_in_new_solver([obligation.clone()]) + let goal = + this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env)); + let mut result = if this.tcx().trait_solver_next() { + this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])? } else { this.evaluate_predicate_recursively( TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), obligation.clone(), - ) + )? + }; + // If the predicate has done any inference, then downgrade the + // result to ambiguous. + if this.infcx.shallow_resolve(goal) != goal { + result = result.max(EvaluatedToAmbig); } + Ok(result) }) } diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index 7fd14a7e1ea..ef8e4d098ed 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -91,7 +91,7 @@ pub struct EscapeDefault(escape::EscapeIterInner<4>); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn escape_default(c: u8) -> EscapeDefault { - let mut data = [0; 4]; + let mut data = [Char::Null; 4]; let range = escape::escape_ascii_into(&mut data, c); EscapeDefault(escape::EscapeIterInner::new(data, range)) } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 1dfa9c34db1..515b8d20ead 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -392,13 +392,13 @@ impl char { #[inline] pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug { match self { - '\0' => EscapeDebug::backslash(b'0'), - '\t' => EscapeDebug::backslash(b't'), - '\r' => EscapeDebug::backslash(b'r'), - '\n' => EscapeDebug::backslash(b'n'), - '\\' => EscapeDebug::backslash(b'\\'), - '"' if args.escape_double_quote => EscapeDebug::backslash(b'"'), - '\'' if args.escape_single_quote => EscapeDebug::backslash(b'\''), + '\0' => EscapeDebug::backslash(ascii::Char::Digit0), + '\t' => EscapeDebug::backslash(ascii::Char::SmallT), + '\r' => EscapeDebug::backslash(ascii::Char::SmallR), + '\n' => EscapeDebug::backslash(ascii::Char::SmallN), + '\\' => EscapeDebug::backslash(ascii::Char::ReverseSolidus), + '\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark), + '\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe), _ if args.escape_grapheme_extended && self.is_grapheme_extended() => { EscapeDebug::from_unicode(self.escape_unicode()) } @@ -503,11 +503,11 @@ impl char { #[inline] pub fn escape_default(self) -> EscapeDefault { match self { - '\t' => EscapeDefault::backslash(b't'), - '\r' => EscapeDefault::backslash(b'r'), - '\n' => EscapeDefault::backslash(b'n'), - '\\' | '\'' | '"' => EscapeDefault::backslash(self as u8), - '\x20'..='\x7e' => EscapeDefault::printable(self as u8), + '\t' => EscapeDefault::backslash(ascii::Char::SmallT), + '\r' => EscapeDefault::backslash(ascii::Char::SmallR), + '\n' => EscapeDefault::backslash(ascii::Char::SmallN), + '\\' | '\'' | '"' => EscapeDefault::backslash(self.as_ascii().unwrap()), + '\x20'..='\x7e' => EscapeDefault::printable(self.as_ascii().unwrap()), _ => EscapeDefault::from_unicode(self.escape_unicode()), } } diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index e186db7052c..5c42912874c 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -38,6 +38,7 @@ pub use self::methods::encode_utf16_raw; #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] pub use self::methods::encode_utf8_raw; +use crate::ascii; use crate::error::Error; use crate::escape; use crate::fmt::{self, Write}; @@ -152,7 +153,7 @@ pub struct EscapeUnicode(escape::EscapeIterInner<10>); impl EscapeUnicode { fn new(chr: char) -> Self { - let mut data = [0; 10]; + let mut data = [ascii::Char::Null; 10]; let range = escape::escape_unicode_into(&mut data, chr); Self(escape::EscapeIterInner::new(data, range)) } @@ -218,14 +219,14 @@ impl fmt::Display for EscapeUnicode { pub struct EscapeDefault(escape::EscapeIterInner<10>); impl EscapeDefault { - fn printable(chr: u8) -> Self { - let data = [chr, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - Self(escape::EscapeIterInner::new(data, 0..1)) + fn printable(chr: ascii::Char) -> Self { + let data = [chr]; + Self(escape::EscapeIterInner::from_array(data)) } - fn backslash(chr: u8) -> Self { - let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0]; - Self(escape::EscapeIterInner::new(data, 0..2)) + fn backslash(chr: ascii::Char) -> Self { + let data = [ascii::Char::ReverseSolidus, chr]; + Self(escape::EscapeIterInner::from_array(data)) } fn from_unicode(esc: EscapeUnicode) -> Self { @@ -307,9 +308,9 @@ impl EscapeDebug { Self(EscapeDebugInner::Char(chr)) } - fn backslash(chr: u8) -> Self { - let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0]; - let iter = escape::EscapeIterInner::new(data, 0..2); + fn backslash(chr: ascii::Char) -> Self { + let data = [ascii::Char::ReverseSolidus, chr]; + let iter = escape::EscapeIterInner::from_array(data); Self(EscapeDebugInner::Bytes(iter)) } @@ -318,7 +319,7 @@ impl EscapeDebug { } fn clear(&mut self) { - let bytes = escape::EscapeIterInner::new([0; 10], 0..0); + let bytes = escape::EscapeIterInner::from_array([]); self.0 = EscapeDebugInner::Bytes(bytes); } } diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs index 20ac3cf027f..3d471419bb8 100644 --- a/library/core/src/escape.rs +++ b/library/core/src/escape.rs @@ -1,34 +1,41 @@ //! Helper code for character escaping. +use crate::ascii; use crate::num::NonZeroUsize; use crate::ops::Range; -const HEX_DIGITS: [u8; 16] = *b"0123456789abcdef"; +const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap(); /// Escapes a byte into provided buffer; returns length of escaped /// representation. -pub(crate) fn escape_ascii_into(output: &mut [u8; 4], byte: u8) -> Range<u8> { +pub(crate) fn escape_ascii_into(output: &mut [ascii::Char; 4], byte: u8) -> Range<u8> { + #[inline] + fn backslash(a: ascii::Char) -> ([ascii::Char; 4], u8) { + ([ascii::Char::ReverseSolidus, a, ascii::Char::Null, ascii::Char::Null], 2) + } + let (data, len) = match byte { - b'\t' => ([b'\\', b't', 0, 0], 2), - b'\r' => ([b'\\', b'r', 0, 0], 2), - b'\n' => ([b'\\', b'n', 0, 0], 2), - b'\\' => ([b'\\', b'\\', 0, 0], 2), - b'\'' => ([b'\\', b'\'', 0, 0], 2), - b'"' => ([b'\\', b'"', 0, 0], 2), - b'\x20'..=b'\x7e' => ([byte, 0, 0, 0], 1), - _ => { + b'\t' => backslash(ascii::Char::SmallT), + b'\r' => backslash(ascii::Char::SmallR), + b'\n' => backslash(ascii::Char::SmallN), + b'\\' => backslash(ascii::Char::ReverseSolidus), + b'\'' => backslash(ascii::Char::Apostrophe), + b'\"' => backslash(ascii::Char::QuotationMark), + _ => if let Some(a) = byte.as_ascii() && !byte.is_ascii_control() { + ([a, ascii::Char::Null, ascii::Char::Null, ascii::Char::Null], 1) + } else { let hi = HEX_DIGITS[usize::from(byte >> 4)]; let lo = HEX_DIGITS[usize::from(byte & 0xf)]; - ([b'\\', b'x', hi, lo], 4) + ([ascii::Char::ReverseSolidus, ascii::Char::SmallX, hi, lo], 4) } }; *output = data; - 0..(len as u8) + 0..len } /// Escapes a character into provided buffer using `\u{NNNN}` representation. -pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8> { - output[9] = b'}'; +pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> Range<u8> { + output[9] = ascii::Char::RightCurlyBracket; let ch = ch as u32; output[3] = HEX_DIGITS[((ch >> 20) & 15) as usize]; @@ -41,7 +48,8 @@ pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8> // or-ing 1 ensures that for ch==0 the code computes that one digit should // be printed. let start = (ch | 1).leading_zeros() as usize / 4 - 2; - output[start..start + 3].copy_from_slice(b"\\u{"); + const UNICODE_ESCAPE_PREFIX: &[ascii::Char; 3] = b"\\u{".as_ascii().unwrap(); + output[start..][..3].copy_from_slice(UNICODE_ESCAPE_PREFIX); (start as u8)..10 } @@ -52,29 +60,34 @@ pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8> /// limited to u8 to reduce size of the structure. #[derive(Clone, Debug)] pub(crate) struct EscapeIterInner<const N: usize> { - // Invariant: data[alive] is all ASCII. - pub(crate) data: [u8; N], + // The element type ensures this is always ASCII, and thus also valid UTF-8. + pub(crate) data: [ascii::Char; N], // Invariant: alive.start <= alive.end <= N. pub(crate) alive: Range<u8>, } impl<const N: usize> EscapeIterInner<N> { - pub fn new(data: [u8; N], alive: Range<u8>) -> Self { + pub fn new(data: [ascii::Char; N], alive: Range<u8>) -> Self { const { assert!(N < 256) }; debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}"); - let this = Self { data, alive }; - debug_assert!(this.as_bytes().is_ascii(), "Expected ASCII, got {:?}", this.as_bytes()); - this + Self { data, alive } + } + + pub fn from_array<const M: usize>(array: [ascii::Char; M]) -> Self { + const { assert!(M <= N) }; + + let mut data = [ascii::Char::Null; N]; + data[..M].copy_from_slice(&array); + Self::new(data, 0..M as u8) } - fn as_bytes(&self) -> &[u8] { + pub fn as_ascii(&self) -> &[ascii::Char] { &self.data[usize::from(self.alive.start)..usize::from(self.alive.end)] } pub fn as_str(&self) -> &str { - // SAFETY: self.data[self.alive] is all ASCII characters. - unsafe { crate::str::from_utf8_unchecked(self.as_bytes()) } + self.as_ascii().as_str() } pub fn len(&self) -> usize { @@ -82,11 +95,11 @@ impl<const N: usize> EscapeIterInner<N> { } pub fn next(&mut self) -> Option<u8> { - self.alive.next().map(|i| self.data[usize::from(i)]) + self.alive.next().map(|i| self.data[usize::from(i)].as_u8()) } pub fn next_back(&mut self) -> Option<u8> { - self.alive.next_back().map(|i| self.data[usize::from(i)]) + self.alive.next_back().map(|i| self.data[usize::from(i)].as_u8()) } pub fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { diff --git a/library/core/src/future/join.rs b/library/core/src/future/join.rs index 35f0dea062e..3f35179ddc2 100644 --- a/library/core/src/future/join.rs +++ b/library/core/src/future/join.rs @@ -4,7 +4,7 @@ use crate::cell::UnsafeCell; use crate::future::{poll_fn, Future}; use crate::mem; use crate::pin::Pin; -use crate::task::{Context, Poll}; +use crate::task::{ready, Context, Poll}; /// Polls multiple futures simultaneously, returning a tuple /// of all results once complete. @@ -118,7 +118,7 @@ macro join_internal { fut }) }; - // Despite how tempting it may be to `let () = fut.poll(cx).ready()?;` + // Despite how tempting it may be to `let () = ready!(fut.poll(cx));` // doing so would defeat the point of `join!`: to start polling eagerly all // of the futures, to allow parallelizing the waits. done &= fut.poll(cx).is_ready(); @@ -180,7 +180,7 @@ impl<F: Future> Future for MaybeDone<F> { // Do not mix match ergonomics with unsafe. match *self.as_mut().get_unchecked_mut() { MaybeDone::Future(ref mut f) => { - let val = Pin::new_unchecked(f).poll(cx).ready()?; + let val = ready!(Pin::new_unchecked(f).poll(cx)); self.set(Self::Done(val)); } MaybeDone::Done(_) => {} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0af04fac909..6c419eb16f3 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -216,6 +216,7 @@ #![feature(intra_doc_pointers)] #![feature(intrinsics)] #![feature(lang_items)] +#![feature(let_chains)] #![feature(link_llvm_intrinsics)] #![feature(macro_metavar_expr)] #![feature(min_specialization)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index ca45683d3d6..2bb688b921c 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -986,7 +986,7 @@ pub trait PointerLike {} #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] pub trait ConstParamTy: StructuralEq {} -/// Derive macro generating an impl of the trait `Copy`. +/// Derive macro generating an impl of the trait `ConstParamTy`. #[rustc_builtin_macro] #[unstable(feature = "adt_const_params", issue = "95174")] #[cfg(not(bootstrap))] diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index ebcce79b0f8..20be60d3535 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -28,13 +28,13 @@ pub macro panic_2015 { $crate::panicking::panic($msg) ), // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint. - ($msg:expr $(,)?) => ( - $crate::panicking::panic_str($msg) - ), + ($msg:expr $(,)?) => ({ + $crate::panicking::panic_str($msg); + }), // Special-case the single-argument case for const_panic. - ("{}", $arg:expr $(,)?) => ( - $crate::panicking::panic_display(&$arg) - ), + ("{}", $arg:expr $(,)?) => ({ + $crate::panicking::panic_display(&$arg); + }), ($fmt:expr, $($arg:tt)+) => ({ // Semicolon to prevent temporaries inside the formatting machinery from // being considered alive in the caller after the panic_fmt call. @@ -52,9 +52,9 @@ pub macro panic_2021 { $crate::panicking::panic("explicit panic") ), // Special-case the single-argument case for const_panic. - ("{}", $arg:expr $(,)?) => ( - $crate::panicking::panic_display(&$arg) - ), + ("{}", $arg:expr $(,)?) => ({ + $crate::panicking::panic_display(&$arg); + }), ($($t:tt)+) => ({ // Semicolon to prevent temporaries inside the formatting machinery from // being considered alive in the caller after the panic_fmt call. @@ -73,9 +73,9 @@ pub macro unreachable_2015 { ), // Use of `unreachable_display` for non_fmt_panic lint. // NOTE: the message ("internal error ...") is embedded directly in unreachable_display - ($msg:expr $(,)?) => ( - $crate::panicking::unreachable_display(&$msg) - ), + ($msg:expr $(,)?) => ({ + $crate::panicking::unreachable_display(&$msg); + }), ($fmt:expr, $($arg:tt)*) => ( $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) ), diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 6fd2b87d0e3..5ece1b78c03 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -995,7 +995,7 @@ impl<T> [T] { #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] #[must_use] - pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] { + pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] { let this = self; // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length let new_len = unsafe { @@ -1043,7 +1043,7 @@ impl<T> [T] { #[inline] #[track_caller] #[must_use] - pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) { + pub const fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) { assert!(N != 0, "chunk size must be non-zero"); let len = self.len() / N; let (multiple_of_n, remainder) = self.split_at(len * N); @@ -1075,7 +1075,7 @@ impl<T> [T] { #[inline] #[track_caller] #[must_use] - pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) { + pub const fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) { assert!(N != 0, "chunk size must be non-zero"); let len = self.len() / N; let (remainder, multiple_of_n) = self.split_at(self.len() - len * N); @@ -1152,7 +1152,7 @@ impl<T> [T] { #[unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] #[must_use] - pub unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] { + pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] { let this = &*self; // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length let new_len = unsafe { @@ -1195,7 +1195,7 @@ impl<T> [T] { #[inline] #[track_caller] #[must_use] - pub fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) { + pub const fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) { assert!(N != 0, "chunk size must be non-zero"); let len = self.len() / N; let (multiple_of_n, remainder) = self.split_at_mut(len * N); @@ -1233,7 +1233,7 @@ impl<T> [T] { #[inline] #[track_caller] #[must_use] - pub fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) { + pub const fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) { assert!(N != 0, "chunk size must be non-zero"); let len = self.len() / N; let (remainder, multiple_of_n) = self.split_at_mut(self.len() - len * N); diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs index c5f89b9a2c6..3f0080e3832 100644 --- a/library/core/src/task/mod.rs +++ b/library/core/src/task/mod.rs @@ -13,5 +13,3 @@ pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker}; mod ready; #[stable(feature = "ready_macro", since = "1.64.0")] pub use ready::ready; -#[unstable(feature = "poll_ready", issue = "89780")] -pub use ready::Ready; diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 5283a576d1b..0a0f702f6fb 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -3,7 +3,6 @@ use crate::convert; use crate::ops::{self, ControlFlow}; use crate::result::Result; -use crate::task::Ready; /// Indicates whether a value is available or if the current task has been /// scheduled to receive a wakeup instead. @@ -95,38 +94,6 @@ impl<T> Poll<T> { pub const fn is_pending(&self) -> bool { !self.is_ready() } - - /// Extracts the successful type of a [`Poll<T>`]. - /// - /// When combined with the `?` operator, this function will - /// propagate any [`Poll::Pending`] values to the caller, and - /// extract the `T` from [`Poll::Ready`]. - /// - /// # Examples - /// - /// ```rust - /// #![feature(poll_ready)] - /// - /// use std::task::{Context, Poll}; - /// use std::future::{self, Future}; - /// use std::pin::Pin; - /// - /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> { - /// let mut fut = future::ready(42); - /// let fut = Pin::new(&mut fut); - /// - /// let num = fut.poll(cx).ready()?; - /// # let _ = num; // to silence unused warning - /// // ... use num - /// - /// Poll::Ready(()) - /// } - /// ``` - #[inline] - #[unstable(feature = "poll_ready", issue = "89780")] - pub fn ready(self) -> Ready<T> { - Ready(self) - } } impl<T, E> Poll<Result<T, E>> { diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs index 8d12625e88d..495d72fd14b 100644 --- a/library/core/src/task/ready.rs +++ b/library/core/src/task/ready.rs @@ -1,8 +1,3 @@ -use core::convert; -use core::fmt; -use core::ops::{ControlFlow, FromResidual, Try}; -use core::task::Poll; - /// Extracts the successful type of a [`Poll<T>`]. /// /// This macro bakes in propagation of [`Pending`] signals by returning early. @@ -60,55 +55,3 @@ pub macro ready($e:expr) { } } } - -/// Extracts the successful type of a [`Poll<T>`]. -/// -/// See [`Poll::ready`] for details. -#[unstable(feature = "poll_ready", issue = "89780")] -pub struct Ready<T>(pub(crate) Poll<T>); - -#[unstable(feature = "poll_ready", issue = "89780")] -impl<T> Try for Ready<T> { - type Output = T; - type Residual = Ready<convert::Infallible>; - - #[inline] - fn from_output(output: Self::Output) -> Self { - Ready(Poll::Ready(output)) - } - - #[inline] - fn branch(self) -> ControlFlow<Self::Residual, Self::Output> { - match self.0 { - Poll::Ready(v) => ControlFlow::Continue(v), - Poll::Pending => ControlFlow::Break(Ready(Poll::Pending)), - } - } -} - -#[unstable(feature = "poll_ready", issue = "89780")] -impl<T> FromResidual for Ready<T> { - #[inline] - fn from_residual(residual: Ready<convert::Infallible>) -> Self { - match residual.0 { - Poll::Pending => Ready(Poll::Pending), - } - } -} - -#[unstable(feature = "poll_ready", issue = "89780")] -impl<T> FromResidual<Ready<convert::Infallible>> for Poll<T> { - #[inline] - fn from_residual(residual: Ready<convert::Infallible>) -> Self { - match residual.0 { - Poll::Pending => Poll::Pending, - } - } -} - -#[unstable(feature = "poll_ready", issue = "89780")] -impl<T> fmt::Debug for Ready<T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Ready").finish() - } -} diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 7f033816901..0a9850146e5 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -386,6 +386,21 @@ fn offset_of() { // Layout of tuples is unstable assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1); assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2); + + #[repr(C)] + struct Generic<T> { + x: u8, + y: u32, + z: T + } + + // Ensure that this type of generics works + fn offs_of_z<T>() -> usize { + offset_of!(Generic<T>, z) + } + + assert_eq!(offset_of!(Generic<u8>, z), 8); + assert_eq!(offs_of_z::<u8>(), 8); } #[test] diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 2a6b1a5ec73..89dfdfafdb1 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -15,6 +15,7 @@ use crate::ffi::OsString; use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; +use crate::sealed::Sealed; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; use crate::time::SystemTime; @@ -1391,6 +1392,16 @@ impl FileTimes { } } +impl AsInnerMut<fs_imp::FileTimes> for FileTimes { + fn as_inner_mut(&mut self) -> &mut fs_imp::FileTimes { + &mut self.0 + } +} + +// For implementing OS extension traits in `std::os` +#[unstable(feature = "file_set_times", issue = "98245")] +impl Sealed for FileTimes {} + impl Permissions { /// Returns `true` if these permissions describe a readonly (unwritable) file. /// diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index a8a0b9f122d..e2480bcbbc7 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1,7 +1,7 @@ use crate::io::prelude::*; use crate::env; -use crate::fs::{self, File, OpenOptions}; +use crate::fs::{self, File, FileTimes, OpenOptions}; use crate::io::{BorrowedBuf, ErrorKind, SeekFrom}; use crate::mem::MaybeUninit; use crate::path::Path; @@ -9,7 +9,7 @@ use crate::str; use crate::sync::Arc; use crate::sys_common::io::test::{tmpdir, TempDir}; use crate::thread; -use crate::time::{Duration, Instant}; +use crate::time::{Duration, Instant, SystemTime}; use rand::RngCore; @@ -1633,3 +1633,53 @@ fn rename_directory() { assert!(new_path.join("newdir").is_dir()); assert!(new_path.join("newdir/temp.txt").exists()); } + +#[test] +fn test_file_times() { + #[cfg(target_os = "ios")] + use crate::os::ios::fs::FileTimesExt; + #[cfg(target_os = "macos")] + use crate::os::macos::fs::FileTimesExt; + #[cfg(target_os = "watchos")] + use crate::os::watchos::fs::FileTimesExt; + #[cfg(windows)] + use crate::os::windows::fs::FileTimesExt; + + let tmp = tmpdir(); + let file = File::create(tmp.join("foo")).unwrap(); + let mut times = FileTimes::new(); + let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345); + let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321); + times = times.set_accessed(accessed).set_modified(modified); + #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))] + let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123); + #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))] + { + times = times.set_created(created); + } + match file.set_times(times) { + // Allow unsupported errors on platforms which don't support setting times. + #[cfg(not(any( + windows, + all( + unix, + not(any( + target_os = "android", + target_os = "redox", + target_os = "espidf", + target_os = "horizon" + )) + ) + )))] + Err(e) if e.kind() == ErrorKind::Unsupported => return, + Err(e) => panic!("error setting file times: {e:?}"), + Ok(_) => {} + } + let metadata = file.metadata().unwrap(); + assert_eq!(metadata.accessed().unwrap(), accessed); + assert_eq!(metadata.modified().unwrap(), modified); + #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))] + { + assert_eq!(metadata.created().unwrap(), created); + } +} diff --git a/library/std/src/os/ios/fs.rs b/library/std/src/os/ios/fs.rs index 4a4637ce072..6d4d54b7c78 100644 --- a/library/std/src/os/ios/fs.rs +++ b/library/std/src/os/ios/fs.rs @@ -1,7 +1,9 @@ #![stable(feature = "metadata_ext", since = "1.1.0")] -use crate::fs::Metadata; -use crate::sys_common::AsInner; +use crate::fs::{self, Metadata}; +use crate::sealed::Sealed; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; #[allow(deprecated)] use crate::os::ios::raw; @@ -140,3 +142,19 @@ impl MetadataExt for Metadata { self.as_inner().as_inner().st_lspare as u32 } } + +/// OS-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} diff --git a/library/std/src/os/macos/fs.rs b/library/std/src/os/macos/fs.rs index 91915da6a43..fe82d03d869 100644 --- a/library/std/src/os/macos/fs.rs +++ b/library/std/src/os/macos/fs.rs @@ -1,7 +1,9 @@ #![stable(feature = "metadata_ext", since = "1.1.0")] -use crate::fs::Metadata; -use crate::sys_common::AsInner; +use crate::fs::{self, Metadata}; +use crate::sealed::Sealed; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; #[allow(deprecated)] use crate::os::macos::raw; @@ -146,3 +148,19 @@ impl MetadataExt for Metadata { [qspare[0] as u64, qspare[1] as u64] } } + +/// OS-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} diff --git a/library/std/src/os/watchos/fs.rs b/library/std/src/os/watchos/fs.rs index a14fe35a77c..2ecc4c68a96 100644 --- a/library/std/src/os/watchos/fs.rs +++ b/library/std/src/os/watchos/fs.rs @@ -1,7 +1,9 @@ #![stable(feature = "metadata_ext", since = "1.1.0")] -use crate::fs::Metadata; -use crate::sys_common::AsInner; +use crate::fs::{self, Metadata}; +use crate::sealed::Sealed; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; #[allow(deprecated)] use crate::os::watchos::raw; @@ -140,3 +142,19 @@ impl MetadataExt for Metadata { self.as_inner().as_inner().st_lspare as u32 } } + +/// OS-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index a091f06dd53..94509e54796 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -9,7 +9,8 @@ use crate::io; use crate::path::Path; use crate::sealed::Sealed; use crate::sys; -use crate::sys_common::{AsInner, AsInnerMut}; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; /// Windows-specific extensions to [`fs::File`]. #[stable(feature = "file_offset", since = "1.15.0")] @@ -526,6 +527,22 @@ impl FileTypeExt for fs::FileType { } } +/// Windows-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} + /// Creates a new symlink to a non-directory file on the filesystem. /// /// The `link` path will be a file symbolic link pointing to the `original` diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index a2ffd8b1e7e..69a6f3e6d5a 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -19,11 +19,11 @@ pub macro panic_2015 { $crate::rt::begin_panic("explicit panic") }), ($msg:expr $(,)?) => ({ - $crate::rt::begin_panic($msg) + $crate::rt::begin_panic($msg); }), // Special-case the single-argument case for const_panic. ("{}", $arg:expr $(,)?) => ({ - $crate::rt::panic_display(&$arg) + $crate::rt::panic_display(&$arg); }), ($fmt:expr, $($arg:tt)+) => ({ // Semicolon to prevent temporaries inside the formatting machinery from diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 09db5b11dbf..09e9ae2720f 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -349,6 +349,8 @@ pub struct FilePermissions { pub struct FileTimes { accessed: Option<SystemTime>, modified: Option<SystemTime>, + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] + created: Option<SystemTime>, } #[derive(Copy, Clone, Eq, Debug)] @@ -591,6 +593,11 @@ impl FileTimes { pub fn set_modified(&mut self, t: SystemTime) { self.modified = Some(t); } + + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] + pub fn set_created(&mut self, t: SystemTime) { + self.created = Some(t); + } } impl FileType { @@ -1215,26 +1222,41 @@ impl File { io::ErrorKind::Unsupported, "setting file times not supported", )) - } else if #[cfg(any(target_os = "android", target_os = "macos"))] { + } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] { + let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3]; + let mut num_times = 0; + let mut attrlist: libc::attrlist = unsafe { mem::zeroed() }; + attrlist.bitmapcount = libc::ATTR_BIT_MAP_COUNT; + if times.created.is_some() { + buf[num_times].write(to_timespec(times.created)?); + num_times += 1; + attrlist.commonattr |= libc::ATTR_CMN_CRTIME; + } + if times.modified.is_some() { + buf[num_times].write(to_timespec(times.modified)?); + num_times += 1; + attrlist.commonattr |= libc::ATTR_CMN_MODTIME; + } + if times.accessed.is_some() { + buf[num_times].write(to_timespec(times.accessed)?); + num_times += 1; + attrlist.commonattr |= libc::ATTR_CMN_ACCTIME; + } + cvt(unsafe { libc::fsetattrlist( + self.as_raw_fd(), + (&attrlist as *const libc::attrlist).cast::<libc::c_void>().cast_mut(), + buf.as_ptr().cast::<libc::c_void>().cast_mut(), + num_times * mem::size_of::<libc::timespec>(), + 0 + ) })?; + Ok(()) + } else if #[cfg(target_os = "android")] { let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; - // futimens requires macOS 10.13, and Android API level 19 + // futimens requires Android API level 19 cvt(unsafe { weak!(fn futimens(c_int, *const libc::timespec) -> c_int); match futimens.get() { Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()), - #[cfg(target_os = "macos")] - None => { - fn ts_to_tv(ts: &libc::timespec) -> libc::timeval { - libc::timeval { - tv_sec: ts.tv_sec, - tv_usec: (ts.tv_nsec / 1000) as _ - } - } - let timevals = [ts_to_tv(×[0]), ts_to_tv(×[1])]; - libc::futimes(self.as_raw_fd(), timevals.as_ptr()) - } - // futimes requires even newer Android. - #[cfg(target_os = "android")] None => return Err(io::const_io_error!( io::ErrorKind::Unsupported, "setting file times requires Android API level >= 19", diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index ce427766d17..21a65bc25f3 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -88,8 +88,10 @@ pub struct FilePermissions { pub struct FileTimes { accessed: Option<c::FILETIME>, modified: Option<c::FILETIME>, + created: Option<c::FILETIME>, } -impl core::fmt::Debug for c::FILETIME { + +impl fmt::Debug for c::FILETIME { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let time = ((self.dwHighDateTime as u64) << 32) | self.dwLowDateTime as u64; f.debug_tuple("FILETIME").field(&time).finish() @@ -582,7 +584,10 @@ impl File { pub fn set_times(&self, times: FileTimes) -> io::Result<()> { let is_zero = |t: c::FILETIME| t.dwLowDateTime == 0 && t.dwHighDateTime == 0; - if times.accessed.map_or(false, is_zero) || times.modified.map_or(false, is_zero) { + if times.accessed.map_or(false, is_zero) + || times.modified.map_or(false, is_zero) + || times.created.map_or(false, is_zero) + { return Err(io::const_io_error!( io::ErrorKind::InvalidInput, "Cannot set file timestamp to 0", @@ -590,18 +595,23 @@ impl File { } let is_max = |t: c::FILETIME| t.dwLowDateTime == c::DWORD::MAX && t.dwHighDateTime == c::DWORD::MAX; - if times.accessed.map_or(false, is_max) || times.modified.map_or(false, is_max) { + if times.accessed.map_or(false, is_max) + || times.modified.map_or(false, is_max) + || times.created.map_or(false, is_max) + { return Err(io::const_io_error!( io::ErrorKind::InvalidInput, "Cannot set file timestamp to 0xFFFF_FFFF_FFFF_FFFF", )); } cvt(unsafe { + let created = + times.created.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null()); let accessed = times.accessed.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null()); let modified = times.modified.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null()); - c::SetFileTime(self.as_raw_handle(), ptr::null_mut(), accessed, modified) + c::SetFileTime(self.as_raw_handle(), created, accessed, modified) })?; Ok(()) } @@ -1005,6 +1015,10 @@ impl FileTimes { pub fn set_modified(&mut self, t: SystemTime) { self.modified = Some(t.into_inner()); } + + pub fn set_created(&mut self, t: SystemTime) { + self.created = Some(t.into_inner()); + } } impl FileType { diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 5c37fab5470..cf7c6596c02 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -942,7 +942,6 @@ impl<'a> Builder<'a> { self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths); } - /// NOTE: keep this in sync with `rustdoc::clean::utils::doc_rust_lang_org_channel`, or tests will fail on beta/stable. pub fn doc_rust_lang_org_channel(&self) -> String { let channel = match &*self.config.channel { "stable" => &self.version, diff --git a/src/tools/replace-version-placeholder/src/main.rs b/src/tools/replace-version-placeholder/src/main.rs index 0aebfc4aad2..5c9c18b9b36 100644 --- a/src/tools/replace-version-placeholder/src/main.rs +++ b/src/tools/replace-version-placeholder/src/main.rs @@ -8,15 +8,13 @@ fn main() { let version_path = root_path.join("src").join("version"); let version_str = t!(std::fs::read_to_string(&version_path), version_path); let version_str = version_str.trim(); - walk::walk( - &root_path, + walk::walk_many( + &[&root_path.join("compiler"), &root_path.join("library")], |path, _is_dir| { walk::filter_dirs(path) // We exempt these as they require the placeholder // for their operation || path.ends_with("compiler/rustc_attr/src/builtin.rs") - || path.ends_with("src/tools/tidy/src/features/version.rs") - || path.ends_with("src/tools/replace-version-placeholder") }, &mut |entry, contents| { if !contents.contains(VERSION_PLACEHOLDER) { diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index ee12f4acb10..be3a5d3aa0f 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -35,6 +35,7 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ "tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment", // more include "tests/ui/unused-crate-deps/test.mk", // why would you use make "tests/ui/proc-macro/auxiliary/included-file.txt", // more include + "tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer ]; fn check_entries(tests_path: &Path, bad: &mut bool) { diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/Makefile b/tests/run-make/CURRENT_RUSTC_VERSION/Makefile new file mode 100644 index 00000000000..7940dae207b --- /dev/null +++ b/tests/run-make/CURRENT_RUSTC_VERSION/Makefile @@ -0,0 +1,6 @@ +include ../tools.mk + +all: + $(RUSTC) --emit=metadata --crate-type lib stable.rs + $(RUSTC) --emit=metadata --extern stable=$(TMPDIR)/libstable.rmeta main.rs 2>&1 >/dev/null \ + | $(CGREP) -e "stable since $$(cat $(S)/src/version)(-[a-zA-Z]+)?" diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/main.rs b/tests/run-make/CURRENT_RUSTC_VERSION/main.rs new file mode 100644 index 00000000000..466aaa82bd4 --- /dev/null +++ b/tests/run-make/CURRENT_RUSTC_VERSION/main.rs @@ -0,0 +1,4 @@ +#![feature(foo)] +extern crate stable; + +fn main() {} diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs b/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs new file mode 100644 index 00000000000..2fd09aded60 --- /dev/null +++ b/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs @@ -0,0 +1,5 @@ +#![feature(staged_api)] +#![stable(since = "1.0.0", feature = "rust1")] + +#[stable(since = "CURRENT_RUSTC_VERSION", feature = "foo")] +pub fn foo() {} diff --git a/tests/run-make/debugger-visualizer-dep-info/Makefile b/tests/run-make/debugger-visualizer-dep-info/Makefile new file mode 100644 index 00000000000..0877998a74f --- /dev/null +++ b/tests/run-make/debugger-visualizer-dep-info/Makefile @@ -0,0 +1,9 @@ +include ../tools.mk + +# This test makes sure that files referenced via #[debugger_visualizer] are +# included in `--emit dep-info` output. + +all: + $(RUSTC) --emit dep-info main.rs + $(CGREP) "foo.py" < $(TMPDIR)/main.d + $(CGREP) "my_visualizers/bar.natvis" < $(TMPDIR)/main.d diff --git a/tests/run-make/debugger-visualizer-dep-info/foo.py b/tests/run-make/debugger-visualizer-dep-info/foo.py new file mode 100644 index 00000000000..1bb8bf6d7fd --- /dev/null +++ b/tests/run-make/debugger-visualizer-dep-info/foo.py @@ -0,0 +1 @@ +# empty diff --git a/tests/run-make/debugger-visualizer-dep-info/main.rs b/tests/run-make/debugger-visualizer-dep-info/main.rs new file mode 100644 index 00000000000..3aede2215ea --- /dev/null +++ b/tests/run-make/debugger-visualizer-dep-info/main.rs @@ -0,0 +1,12 @@ +#![debugger_visualizer(gdb_script_file = "foo.py")] + +fn main() { + const _UNUSED: u32 = { + mod inner { + #![debugger_visualizer(natvis_file = "my_visualizers/bar.natvis")] + pub const XYZ: u32 = 123; + } + + inner::XYZ + 1 + }; +} diff --git a/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis b/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis new file mode 100644 index 00000000000..c341a403902 --- /dev/null +++ b/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis @@ -0,0 +1 @@ +<!-- empty --> diff --git a/tests/run-make/incremental-debugger-visualizer/Makefile b/tests/run-make/incremental-debugger-visualizer/Makefile new file mode 100644 index 00000000000..8cfe41597ad --- /dev/null +++ b/tests/run-make/incremental-debugger-visualizer/Makefile @@ -0,0 +1,49 @@ +include ../tools.mk + +# This test makes sure that changes to files referenced via #[debugger_visualizer] +# are picked up when compiling incrementally. + +# We have to copy the source to $(TMPDIR) because Github CI mounts the source +# directory as readonly. We need to apply modifications to some of the source +# file. +SRC_DIR := $(TMPDIR)/src +INCR_CACHE_DIR := $(TMPDIR)/incremental + +all: + rm -rf $(TMPDIR)/* + mkdir $(SRC_DIR) + cp ./foo.rs $(SRC_DIR) + echo "GDB script v1" > $(SRC_DIR)/foo.py + echo "Natvis v1" > $(SRC_DIR)/foo.natvis + $(RUSTC) $(SRC_DIR)/foo.rs \ + --crate-type=rlib \ + --emit metadata \ + -C incremental=$(INCR_CACHE_DIR) \ + -Z incremental-verify-ich + $(CGREP) "GDB script v1" < $(TMPDIR)/libfoo.rmeta + $(CGREP) "Natvis v1" < $(TMPDIR)/libfoo.rmeta + + # Change only the GDB script and check that the change has been picked up + echo "GDB script v2" > $(SRC_DIR)/foo.py + $(RUSTC) $(SRC_DIR)/foo.rs \ + --crate-type=rlib \ + --emit metadata \ + -C incremental=$(INCR_CACHE_DIR) \ + -Z incremental-verify-ich + + $(CGREP) "GDB script v2" < $(TMPDIR)/libfoo.rmeta + $(CGREP) -v "GDB script v1" < $(TMPDIR)/libfoo.rmeta + $(CGREP) "Natvis v1" < $(TMPDIR)/libfoo.rmeta + + # Now change the Natvis version and check that the change has been picked up + echo "Natvis v2" > $(SRC_DIR)/foo.natvis + $(RUSTC) $(SRC_DIR)/foo.rs \ + --crate-type=rlib \ + --emit metadata \ + -C incremental=$(INCR_CACHE_DIR) \ + -Z incremental-verify-ich + + $(CGREP) "GDB script v2" < $(TMPDIR)/libfoo.rmeta + $(CGREP) -v "GDB script v1" < $(TMPDIR)/libfoo.rmeta + $(CGREP) "Natvis v2" < $(TMPDIR)/libfoo.rmeta + $(CGREP) -v "Natvis v1" < $(TMPDIR)/libfoo.rmeta diff --git a/tests/run-make/incremental-debugger-visualizer/foo.rs b/tests/run-make/incremental-debugger-visualizer/foo.rs new file mode 100644 index 00000000000..8daa36a12d3 --- /dev/null +++ b/tests/run-make/incremental-debugger-visualizer/foo.rs @@ -0,0 +1,6 @@ +#![debugger_visualizer(natvis_file = "./foo.natvis")] +#![debugger_visualizer(gdb_script_file = "./foo.py")] + +pub struct Foo { + pub x: u32, +} diff --git a/tests/rustdoc-gui/source-code-page.goml b/tests/rustdoc-gui/source-code-page.goml index 5c795928bdc..d5dd511b1d3 100644 --- a/tests/rustdoc-gui/source-code-page.goml +++ b/tests/rustdoc-gui/source-code-page.goml @@ -40,24 +40,24 @@ define-function: ( call-function: ("check-colors", { "theme": "ayu", - "color": "rgb(92, 103, 115)", - "background_color": "rgba(0, 0, 0, 0)", - "highlight_color": "rgb(112, 128, 144)", + "color": "#5c6773", + "background_color": "transparent", + "highlight_color": "#708090", "highlight_background_color": "rgba(255, 236, 164, 0.06)", }) call-function: ("check-colors", { "theme": "dark", - "color": "rgb(59, 145, 226)", - "background_color": "rgba(0, 0, 0, 0)", - "highlight_color": "rgb(59, 145, 226)", - "highlight_background_color": "rgb(10, 4, 47)", + "color": "#3b91e2", + "background_color": "transparent", + "highlight_color": "#3b91e2", + "highlight_background_color": "#0a042f", }) call-function: ("check-colors", { "theme": "light", - "color": "rgb(198, 126, 45)", - "background_color": "rgba(0, 0, 0, 0)", - "highlight_color": "rgb(198, 126, 45)", - "highlight_background_color": "rgb(253, 255, 211)", + "color": "#c67e2d", + "background_color": "transparent", + "highlight_color": "#c67e2d", + "highlight_background_color": "#fdffd3", }) // This is to ensure that the content is correctly align with the line numbers. diff --git a/tests/ui/imports/issue-109343.rs b/tests/ui/imports/issue-109343.rs new file mode 100644 index 00000000000..0c10259bcd7 --- /dev/null +++ b/tests/ui/imports/issue-109343.rs @@ -0,0 +1,10 @@ +#![crate_type = "lib"] + +pub mod f {} +pub use unresolved::f; +//~^ ERROR unresolved import `unresolved` + +/// [g] +pub use f as g; + +fn main() {} diff --git a/tests/ui/imports/issue-109343.stderr b/tests/ui/imports/issue-109343.stderr new file mode 100644 index 00000000000..8d9a3aee980 --- /dev/null +++ b/tests/ui/imports/issue-109343.stderr @@ -0,0 +1,11 @@ +error[E0432]: unresolved import `unresolved` + --> $DIR/issue-109343.rs:4:9 + | +LL | pub use unresolved::f; + | ^^^^^^^^^^ maybe a missing crate `unresolved`? + | + = help: consider adding `extern crate unresolved` to use the `unresolved` crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/invalid/foo.natvis.xml b/tests/ui/invalid/foo.natvis.xml new file mode 100644 index 00000000000..c341a403902 --- /dev/null +++ b/tests/ui/invalid/foo.natvis.xml @@ -0,0 +1 @@ +<!-- empty --> diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.rs b/tests/ui/invalid/invalid-debugger-visualizer-target.rs index f9dd20dbfed..1efb9555c24 100644 --- a/tests/ui/invalid/invalid-debugger-visualizer-target.rs +++ b/tests/ui/invalid/invalid-debugger-visualizer-target.rs @@ -1,2 +1,2 @@ -#[debugger_visualizer(natvis_file = "../foo.natvis")] //~ ERROR attribute should be applied to a module +#[debugger_visualizer(natvis_file = "./foo.natvis.xml")] //~ ERROR attribute should be applied to a module fn main() {} diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr index 7944f751859..c8a4d681379 100644 --- a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr +++ b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr @@ -1,8 +1,8 @@ error: attribute should be applied to a module --> $DIR/invalid-debugger-visualizer-target.rs:1:1 | -LL | #[debugger_visualizer(natvis_file = "../foo.natvis")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[debugger_visualizer(natvis_file = "./foo.natvis.xml")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/tests/ui/lint/unused/auxiliary/must-use-foreign.rs b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs new file mode 100644 index 00000000000..f773f09c382 --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs @@ -0,0 +1,12 @@ +// edition:2021 + +use std::future::Future; + +pub struct Manager; + +impl Manager { + #[must_use] + pub async fn new() -> (Self, impl Future<Output = ()>) { + (Manager, async {}) + } +} diff --git a/tests/ui/lint/unused/must-use-foreign.rs b/tests/ui/lint/unused/must-use-foreign.rs new file mode 100644 index 00000000000..21a11058562 --- /dev/null +++ b/tests/ui/lint/unused/must-use-foreign.rs @@ -0,0 +1,15 @@ +// edition:2021 +// aux-build:must-use-foreign.rs +// check-pass + +extern crate must_use_foreign; + +use must_use_foreign::Manager; + +async fn async_main() { + Manager::new().await.1.await; +} + +fn main() { + let _ = async_main(); +} diff --git a/tests/ui/lint/unused/unused-async.rs b/tests/ui/lint/unused/unused-async.rs index 4be93aa155a..6355f47f037 100644 --- a/tests/ui/lint/unused/unused-async.rs +++ b/tests/ui/lint/unused/unused-async.rs @@ -33,7 +33,7 @@ async fn test() { foo().await; //~ ERROR unused output of future returned by `foo` that must be used bar(); //~ ERROR unused return value of `bar` that must be used //~^ ERROR unused implementer of `Future` that must be used - bar().await; //~ ERROR unused output of future returned by `bar` that must be used + bar().await; // ok, it's not an async fn baz(); //~ ERROR unused implementer of `Future` that must be used baz().await; // ok } diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr index 1c3702ba265..e93a40658f3 100644 --- a/tests/ui/lint/unused/unused-async.stderr +++ b/tests/ui/lint/unused/unused-async.stderr @@ -52,17 +52,6 @@ help: use `let _ = ...` to ignore the resulting value LL | let _ = bar(); | +++++++ -error: unused output of future returned by `bar` that must be used - --> $DIR/unused-async.rs:36:5 - | -LL | bar().await; - | ^^^^^^^^^^^ - | -help: use `let _ = ...` to ignore the resulting value - | -LL | let _ = bar().await; - | +++++++ - error: unused implementer of `Future` that must be used --> $DIR/unused-async.rs:37:5 | @@ -71,5 +60,5 @@ LL | baz(); | = note: futures do nothing unless you `.await` or poll them -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/macros/issue-111749.rs b/tests/ui/macros/issue-111749.rs new file mode 100644 index 00000000000..6c45e4e8cd7 --- /dev/null +++ b/tests/ui/macros/issue-111749.rs @@ -0,0 +1,12 @@ +macro_rules! cbor_map { + ($key:expr) => { + $key.signum(); + }; +} + +fn main() { + cbor_map! { #[test(test)] 4}; + //~^ ERROR removing an expression is not supported in this position + //~| ERROR attribute must be of the form `#[test]` + //~| WARNING this was previously accepted by the compiler but is being phased out +} diff --git a/tests/ui/macros/issue-111749.stderr b/tests/ui/macros/issue-111749.stderr new file mode 100644 index 00000000000..7db2b8e6ad1 --- /dev/null +++ b/tests/ui/macros/issue-111749.stderr @@ -0,0 +1,18 @@ +error: removing an expression is not supported in this position + --> $DIR/issue-111749.rs:8:17 + | +LL | cbor_map! { #[test(test)] 4}; + | ^^^^^^^^^^^^^ + +error: attribute must be of the form `#[test]` + --> $DIR/issue-111749.rs:8:17 + | +LL | cbor_map! { #[test(test)] 4}; + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> + = note: `#[deny(ill_formed_attribute_input)]` on by default + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/panic-temporaries-2018.rs b/tests/ui/macros/panic-temporaries-2018.rs new file mode 100644 index 00000000000..d914df38062 --- /dev/null +++ b/tests/ui/macros/panic-temporaries-2018.rs @@ -0,0 +1,55 @@ +// check-pass +// edition:2018 + +#![allow(non_fmt_panics, unreachable_code)] + +use std::fmt::{self, Display}; +use std::marker::PhantomData; + +struct NotSend { + marker: PhantomData<*const u8>, +} + +const NOT_SEND: NotSend = NotSend { marker: PhantomData }; + +impl Display for NotSend { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("this value does not implement Send") + } +} + +async fn f(_: u8) {} + +// Exercises this matcher in panic_2015: +// ($fmt:expr, $($arg:tt)+) => $crate::panicking::panic_fmt(...) +async fn panic_fmt() { + // Panic returns `!`, so the await is never reached, and in particular the + // temporaries inside the formatting machinery are not still alive at the + // await point. + let todo = "..."; + f(panic!("not yet implemented: {}", todo)).await; +} + +// Exercises ("{}", $arg:expr) => $crate::panicking::panic_display(&$arg) +async fn panic_display() { + f(panic!("{}", NOT_SEND)).await; +} + +// Exercises ($msg:expr) => $crate::panicking::panic_str($msg) +async fn panic_str() { + f(panic!((NOT_SEND, "...").1)).await; +} + +// Exercises ($msg:expr) => $crate::panicking::unreachable_display(&$msg) +async fn unreachable_display() { + f(unreachable!(NOT_SEND)).await; +} + +fn require_send(_: impl Send) {} + +fn main() { + require_send(panic_fmt()); + require_send(panic_display()); + require_send(panic_str()); + require_send(unreachable_display()); +} diff --git a/tests/ui/macros/panic-temporaries.rs b/tests/ui/macros/panic-temporaries.rs index 5b5b8b7c2d9..db65601fb73 100644 --- a/tests/ui/macros/panic-temporaries.rs +++ b/tests/ui/macros/panic-temporaries.rs @@ -3,17 +3,41 @@ #![allow(unreachable_code)] +use std::fmt::{self, Display}; +use std::marker::PhantomData; + +struct NotSend { + marker: PhantomData<*const u8>, +} + +const NOT_SEND: NotSend = NotSend { marker: PhantomData }; + +impl Display for NotSend { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("this value does not implement Send") + } +} + async fn f(_: u8) {} -async fn g() { - // Todo returns `!`, so the await is never reached, and in particular the +// Exercises this matcher in panic_2021: +// ($($t:tt)+) => $crate::panicking::panic_fmt(...) +async fn panic_fmt() { + // Panic returns `!`, so the await is never reached, and in particular the // temporaries inside the formatting machinery are not still alive at the // await point. - f(todo!("...")).await; + let todo = "..."; + f(panic!("not yet implemented: {}", todo)).await; +} + +// Exercises ("{}", $arg:expr) => $crate::panicking::panic_display(&$arg) +async fn panic_display() { + f(panic!("{}", NOT_SEND)).await; } fn require_send(_: impl Send) {} fn main() { - require_send(g()); + require_send(panic_fmt()); + require_send(panic_display()); } diff --git a/tests/ui/offset-of/offset-of-dst-field.rs b/tests/ui/offset-of/offset-of-dst-field.rs index a0269ca2d12..89e73b8c6b8 100644 --- a/tests/ui/offset-of/offset-of-dst-field.rs +++ b/tests/ui/offset-of/offset-of-dst-field.rs @@ -26,8 +26,23 @@ struct Gamma { z: Extern, } +struct Delta<T: ?Sized> { + x: u8, + y: u16, + z: T, +} + fn main() { offset_of!(Alpha, z); //~ ERROR the size for values of type offset_of!(Beta, z); //~ ERROR the size for values of type offset_of!(Gamma, z); //~ ERROR the size for values of type } + +fn delta() { + offset_of!(Delta<Alpha>, z); //~ ERROR the size for values of type + offset_of!(Delta<Extern>, z); //~ ERROR the size for values of type +} + +fn generic_with_maybe_sized<T: ?Sized>() -> usize { + offset_of!(Delta<T>, z) //~ ERROR the size for values of type +} diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr index e6e0f499236..992eab3d4bd 100644 --- a/tests/ui/offset-of/offset-of-dst-field.stderr +++ b/tests/ui/offset-of/offset-of-dst-field.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/offset-of-dst-field.rs:30:5 + --> $DIR/offset-of-dst-field.rs:36:5 | LL | offset_of!(Alpha, z); | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -8,7 +8,7 @@ LL | offset_of!(Alpha, z); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/offset-of-dst-field.rs:31:5 + --> $DIR/offset-of-dst-field.rs:37:5 | LL | offset_of!(Beta, z); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -17,7 +17,7 @@ LL | offset_of!(Beta, z); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the size for values of type `Extern` cannot be known at compilation time - --> $DIR/offset-of-dst-field.rs:32:5 + --> $DIR/offset-of-dst-field.rs:38:5 | LL | offset_of!(Gamma, z); | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -25,6 +25,44 @@ LL | offset_of!(Gamma, z); = help: the trait `Sized` is not implemented for `Extern` = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors +error[E0277]: the size for values of type `Extern` cannot be known at compilation time + --> $DIR/offset-of-dst-field.rs:43:5 + | +LL | offset_of!(Delta<Extern>, z); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `Extern` + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/offset-of-dst-field.rs:42:5 + | +LL | offset_of!(Delta<Alpha>, z); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]` +note: required because it appears within the type `Alpha` + --> $DIR/offset-of-dst-field.rs:5:8 + | +LL | struct Alpha { + | ^^^^^ + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/offset-of-dst-field.rs:47:5 + | +LL | fn generic_with_maybe_sized<T: ?Sized>() -> usize { + | - this type parameter needs to be `std::marker::Sized` +LL | offset_of!(Delta<T>, z) + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn generic_with_maybe_sized<T: ?Sized>() -> usize { +LL + fn generic_with_maybe_sized<T>() -> usize { + | + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/offset-of/offset-of-output-type.rs b/tests/ui/offset-of/offset-of-output-type.rs new file mode 100644 index 00000000000..50c2e93841f --- /dev/null +++ b/tests/ui/offset-of/offset-of-output-type.rs @@ -0,0 +1,20 @@ +#![feature(offset_of)] + +use std::mem::offset_of; + +struct S { + v: u8, + w: u16, +} + + +fn main() { + let _: u8 = offset_of!(S, v); //~ ERROR mismatched types + let _: u16 = offset_of!(S, v); //~ ERROR mismatched types + let _: u32 = offset_of!(S, v); //~ ERROR mismatched types + let _: u64 = offset_of!(S, v); //~ ERROR mismatched types + let _: isize = offset_of!(S, v); //~ ERROR mismatched types + let _: usize = offset_of!(S, v); + + offset_of!(S, v) //~ ERROR mismatched types +} diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr new file mode 100644 index 00000000000..6f8c9475029 --- /dev/null +++ b/tests/ui/offset-of/offset-of-output-type.stderr @@ -0,0 +1,64 @@ +error[E0308]: mismatched types + --> $DIR/offset-of-output-type.rs:12:17 + | +LL | let _: u8 = offset_of!(S, v); + | -- ^^^^^^^^^^^^^^^^ expected `u8`, found `usize` + | | + | expected due to this + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/offset-of-output-type.rs:13:18 + | +LL | let _: u16 = offset_of!(S, v); + | --- ^^^^^^^^^^^^^^^^ expected `u16`, found `usize` + | | + | expected due to this + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/offset-of-output-type.rs:14:18 + | +LL | let _: u32 = offset_of!(S, v); + | --- ^^^^^^^^^^^^^^^^ expected `u32`, found `usize` + | | + | expected due to this + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/offset-of-output-type.rs:15:18 + | +LL | let _: u64 = offset_of!(S, v); + | --- ^^^^^^^^^^^^^^^^ expected `u64`, found `usize` + | | + | expected due to this + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/offset-of-output-type.rs:16:20 + | +LL | let _: isize = offset_of!(S, v); + | ----- ^^^^^^^^^^^^^^^^ expected `isize`, found `usize` + | | + | expected due to this + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/offset-of-output-type.rs:19:5 + | +LL | fn main() { + | - expected `()` because of default return type +... +LL | offset_of!(S, v) + | ^^^^^^^^^^^^^^^^ expected `()`, found `usize` + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs index 0291b7825ca..6b1a16ba62b 100644 --- a/tests/ui/offset-of/offset-of-private.rs +++ b/tests/ui/offset-of/offset-of-private.rs @@ -8,9 +8,21 @@ mod m { pub public: u8, private: u8, } + #[repr(C)] + pub struct FooTuple(pub u8, u8); + #[repr(C)] + struct Bar { + pub public: u8, + private: u8, + } } fn main() { offset_of!(m::Foo, public); offset_of!(m::Foo, private); //~ ERROR field `private` of struct `Foo` is private + offset_of!(m::FooTuple, 0); + offset_of!(m::FooTuple, 1); //~ ERROR field `1` of struct `FooTuple` is private + offset_of!(m::Bar, public); //~ ERROR struct `Bar` is private + offset_of!(m::Bar, private); //~ ERROR struct `Bar` is private + //~| ERROR field `private` of struct `Bar` is private } diff --git a/tests/ui/offset-of/offset-of-private.stderr b/tests/ui/offset-of/offset-of-private.stderr index 8a186dd5a02..0674b58f860 100644 --- a/tests/ui/offset-of/offset-of-private.stderr +++ b/tests/ui/offset-of/offset-of-private.stderr @@ -1,9 +1,46 @@ +error[E0603]: struct `Bar` is private + --> $DIR/offset-of-private.rs:25:19 + | +LL | offset_of!(m::Bar, public); + | ^^^ private struct + | +note: the struct `Bar` is defined here + --> $DIR/offset-of-private.rs:14:5 + | +LL | struct Bar { + | ^^^^^^^^^^ + +error[E0603]: struct `Bar` is private + --> $DIR/offset-of-private.rs:26:19 + | +LL | offset_of!(m::Bar, private); + | ^^^ private struct + | +note: the struct `Bar` is defined here + --> $DIR/offset-of-private.rs:14:5 + | +LL | struct Bar { + | ^^^^^^^^^^ + error[E0616]: field `private` of struct `Foo` is private - --> $DIR/offset-of-private.rs:15:24 + --> $DIR/offset-of-private.rs:22:24 | LL | offset_of!(m::Foo, private); | ^^^^^^^ private field -error: aborting due to previous error +error[E0616]: field `1` of struct `FooTuple` is private + --> $DIR/offset-of-private.rs:24:29 + | +LL | offset_of!(m::FooTuple, 1); + | ^ private field + +error[E0616]: field `private` of struct `Bar` is private + --> $DIR/offset-of-private.rs:26:24 + | +LL | offset_of!(m::Bar, private); + | ^^^^^^^ private field + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0616`. +Some errors have detailed explanations: E0603, E0616. +For more information about an error, try `rustc --explain E0603`. diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs new file mode 100644 index 00000000000..dbeef0e74dc --- /dev/null +++ b/tests/ui/offset-of/offset-of-self.rs @@ -0,0 +1,58 @@ +#![feature(offset_of)] + +use std::mem::offset_of; + +struct C<T> { + v: T, + w: T, +} + +struct S { + v: u8, + w: u16, +} + +impl S { + fn v_offs() -> usize { + offset_of!(Self, v) + } + fn v_offs_wrong_syntax() { + offset_of!(Self, Self::v); //~ ERROR no rules expected the token `::` + offset_of!(S, Self); //~ ERROR expected identifier, found keyword `Self` + //~| no field `Self` on type `S` + } + fn offs_in_c() -> usize { + offset_of!(C<Self>, w) + } + fn offs_in_c_colon() -> usize { + offset_of!(C::<Self>, w) + } +} + +mod m { + use std::mem::offset_of; + fn off() { + offset_of!(self::S, v); //~ ERROR cannot find type `S` in module + offset_of!(super::S, v); + offset_of!(crate::S, v); + } + impl super::n::T { + fn v_offs_self() -> usize { + offset_of!(Self, v) //~ ERROR field `v` of struct `T` is private + } + } +} + +mod n { + pub struct T { v: u8, } +} + +fn main() { + offset_of!(self::S, v); + offset_of!(Self, v); //~ ERROR cannot find type `Self` in this scope + + offset_of!(S, self); //~ ERROR expected identifier, found keyword `self` + //~| no field `self` on type `S` + offset_of!(S, v.self); //~ ERROR expected identifier, found keyword `self` + //~| no field `self` on type `u8` +} diff --git a/tests/ui/offset-of/offset-of-self.stderr b/tests/ui/offset-of/offset-of-self.stderr new file mode 100644 index 00000000000..df555463f98 --- /dev/null +++ b/tests/ui/offset-of/offset-of-self.stderr @@ -0,0 +1,79 @@ +error: no rules expected the token `::` + --> $DIR/offset-of-self.rs:20:30 + | +LL | offset_of!(Self, Self::v); + | ^^ no rules expected this token in macro call + | + = note: while trying to match sequence start + +error: expected identifier, found keyword `Self` + --> $DIR/offset-of-self.rs:21:23 + | +LL | offset_of!(S, Self); + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `self` + --> $DIR/offset-of-self.rs:54:19 + | +LL | offset_of!(S, self); + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `self` + --> $DIR/offset-of-self.rs:56:21 + | +LL | offset_of!(S, v.self); + | ^^^^ expected identifier, found keyword + +error[E0412]: cannot find type `S` in module `self` + --> $DIR/offset-of-self.rs:35:26 + | +LL | offset_of!(self::S, v); + | ^ not found in `self` + | +help: consider importing this struct + | +LL + use S; + | +help: if you import `S`, refer to it directly + | +LL - offset_of!(self::S, v); +LL + offset_of!(S, v); + | + +error[E0411]: cannot find type `Self` in this scope + --> $DIR/offset-of-self.rs:52:16 + | +LL | fn main() { + | ---- `Self` not allowed in a function +LL | offset_of!(self::S, v); +LL | offset_of!(Self, v); + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error[E0609]: no field `Self` on type `S` + --> $DIR/offset-of-self.rs:21:23 + | +LL | offset_of!(S, Self); + | ^^^^ + +error[E0616]: field `v` of struct `T` is private + --> $DIR/offset-of-self.rs:41:30 + | +LL | offset_of!(Self, v) + | ^ private field + +error[E0609]: no field `self` on type `S` + --> $DIR/offset-of-self.rs:54:19 + | +LL | offset_of!(S, self); + | ^^^^ + +error[E0609]: no field `self` on type `u8` + --> $DIR/offset-of-self.rs:56:21 + | +LL | offset_of!(S, v.self); + | ^^^^ + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0411, E0412, E0609, E0616. +For more information about an error, try `rustc --explain E0411`. diff --git a/tests/ui/traits/copy-guessing.rs b/tests/ui/traits/copy-guessing.rs index 558303c2e40..c1ed4c28a03 100644 --- a/tests/ui/traits/copy-guessing.rs +++ b/tests/ui/traits/copy-guessing.rs @@ -1,5 +1,3 @@ -// run-pass - #![allow(dead_code)] #![allow(drop_copy)] @@ -20,6 +18,7 @@ fn assert_impls_fn<R,T: Fn()->R>(_: &T){} fn main() { let n = None; + //~^ ERROR type annotations needed for `Option<T>` let e = S(&n); let f = || { // S being copy is critical for this to work diff --git a/tests/ui/traits/copy-guessing.stderr b/tests/ui/traits/copy-guessing.stderr new file mode 100644 index 00000000000..568b7e5a64a --- /dev/null +++ b/tests/ui/traits/copy-guessing.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `Option<T>` + --> $DIR/copy-guessing.rs:20:9 + | +LL | let n = None; + | ^ + | +help: consider giving `n` an explicit type, where the type for type parameter `T` is specified + | +LL | let n: Option<T> = None; + | +++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/use/use-self-type.stderr b/tests/ui/use/use-self-type.stderr index e6153941151..3da04a851f6 100644 --- a/tests/ui/use/use-self-type.stderr +++ b/tests/ui/use/use-self-type.stderr @@ -8,7 +8,7 @@ error[E0432]: unresolved import `Self` --> $DIR/use-self-type.rs:6:13 | LL | use Self::f; - | ^^^^ `Self` is only available in impls, traits, and type definitions + | ^^^^ `Self` cannot be used in imports error: aborting due to 2 previous errors |
