diff --git a/Cargo.lock b/Cargo.lock index ecd42d6d4a36a..90fc5604d812a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1926,6 +1926,17 @@ dependencies = [ "rustc-hash", ] +[[package]] +name = "measureme" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22bf8d885d073610aee20e7fa205c4341ed32a761dbde96da5fd96301a8d3e82" +dependencies = [ + "parking_lot 0.11.0", + "rustc-hash", + "smallvec 1.4.2", +] + [[package]] name = "memchr" version = "2.3.3" @@ -2636,9 +2647,9 @@ dependencies = [ [[package]] name = "racer" -version = "2.1.39" +version = "2.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9424b4650b9c1134d0a1b34dab82319691e1c95fa8af1658fc640deb1b6823c" +checksum = "68c5fb83bc092c10e12ca863ab8922b1833382d5d248aaafca779886d3396a44" dependencies = [ "bitflags", "clap", @@ -2963,19 +2974,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e941a8fc3878a111d2bbfe78e39522d884136f0b412b12592195f26f653476" +checksum = "477085eefed2f12085c68577cc3827c8c39a31a4a750978aacb9af10f7903174" dependencies = [ - "rustc-ap-rustc_data_structures", "smallvec 1.4.2", ] [[package]] name = "rustc-ap-rustc_ast" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b58b6b035710df7f339a2bf86f6dafa876efd95439540970e24609e33598ca6" +checksum = "4d4ad5ec25f6b3d122354595be0d1b513f37fca3299d9b448b1db28f4a9e4b12" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -2990,9 +3000,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_passes" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d379a900d6a1f098490d92ab83e87487dcee2e4ec3f04c3ac4512b5117b64e2" +checksum = "0c6d8635298d7736decdb3c6e92e784d3eccde557462a9c10ac11a34fec3d756" dependencies = [ "itertools 0.9.0", "rustc-ap-rustc_ast", @@ -3009,9 +3019,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658d925c0da9e3c5cddc5e54f4fa8c03b41aff1fc6dc5e41837c1118ad010ac0" +checksum = "7a61bdb5252e1a95b7715038949e10f07ce770a436fcd497cdd9bc7255471de9" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_span", @@ -3021,9 +3031,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_attr" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f387037534f34c148aed753622677500e42d190a095670e7ac3fffc09811a59" +checksum = "84520a16cb61bd31e9c27e87eca5d933a9c94ac84f25649bddcc19989275ab2a" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", @@ -3040,10 +3050,11 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14ffd17a37e00d77926a0713f191c59ff3aeb2b551a024c7cfffce14bab79be8" +checksum = "b1cb2b6a38759cf7c0c1434c8b4cbfcab9cd24970d05f960f2ca01226ddb4d68" dependencies = [ + "arrayvec", "bitflags", "cfg-if", "crossbeam-utils 0.7.2", @@ -3051,7 +3062,7 @@ dependencies = [ "indexmap", "jobserver", "libc", - "measureme", + "measureme 9.0.0", "parking_lot 0.11.0", "rustc-ap-rustc_graphviz", "rustc-ap-rustc_index", @@ -3070,9 +3081,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b3263ddcfa9eb911e54a4e8088878dd9fd10e00d8b99b01033ba4a2733fe91d" +checksum = "46cfb19536426bf9252827a78552d635be207a4be74f4e92832aad82d7f2135c" dependencies = [ "annotate-snippets 0.8.0", "atty", @@ -3089,9 +3100,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1ab7e68cede8a2273fd8b8623002ce9dc832e061dfc3330e9bcc1fc2a722d73" +checksum = "6273e60042a0ef31f6cfe783c519873993eb426f055be2bc058a48b6ca3934d0" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_passes", @@ -3112,9 +3123,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_feature" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea2dc95421bc19bbd4d939399833a882c46b684283b4267ad1fcf982fc043d9" +checksum = "2936e8346157e2848305e509f38aa3ed4e97697975ef68027587f5db6a38703f" dependencies = [ "rustc-ap-rustc_data_structures", "rustc-ap-rustc_span", @@ -3122,21 +3133,21 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_fs_util" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e44c1804f09635f83f6cf1e04c2e92f8aeb7b4e850ac6c53d373dab02c13053" +checksum = "9b4c3ae17776b5a5aa441ca510a650f75805e1f5569edd231caa8378552195a4" [[package]] name = "rustc-ap-rustc_graphviz" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc491f2b9be6e928f6df6b287549b8d50c48e8eff8638345155f40fa2cfb785d" +checksum = "5611bf0ac0ac49c2a22c959c7d8b17f85f69959293f0e8c4f753eca832fe7ad0" [[package]] name = "rustc-ap-rustc_index" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa73f3fed413cdb6290738a10267da17b9ae8e02087334778b9a8c9491c5efc0" +checksum = "ca67cf37c427057192e451c7f912e94ae9a8ca5ad69fd481c011fad3f86982cb" dependencies = [ "arrayvec", "rustc-ap-rustc_macros", @@ -3145,18 +3156,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_lexer" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e993881244a92f3b44cf43c8f22ae2ca5cefe4f55a34e2b65b72ee66fe5ad077" +checksum = "a5b04cd2159495584d976d501c5394498470c2e94e4f0cebb8186562d407a678" dependencies = [ "unicode-xid", ] [[package]] name = "rustc-ap-rustc_macros" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4effe366556e1d75344764adf4d54cba7c2fad33dbd07588e96d0853831ddc7c" +checksum = "61ec6d623853449acd3c65050d249d3674edab5f6e4d9f074c7bac183269f9c8" dependencies = [ "proc-macro2", "quote", @@ -3166,9 +3177,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0342675835251571471d3dca9ea1576a853a8dfa1f4b0084db283c861223cb60" +checksum = "ca524bafce4b04d2b49fee2d40b4b26c3ebab9f1a4f731fdf561f00617862f02" dependencies = [ "bitflags", "rustc-ap-rustc_ast", @@ -3186,9 +3197,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_serialize" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "438255ed968d73bf6573aa18d3b8d33c0a85ecdfd14160ef09ff813938e0606c" +checksum = "c67920561e58f98c4de864407c92b2dd05ace5d5e5301e17444f10f742c005b7" dependencies = [ "indexmap", "smallvec 1.4.2", @@ -3196,9 +3207,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_session" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d61ff76dede8eb827f6805754900d1097a7046f938f950231b62b448f55bf78" +checksum = "0762fd855792e06ef639327237898e4e092ad68150e6a8e19aeb7dc06276ad7a" dependencies = [ "bitflags", "getopts", @@ -3217,9 +3228,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_span" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c267f15c3cfc82a8a441d2bf86bcccf299d1eb625822468e3d8ee6f7c5a1c89" +checksum = "0bf3db7b4ca5d21c14c45475df155e5e020c9a3760346945a662c9a9053b49c8" dependencies = [ "cfg-if", "md-5", @@ -3236,9 +3247,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "679.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1b4b266c4d44aac0f7f83b6741d8f0545b03d1ce32f3b5254f2014225cb96c" +checksum = "3aa6560bb9742b276064d67ab9edb5766ecb303f8ae3854835ad3fad4b432188" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -3323,6 +3334,7 @@ dependencies = [ name = "rustc-workspace-hack" version = "1.0.0" dependencies = [ + "byteorder", "crossbeam-utils 0.7.2", "proc-macro2", "quote", @@ -3454,7 +3466,7 @@ version = "0.0.0" dependencies = [ "bitflags", "libc", - "measureme", + "measureme 0.7.1", "rustc-demangle", "rustc_ast", "rustc_attr", @@ -3520,7 +3532,7 @@ dependencies = [ "indexmap", "jobserver", "libc", - "measureme", + "measureme 0.7.1", "parking_lot 0.11.0", "rustc-hash", "rustc-rayon", @@ -3824,7 +3836,7 @@ version = "0.0.0" dependencies = [ "bitflags", "chalk-ir", - "measureme", + "measureme 0.7.1", "polonius-engine", "rustc-rayon-core", "rustc_apfloat", @@ -4255,7 +4267,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.22" +version = "1.4.24" dependencies = [ "annotate-snippets 0.6.1", "anyhow", diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs index bc3d1ce53bac5..5f42d46e28575 100644 --- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs +++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs @@ -1,6 +1,7 @@ use super::{DirectedGraph, WithNumNodes, WithStartNode, WithSuccessors}; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; +use std::ops::ControlFlow; #[cfg(test)] mod tests; @@ -86,10 +87,6 @@ where } } -/// Allows searches to terminate early with a value. -// FIXME (#75744): remove the alias once the generics are in a better order and `C=()`. -pub type ControlFlow = std::ops::ControlFlow<(), T>; - /// The status of a node in the depth-first search. /// /// See the documentation of `TriColorDepthFirstSearch` to see how a node's status is updated diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 544efc124e117..a3391ca7da5ab 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -134,9 +134,52 @@ pub fn diagnostics_registry() -> Registry { Registry::new(&rustc_error_codes::DIAGNOSTICS) } +pub struct RunCompiler<'a, 'b> { + at_args: &'a [String], + callbacks: &'b mut (dyn Callbacks + Send), + file_loader: Option>, + emitter: Option>, + make_codegen_backend: + Option Box + Send>>, +} + +impl<'a, 'b> RunCompiler<'a, 'b> { + pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self { + Self { at_args, callbacks, file_loader: None, emitter: None, make_codegen_backend: None } + } + pub fn set_make_codegen_backend( + &mut self, + make_codegen_backend: Option< + Box Box + Send>, + >, + ) -> &mut Self { + self.make_codegen_backend = make_codegen_backend; + self + } + pub fn set_emitter(&mut self, emitter: Option>) -> &mut Self { + self.emitter = emitter; + self + } + pub fn set_file_loader( + &mut self, + file_loader: Option>, + ) -> &mut Self { + self.file_loader = file_loader; + self + } + pub fn run(self) -> interface::Result<()> { + run_compiler( + self.at_args, + self.callbacks, + self.file_loader, + self.emitter, + self.make_codegen_backend, + ) + } +} // Parse args and run the compiler. This is the primary entry point for rustc. // The FileLoader provides a way to load files from sources other than the file system. -pub fn run_compiler( +fn run_compiler( at_args: &[String], callbacks: &mut (dyn Callbacks + Send), file_loader: Option>, @@ -1275,7 +1318,7 @@ pub fn main() -> ! { }) }) .collect::>(); - run_compiler(&args, &mut callbacks, None, None, None) + RunCompiler::new(&args, &mut callbacks).run() }); // The extra `\t` is necessary to align this label with the others. print_time_passes_entry(callbacks.time_passes, "\ttotal", start.elapsed()); diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index a8d7c612a8419..45a89c40b4ed5 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -1,5 +1,5 @@ use rustc_data_structures::graph::iterate::{ - ControlFlow, NodeStatus, TriColorDepthFirstSearch, TriColorVisitor, + NodeStatus, TriColorDepthFirstSearch, TriColorVisitor, }; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; @@ -9,6 +9,7 @@ use rustc_middle::ty::subst::{GenericArg, InternalSubsts}; use rustc_middle::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt}; use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION; use rustc_span::Span; +use std::ops::ControlFlow; crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: LocalDefId) { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index adff4542b0ff8..bf8a2f269dd57 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -875,6 +875,12 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// consolidate multiple unresolved import errors into a single diagnostic. fn finalize_import(&mut self, import: &'b Import<'b>) -> Option { let orig_vis = import.vis.replace(ty::Visibility::Invisible); + let orig_unusable_binding = match &import.kind { + ImportKind::Single { target_bindings, .. } => { + Some(mem::replace(&mut self.r.unusable_binding, target_bindings[TypeNS].get())) + } + _ => None, + }; let prev_ambiguity_errors_len = self.r.ambiguity_errors.len(); let path_res = self.r.resolve_path( &import.module_path, @@ -885,6 +891,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> { import.crate_lint(), ); let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len; + if let Some(orig_unusable_binding) = orig_unusable_binding { + self.r.unusable_binding = orig_unusable_binding; + } import.vis.set(orig_vis); if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res { // Consider erroneous imports used to avoid duplicate diagnostics. @@ -895,8 +904,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // Consistency checks, analogous to `finalize_macro_resolutions`. if let Some(initial_module) = import.imported_module.get() { if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity { - let msg = "inconsistent resolution for an import"; - self.r.session.span_err(import.span, msg); + span_bug!(import.span, "inconsistent resolution for an import"); } } else { if self.r.privacy_errors.is_empty() { @@ -918,6 +926,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } PathResult::Failed { is_error_from_last_segment: true, span, label, suggestion } => { if no_ambiguity { + assert!(import.imported_module.get().is_none()); let err = match self.make_path_suggestion( span, import.module_path.clone(), diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 1e520b62f77c4..a725fb007e481 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1280,7 +1280,7 @@ where #[inline] fn find( f: &mut impl FnMut(T) -> Option, - ) -> impl FnMut((), T) -> ControlFlow<(), B> + '_ { + ) -> impl FnMut((), T) -> ControlFlow + '_ { move |(), x| match f(x) { Some(x) => ControlFlow::Break(x), None => ControlFlow::CONTINUE, @@ -2059,7 +2059,7 @@ where flag: &'a mut bool, p: &'a mut impl FnMut(&T) -> bool, mut fold: impl FnMut(Acc, T) -> R + 'a, - ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { + ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { move |acc, x| { if p(&x) { ControlFlow::from_try(fold(acc, x)) @@ -2372,7 +2372,7 @@ where fn check>( mut n: usize, mut fold: impl FnMut(Acc, T) -> R, - ) -> impl FnMut(Acc, T) -> ControlFlow { + ) -> impl FnMut(Acc, T) -> ControlFlow { move |acc, x| { n -= 1; let r = fold(acc, x); @@ -2500,7 +2500,7 @@ where fn check<'a, T, Acc, R: Try>( n: &'a mut usize, mut fold: impl FnMut(Acc, T) -> R + 'a, - ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { + ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { move |acc, x| { *n -= 1; let r = fold(acc, x); @@ -2685,7 +2685,7 @@ where state: &'a mut St, f: &'a mut impl FnMut(&mut St, T) -> Option, mut fold: impl FnMut(Acc, B) -> R + 'a, - ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { + ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { move |acc, x| match f(state, x) { None => ControlFlow::Break(Try::from_ok(acc)), Some(x) => ControlFlow::from_try(fold(acc, x)), diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index 16bee0e2eee18..2280799643055 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -336,9 +336,7 @@ pub trait DoubleEndedIterator: Iterator { P: FnMut(&Self::Item) -> bool, { #[inline] - fn check( - mut predicate: impl FnMut(&T) -> bool, - ) -> impl FnMut((), T) -> ControlFlow<(), T> { + fn check(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow { move |(), x| { if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 813afcc0ec6e4..a1d8deb0aca22 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2109,7 +2109,7 @@ pub trait Iterator { F: FnMut(Self::Item) -> bool, { #[inline] - fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> { + fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> { move |(), x| { if f(x) { ControlFlow::CONTINUE } else { ControlFlow::BREAK } } @@ -2162,7 +2162,7 @@ pub trait Iterator { F: FnMut(Self::Item) -> bool, { #[inline] - fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<(), ()> { + fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> { move |(), x| { if f(x) { ControlFlow::BREAK } else { ControlFlow::CONTINUE } } @@ -2222,9 +2222,7 @@ pub trait Iterator { P: FnMut(&Self::Item) -> bool, { #[inline] - fn check( - mut predicate: impl FnMut(&T) -> bool, - ) -> impl FnMut((), T) -> ControlFlow<(), T> { + fn check(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow { move |(), x| { if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE } } @@ -2255,9 +2253,7 @@ pub trait Iterator { F: FnMut(Self::Item) -> Option, { #[inline] - fn check( - mut f: impl FnMut(T) -> Option, - ) -> impl FnMut((), T) -> ControlFlow<(), B> { + fn check(mut f: impl FnMut(T) -> Option) -> impl FnMut((), T) -> ControlFlow { move |(), x| match f(x) { Some(x) => ControlFlow::Break(x), None => ControlFlow::CONTINUE, @@ -2296,7 +2292,7 @@ pub trait Iterator { R: Try, { #[inline] - fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow<(), Result> + fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> where F: FnMut(&T) -> R, R: Try, diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index b0c7dc1a51875..5ede1ba8e2c10 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -3,7 +3,7 @@ use crate::ops::Try; /// Used to make try_fold closures more like normal loops #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[derive(Debug, Clone, Copy, PartialEq)] -pub enum ControlFlow { +pub enum ControlFlow { /// Continue in the loop, using the given value for the next iteration Continue(C), /// Exit the loop, yielding the given value @@ -11,7 +11,7 @@ pub enum ControlFlow { } #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] -impl Try for ControlFlow { +impl Try for ControlFlow { type Ok = C; type Error = B; #[inline] @@ -31,7 +31,21 @@ impl Try for ControlFlow { } } -impl ControlFlow { +impl ControlFlow { + /// Returns `true` if this is a `Break` variant. + #[inline] + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + pub fn is_break(&self) -> bool { + matches!(*self, ControlFlow::Break(_)) + } + + /// Returns `true` if this is a `Continue` variant. + #[inline] + #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + pub fn is_continue(&self) -> bool { + matches!(*self, ControlFlow::Continue(_)) + } + /// Converts the `ControlFlow` into an `Option` which is `Some` if the /// `ControlFlow` was `Break` and `None` otherwise. #[inline] @@ -44,7 +58,7 @@ impl ControlFlow { } } -impl ControlFlow { +impl ControlFlow { /// Create a `ControlFlow` from any type implementing `Try`. #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[inline] @@ -66,7 +80,7 @@ impl ControlFlow { } } -impl ControlFlow<(), B> { +impl ControlFlow { /// It's frequently the case that there's no value needed with `Continue`, /// so this provides a way to avoid typing `(())`, if you prefer it. /// @@ -88,7 +102,7 @@ impl ControlFlow<(), B> { pub const CONTINUE: Self = ControlFlow::Continue(()); } -impl ControlFlow { +impl ControlFlow<(), C> { /// APIs like `try_for_each` don't need values with `Break`, /// so this provides a way to avoid typing `(())`, if you prefer it. /// diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 9f0284d5d9542..b73cd046e5a65 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -781,6 +781,34 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { } } +impl Pin<&'static T> { + /// Get a pinned reference from a static reference. + /// + /// This is safe, because `T` is borrowed for the `'static` lifetime, which + /// never ends. + #[unstable(feature = "pin_static_ref", issue = "none")] + #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + pub const fn static_ref(r: &'static T) -> Pin<&'static T> { + // SAFETY: The 'static borrow guarantees the data will not be + // moved/invalidated until it gets dropped (which is never). + unsafe { Pin::new_unchecked(r) } + } +} + +impl Pin<&'static mut T> { + /// Get a pinned mutable reference from a static mutable reference. + /// + /// This is safe, because `T` is borrowed for the `'static` lifetime, which + /// never ends. + #[unstable(feature = "pin_static_ref", issue = "none")] + #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + pub const fn static_mut(r: &'static mut T) -> Pin<&'static mut T> { + // SAFETY: The 'static borrow guarantees the data will not be + // moved/invalidated until it gets dropped (which is never). + unsafe { Pin::new_unchecked(r) } + } +} + #[stable(feature = "pin", since = "1.33.0")] impl Deref for Pin

{ type Target = P::Target; diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 36b49401591f5..b68e538c19fb6 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -9,6 +9,7 @@ use crate::cell::RefCell; use crate::fmt; use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter}; use crate::lazy::SyncOnceCell; +use crate::pin::Pin; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sync::{Mutex, MutexGuard}; use crate::sys::stdio; @@ -488,7 +489,7 @@ pub struct Stdout { // FIXME: this should be LineWriter or BufWriter depending on the state of // stdout (tty or not). Note that if this is not line buffered it // should also flush-on-panic or some form of flush-on-abort. - inner: &'static ReentrantMutex>>, + inner: Pin<&'static ReentrantMutex>>>, } /// A locked reference to the `Stdout` handle. @@ -548,25 +549,29 @@ pub struct StdoutLock<'a> { pub fn stdout() -> Stdout { static INSTANCE: SyncOnceCell>>> = SyncOnceCell::new(); + + fn cleanup() { + if let Some(instance) = INSTANCE.get() { + // Flush the data and disable buffering during shutdown + // by replacing the line writer by one with zero + // buffering capacity. + // We use try_lock() instead of lock(), because someone + // might have leaked a StdoutLock, which would + // otherwise cause a deadlock here. + if let Some(lock) = Pin::static_ref(instance).try_lock() { + *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw()); + } + } + } + Stdout { - inner: INSTANCE.get_or_init(|| unsafe { - let _ = sys_common::at_exit(|| { - if let Some(instance) = INSTANCE.get() { - // Flush the data and disable buffering during shutdown - // by replacing the line writer by one with zero - // buffering capacity. - // We use try_lock() instead of lock(), because someone - // might have leaked a StdoutLock, which would - // otherwise cause a deadlock here. - if let Some(lock) = instance.try_lock() { - *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw()); - } - } - }); - let r = ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))); - r.init(); - r - }), + inner: Pin::static_ref(&INSTANCE).get_or_init_pin( + || unsafe { + let _ = sys_common::at_exit(cleanup); + ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))) + }, + |mutex| unsafe { mutex.init() }, + ), } } @@ -698,7 +703,7 @@ impl fmt::Debug for StdoutLock<'_> { /// an error. #[stable(feature = "rust1", since = "1.0.0")] pub struct Stderr { - inner: &'static ReentrantMutex>, + inner: Pin<&'static ReentrantMutex>>, } /// A locked reference to the `Stderr` handle. @@ -754,21 +759,16 @@ pub struct StderrLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { - // Note that unlike `stdout()` we don't use `Lazy` here which registers a - // destructor. Stderr is not buffered nor does the `stderr_raw` type consume - // any owned resources, so there's no need to run any destructors at some - // point in the future. - // - // This has the added benefit of allowing `stderr` to be usable during - // process shutdown as well! + // Note that unlike `stdout()` we don't use `at_exit` here to register a + // destructor. Stderr is not buffered , so there's no need to run a + // destructor for flushing the buffer static INSTANCE: SyncOnceCell>> = SyncOnceCell::new(); Stderr { - inner: INSTANCE.get_or_init(|| unsafe { - let r = ReentrantMutex::new(RefCell::new(stderr_raw())); - r.init(); - r - }), + inner: Pin::static_ref(&INSTANCE).get_or_init_pin( + || unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) }, + |mutex| unsafe { mutex.init() }, + ), } } diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs index e0095e64faf31..68f57958bb233 100644 --- a/library/std/src/lazy.rs +++ b/library/std/src/lazy.rs @@ -10,6 +10,7 @@ use crate::{ mem::MaybeUninit, ops::{Deref, Drop}, panic::{RefUnwindSafe, UnwindSafe}, + pin::Pin, sync::Once, }; @@ -297,6 +298,60 @@ impl SyncOnceCell { Ok(unsafe { self.get_unchecked() }) } + /// Internal-only API that gets the contents of the cell, initializing it + /// in two steps with `f` and `g` if the cell was empty. + /// + /// `f` is called to construct the value, which is then moved into the cell + /// and given as a (pinned) mutable reference to `g` to finish + /// initialization. + /// + /// This allows `g` to inspect an manipulate the value after it has been + /// moved into its final place in the cell, but before the cell is + /// considered initialized. + /// + /// # Panics + /// + /// If `f` or `g` panics, the panic is propagated to the caller, and the + /// cell remains uninitialized. + /// + /// With the current implementation, if `g` panics, the value from `f` will + /// not be dropped. This should probably be fixed if this is ever used for + /// a type where this matters. + /// + /// It is an error to reentrantly initialize the cell from `f`. The exact + /// outcome is unspecified. Current implementation deadlocks, but this may + /// be changed to a panic in the future. + pub(crate) fn get_or_init_pin(self: Pin<&Self>, f: F, g: G) -> Pin<&T> + where + F: FnOnce() -> T, + G: FnOnce(Pin<&mut T>), + { + if let Some(value) = self.get_ref().get() { + // SAFETY: The inner value was already initialized, and will not be + // moved anymore. + return unsafe { Pin::new_unchecked(value) }; + } + + let slot = &self.value; + + // Ignore poisoning from other threads + // If another thread panics, then we'll be able to run our closure + self.once.call_once_force(|_| { + let value = f(); + // SAFETY: We use the Once (self.once) to guarantee unique access + // to the UnsafeCell (slot). + let value: &mut T = unsafe { (&mut *slot.get()).write(value) }; + // SAFETY: The value has been written to its final place in + // self.value. We do not to move it anymore, which we promise here + // with a Pin<&mut T>. + g(unsafe { Pin::new_unchecked(value) }); + }); + + // SAFETY: The inner value has been initialized, and will not be moved + // anymore. + unsafe { Pin::new_unchecked(self.get_ref().get_unchecked()) } + } + /// Consumes the `SyncOnceCell`, returning the wrapped value. Returns /// `None` if the cell was empty. /// diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index b2bd5f4da5012..5aa9d6a3562f1 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -264,6 +264,7 @@ #![feature(format_args_nl)] #![feature(gen_future)] #![feature(generator_trait)] +#![feature(get_mut_unchecked)] #![feature(global_asm)] #![feature(hashmap_internals)] #![feature(int_error_internals)] @@ -290,6 +291,7 @@ #![feature(panic_info_message)] #![feature(panic_internals)] #![feature(panic_unwind)] +#![feature(pin_static_ref)] #![feature(prelude_import)] #![feature(ptr_internals)] #![feature(raw)] diff --git a/library/std/src/sys_common/remutex.rs b/library/std/src/sys_common/remutex.rs index 162eab2388d55..475bfca9b6dcc 100644 --- a/library/std/src/sys_common/remutex.rs +++ b/library/std/src/sys_common/remutex.rs @@ -1,10 +1,10 @@ #[cfg(all(test, not(target_os = "emscripten")))] mod tests; -use crate::fmt; -use crate::marker; +use crate::marker::PhantomPinned; use crate::ops::Deref; use crate::panic::{RefUnwindSafe, UnwindSafe}; +use crate::pin::Pin; use crate::sys::mutex as sys; /// A re-entrant mutual exclusion @@ -15,6 +15,7 @@ use crate::sys::mutex as sys; pub struct ReentrantMutex { inner: sys::ReentrantMutex, data: T, + _pinned: PhantomPinned, } unsafe impl Send for ReentrantMutex {} @@ -37,10 +38,10 @@ impl RefUnwindSafe for ReentrantMutex {} /// guarded data. #[must_use = "if unused the ReentrantMutex will immediately unlock"] pub struct ReentrantMutexGuard<'a, T: 'a> { - lock: &'a ReentrantMutex, + lock: Pin<&'a ReentrantMutex>, } -impl !marker::Send for ReentrantMutexGuard<'_, T> {} +impl !Send for ReentrantMutexGuard<'_, T> {} impl ReentrantMutex { /// Creates a new reentrant mutex in an unlocked state. @@ -51,7 +52,11 @@ impl ReentrantMutex { /// once this mutex is in its final resting place, and only then are the /// lock/unlock methods safe. pub const unsafe fn new(t: T) -> ReentrantMutex { - ReentrantMutex { inner: sys::ReentrantMutex::uninitialized(), data: t } + ReentrantMutex { + inner: sys::ReentrantMutex::uninitialized(), + data: t, + _pinned: PhantomPinned, + } } /// Initializes this mutex so it's ready for use. @@ -60,8 +65,8 @@ impl ReentrantMutex { /// /// Unsafe to call more than once, and must be called after this will no /// longer move in memory. - pub unsafe fn init(&self) { - self.inner.init(); + pub unsafe fn init(self: Pin<&mut Self>) { + self.get_unchecked_mut().inner.init() } /// Acquires a mutex, blocking the current thread until it is able to do so. @@ -76,9 +81,9 @@ impl ReentrantMutex { /// If another user of this mutex panicked while holding the mutex, then /// this call will return failure if the mutex would otherwise be /// acquired. - pub fn lock(&self) -> ReentrantMutexGuard<'_, T> { + pub fn lock(self: Pin<&Self>) -> ReentrantMutexGuard<'_, T> { unsafe { self.inner.lock() } - ReentrantMutexGuard::new(&self) + ReentrantMutexGuard { lock: self } } /// Attempts to acquire this lock. @@ -93,8 +98,12 @@ impl ReentrantMutex { /// If another user of this mutex panicked while holding the mutex, then /// this call will return failure if the mutex would otherwise be /// acquired. - pub fn try_lock(&self) -> Option> { - if unsafe { self.inner.try_lock() } { Some(ReentrantMutexGuard::new(&self)) } else { None } + pub fn try_lock(self: Pin<&Self>) -> Option> { + if unsafe { self.inner.try_lock() } { + Some(ReentrantMutexGuard { lock: self }) + } else { + None + } } } @@ -107,30 +116,6 @@ impl Drop for ReentrantMutex { } } -impl fmt::Debug for ReentrantMutex { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.try_lock() { - Some(guard) => f.debug_struct("ReentrantMutex").field("data", &*guard).finish(), - None => { - struct LockedPlaceholder; - impl fmt::Debug for LockedPlaceholder { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("") - } - } - - f.debug_struct("ReentrantMutex").field("data", &LockedPlaceholder).finish() - } - } - } -} - -impl<'mutex, T> ReentrantMutexGuard<'mutex, T> { - fn new(lock: &'mutex ReentrantMutex) -> ReentrantMutexGuard<'mutex, T> { - ReentrantMutexGuard { lock } - } -} - impl Deref for ReentrantMutexGuard<'_, T> { type Target = T; diff --git a/library/std/src/sys_common/remutex/tests.rs b/library/std/src/sys_common/remutex/tests.rs index 9c686e579d735..88453ded2f9fb 100644 --- a/library/std/src/sys_common/remutex/tests.rs +++ b/library/std/src/sys_common/remutex/tests.rs @@ -1,4 +1,6 @@ +use crate::boxed::Box; use crate::cell::RefCell; +use crate::pin::Pin; use crate::sync::Arc; use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; use crate::thread; @@ -6,10 +8,11 @@ use crate::thread; #[test] fn smoke() { let m = unsafe { - let m = ReentrantMutex::new(()); - m.init(); + let mut m = Box::pin(ReentrantMutex::new(())); + m.as_mut().init(); m }; + let m = m.as_ref(); { let a = m.lock(); { @@ -27,18 +30,19 @@ fn smoke() { #[test] fn is_mutex() { let m = unsafe { - let m = Arc::new(ReentrantMutex::new(RefCell::new(0))); - m.init(); - m + // FIXME: Simplify this if Arc gets a Arc::get_pin_mut. + let mut m = Arc::new(ReentrantMutex::new(RefCell::new(0))); + Pin::new_unchecked(Arc::get_mut_unchecked(&mut m)).init(); + Pin::new_unchecked(m) }; let m2 = m.clone(); - let lock = m.lock(); + let lock = m.as_ref().lock(); let child = thread::spawn(move || { - let lock = m2.lock(); + let lock = m2.as_ref().lock(); assert_eq!(*lock.borrow(), 4950); }); for i in 0..100 { - let lock = m.lock(); + let lock = m.as_ref().lock(); *lock.borrow_mut() += i; } drop(lock); @@ -48,20 +52,21 @@ fn is_mutex() { #[test] fn trylock_works() { let m = unsafe { - let m = Arc::new(ReentrantMutex::new(())); - m.init(); - m + // FIXME: Simplify this if Arc gets a Arc::get_pin_mut. + let mut m = Arc::new(ReentrantMutex::new(())); + Pin::new_unchecked(Arc::get_mut_unchecked(&mut m)).init(); + Pin::new_unchecked(m) }; let m2 = m.clone(); - let _lock = m.try_lock(); - let _lock2 = m.try_lock(); + let _lock = m.as_ref().try_lock(); + let _lock2 = m.as_ref().try_lock(); thread::spawn(move || { - let lock = m2.try_lock(); + let lock = m2.as_ref().try_lock(); assert!(lock.is_none()); }) .join() .unwrap(); - let _lock3 = m.try_lock(); + let _lock3 = m.as_ref().try_lock(); } pub struct Answer<'a>(pub ReentrantMutexGuard<'a, RefCell>); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 1887b805da19b..b2a590307a203 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1575,13 +1575,13 @@ impl Step for Miri { let miri = builder .ensure(tool::Miri { compiler, target, extra_features: Vec::new() }) .or_else(|| { - missing_tool("miri", builder.build.config.missing_tools); + missing_tool("miri", true); None })?; let cargomiri = builder .ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() }) .or_else(|| { - missing_tool("cargo miri", builder.build.config.missing_tools); + missing_tool("cargo miri", true); None })?; @@ -2377,6 +2377,25 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir return; } + if let Some(config) = builder.config.target_config.get(&target) { + if config.llvm_config.is_some() && !builder.config.llvm_from_ci { + // If the LLVM was externally provided, then we don't currently copy + // artifacts into the sysroot. This is not necessarily the right + // choice (in particular, it will require the LLVM dylib to be in + // the linker's load path at runtime), but the common use case for + // external LLVMs is distribution provided LLVMs, and in that case + // they're usually in the standard search path (e.g., /usr/lib) and + // copying them here is going to cause problems as we may end up + // with the wrong files and isn't what distributions want. + // + // This behavior may be revisited in the future though. + // + // If the LLVM is coming from ourselves (just from CI) though, we + // still want to install it, as it otherwise won't be available. + return; + } + } + // On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib // instead of libLLVM-11-rust-....dylib, as on linux. It's not entirely // clear why this is the case, though. llvm-config will emit the versioned diff --git a/src/test/ui-fulldeps/compiler-calls.rs b/src/test/ui-fulldeps/compiler-calls.rs index 0025b47403d19..a9520b59277ac 100644 --- a/src/test/ui-fulldeps/compiler-calls.rs +++ b/src/test/ui-fulldeps/compiler-calls.rs @@ -26,13 +26,8 @@ fn main() { let mut count = 1; let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; rustc_driver::catch_fatal_errors(|| { - rustc_driver::run_compiler( - &args, - &mut TestCalls { count: &mut count }, - None, - None, - None, - ).ok(); - }).ok(); + rustc_driver::RunCompiler::new(&args, &mut TestCalls { count: &mut count }).run().ok(); + }) + .ok(); assert_eq!(count, 2); } diff --git a/src/test/ui/imports/issue-62767.rs b/src/test/ui/imports/issue-62767.rs index 0e0f915ea53c2..01184eea9b495 100644 --- a/src/test/ui/imports/issue-62767.rs +++ b/src/test/ui/imports/issue-62767.rs @@ -1,3 +1,5 @@ +// check-pass + // Minimized case from #62767. mod m { pub enum Same { @@ -9,7 +11,7 @@ use m::*; // The variant `Same` introduced by this import is also considered when resolving the prefix // `Same::` during import validation to avoid effects similar to time travel (#74556). -use Same::Same; //~ ERROR unresolved import `Same` +use Same::Same; // Case from #74556. mod foo { @@ -21,8 +23,8 @@ mod foo { } use foo::*; -use bar::bar; //~ ERROR unresolved import `bar::bar` - //~| ERROR inconsistent resolution for an import +use bar::bar; + use bar::foobar; fn main() {} diff --git a/src/test/ui/imports/issue-62767.stderr b/src/test/ui/imports/issue-62767.stderr deleted file mode 100644 index a4334bda6dd87..0000000000000 --- a/src/test/ui/imports/issue-62767.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: inconsistent resolution for an import - --> $DIR/issue-62767.rs:24:5 - | -LL | use bar::bar; - | ^^^^^^^^ - -error[E0432]: unresolved import `Same` - --> $DIR/issue-62767.rs:12:5 - | -LL | use Same::Same; - | ^^^^ `Same` is a variant, not a module - -error[E0432]: unresolved import `bar::bar` - --> $DIR/issue-62767.rs:24:5 - | -LL | use bar::bar; - | ^^^^^^^^ no `bar` in `foo::bar::bar` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index f4f2259cefd51..377f6d2244635 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -357,7 +357,7 @@ pub fn main() { args.extend(vec!["--sysroot".into(), sys_root]); }; - return rustc_driver::run_compiler(&args, &mut DefaultCallbacks, None, None, None); + return rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run(); } if orig_args.iter().any(|a| a == "--version" || a == "-V") { @@ -420,6 +420,6 @@ pub fn main() { let mut default = DefaultCallbacks; let callbacks: &mut (dyn rustc_driver::Callbacks + Send) = if clippy_enabled { &mut clippy } else { &mut default }; - rustc_driver::run_compiler(&args, callbacks, None, None, None) + rustc_driver::RunCompiler::new(&args, callbacks).run() })) } diff --git a/src/tools/rls b/src/tools/rls index 9bfb47a79299d..dab1468d6aeed 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 9bfb47a79299d52f45304367762c9bfc96d9ed7c +Subproject commit dab1468d6aeed0e49f7d0569c1d2128b5a7751e0 diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index 11d61606ff521..4b892c5aaef8f 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -61,6 +61,7 @@ features = [ ] [dependencies] +byteorder = { version = "1", features = ['default', 'std'] } curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true } crossbeam-utils = { version = "0.7.2", features = ["nightly"] } proc-macro2 = { version = "1", features = ["default"] } diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 97d0301011533..eb894d5370812 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 97d0301011533e1c131c0edd660d77b4bd476c8b +Subproject commit eb894d53708122a67762de9489881c11aa8ce257