From 4ee75389dfed4004ffe7be8c1d9834e3997ded1b Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 12 Nov 2020 09:49:45 -0500 Subject: [PATCH 01/22] Avoid installing external LLVM dylibs 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. --- src/bootstrap/dist.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 1887b805da19b..b32f2053aa392 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2377,6 +2377,22 @@ 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() { + // 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. + 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 From 5e39baa921c725539e8bf338fd1356e3c112ba3f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 15 Nov 2020 08:59:53 -0500 Subject: [PATCH 02/22] Install CI llvm into the library directory --- src/bootstrap/dist.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index b32f2053aa392..289781b96ab6e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2378,7 +2378,7 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir } if let Some(config) = builder.config.target_config.get(&target) { - if config.llvm_config.is_some() { + 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 @@ -2389,6 +2389,9 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir // 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; } } From a846cc63ca16c88eb80d4a16cc5a417684f9a9d4 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 5 Nov 2020 15:16:12 -0500 Subject: [PATCH 03/22] Revert "Revert "resolve: Avoid "self-confirming" import resolutions in one more case"" This reverts commit b20bce8ce54ea9d47c2e3eb0b17cbb6baf916ae2. It retains the test added in that commit as a check-pass test, intended to prevent future (unintentional) regressions. --- compiler/rustc_resolve/src/imports.rs | 13 +++++++++++-- src/test/ui/imports/issue-62767.rs | 8 +++++--- src/test/ui/imports/issue-62767.stderr | 21 --------------------- 3 files changed, 16 insertions(+), 26 deletions(-) delete mode 100644 src/test/ui/imports/issue-62767.stderr 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/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`. From 9876548fe5e4e988dd96cf33f6f7fac031272e58 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini Date: Thu, 5 Nov 2020 15:58:23 +0000 Subject: [PATCH 04/22] Bump Rustfmt and RLS Should hopefully fix #78341 and #78340. --- Cargo.lock | 104 ++++++++++++---------- src/tools/rls | 2 +- src/tools/rustc-workspace-hack/Cargo.toml | 1 + src/tools/rustfmt | 2 +- 4 files changed, 61 insertions(+), 48 deletions(-) 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/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 From 60173790050b9c3df3b7fd3296bda50a7cfff030 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Wed, 21 Oct 2020 21:50:08 +0200 Subject: [PATCH 05/22] Add `ControlFlow::is_{break,continue}` methods --- library/core/src/ops/control_flow.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index b0c7dc1a51875..3bca3ff97332b 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -32,6 +32,20 @@ impl Try for 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] From a4582987cd673358d76903cb4e87e1506e4d85e8 Mon Sep 17 00:00:00 2001 From: Leonora Tindall Date: Fri, 11 Sep 2020 16:36:58 -0500 Subject: [PATCH 06/22] change the order of type arguments on ControlFlow This allows ControlFlow which is much more ergonomic for common iterator combinator use cases. --- .../rustc_data_structures/src/graph/iterate/mod.rs | 3 +-- library/core/src/iter/adapters/mod.rs | 10 +++++----- library/core/src/iter/traits/double_ended.rs | 4 +--- library/core/src/iter/traits/iterator.rs | 14 +++++--------- library/core/src/ops/control_flow.rs | 12 ++++++------ 5 files changed, 18 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs index bc3d1ce53bac5..c0c3260e2e2ec 100644 --- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs +++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs @@ -87,8 +87,7 @@ 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>; +pub use std::ops::ControlFlow; /// The status of a node in the depth-first search. /// 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 3bca3ff97332b..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,7 @@ 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")] @@ -58,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] @@ -80,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. /// @@ -102,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. /// From 9dd3c4bea5421cdad92dd4ce3a4d1a8e7ef021a5 Mon Sep 17 00:00:00 2001 From: Leonora Tindall Date: Wed, 21 Oct 2020 09:51:13 -0500 Subject: [PATCH 07/22] Don't re-export std::ops::ControlFlow in the compiler. --- compiler/rustc_data_structures/src/graph/iterate/mod.rs | 4 +--- compiler/rustc_mir_build/src/lints.rs | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs index c0c3260e2e2ec..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,9 +87,6 @@ where } } -/// Allows searches to terminate early with a value. -pub use std::ops::ControlFlow; - /// 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_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); From c952c5b29f3698cb5ff93c35aade4ed8bdf61a59 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 10 Oct 2020 20:13:03 +0200 Subject: [PATCH 08/22] Fix outdated comment about not needing to flush stderr. --- library/std/src/io/stdio.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 36b49401591f5..9b6bd70523da1 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -754,13 +754,9 @@ 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 { From fae7f01405ef460fe208dd658cbf6884c5653eae Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 10 Oct 2020 20:15:55 +0200 Subject: [PATCH 09/22] Remove unnecessary import of `crate::marker` in std::sys_common::remutex. It was used for marker::Send, but Send is already in scope. --- library/std/src/sys_common/remutex.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/std/src/sys_common/remutex.rs b/library/std/src/sys_common/remutex.rs index 162eab2388d55..35d6701efd0bd 100644 --- a/library/std/src/sys_common/remutex.rs +++ b/library/std/src/sys_common/remutex.rs @@ -2,7 +2,6 @@ mod tests; use crate::fmt; -use crate::marker; use crate::ops::Deref; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sys::mutex as sys; @@ -40,7 +39,7 @@ pub struct ReentrantMutexGuard<'a, T: 'a> { lock: &'a ReentrantMutex, } -impl !marker::Send for ReentrantMutexGuard<'_, T> {} +impl !Send for ReentrantMutexGuard<'_, T> {} impl ReentrantMutex { /// Creates a new reentrant mutex in an unlocked state. From 3c30290bec6e7a6bb58e71699375a4494a47f598 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 10 Oct 2020 20:20:14 +0200 Subject: [PATCH 10/22] Use Pin for the 'don't move' requirement of ReentrantMutex. --- library/std/src/sys_common/remutex.rs | 52 ++++++++++----------------- 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/library/std/src/sys_common/remutex.rs b/library/std/src/sys_common/remutex.rs index 35d6701efd0bd..475bfca9b6dcc 100644 --- a/library/std/src/sys_common/remutex.rs +++ b/library/std/src/sys_common/remutex.rs @@ -1,9 +1,10 @@ #[cfg(all(test, not(target_os = "emscripten")))] mod tests; -use crate::fmt; +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 @@ -14,6 +15,7 @@ use crate::sys::mutex as sys; pub struct ReentrantMutex { inner: sys::ReentrantMutex, data: T, + _pinned: PhantomPinned, } unsafe impl Send for ReentrantMutex {} @@ -36,7 +38,7 @@ 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 !Send for ReentrantMutexGuard<'_, T> {} @@ -50,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. @@ -59,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. @@ -75,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. @@ -92,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 + } } } @@ -106,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; From 0ec7a81ecbc6038c68f1d5a43d65013be7d6e071 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 10 Oct 2020 20:21:36 +0200 Subject: [PATCH 11/22] Update ReentrantMutex tests to use Pin. --- library/std/src/lib.rs | 1 + library/std/src/sys_common/remutex/tests.rs | 35 ++++++++++++--------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index b2bd5f4da5012..e9ac7875cc26f 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)] 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>); From da00a4ffc1f4df7a3ab59170c79e3febc469b746 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 7 Oct 2020 17:19:38 +0200 Subject: [PATCH 12/22] Add (internal-only) SyncOnceCell::get_or_init_pin. --- library/std/src/lazy.rs | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs index e0095e64faf31..091c69ca083ad 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,57 @@ 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) -> &T + where + F: FnOnce() -> T, + G: FnOnce(Pin<&mut T>), + { + if let Some(value) = self.get_ref().get() { + return 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. + unsafe { self.get_ref().get_unchecked() } + } + /// Consumes the `SyncOnceCell`, returning the wrapped value. Returns /// `None` if the cell was empty. /// From 72cccf14896615e33c2d26c4457d480d4aa5fd89 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 10 Oct 2020 20:14:33 +0200 Subject: [PATCH 13/22] Return a Pin from SyncOnceCell::get_or_init_pin. --- library/std/src/lazy.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs index 091c69ca083ad..68f57958bb233 100644 --- a/library/std/src/lazy.rs +++ b/library/std/src/lazy.rs @@ -321,13 +321,15 @@ impl SyncOnceCell { /// 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) -> &T + 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() { - return value; + // SAFETY: The inner value was already initialized, and will not be + // moved anymore. + return unsafe { Pin::new_unchecked(value) }; } let slot = &self.value; @@ -345,8 +347,9 @@ impl SyncOnceCell { g(unsafe { Pin::new_unchecked(value) }); }); - // SAFETY: The inner value has been initialized. - unsafe { self.get_ref().get_unchecked() } + // 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 From 93ba97f97b487fb4c8da4842078d7595ecc2a4a5 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 10 Oct 2020 20:22:15 +0200 Subject: [PATCH 14/22] Pin the ReentrantMutexes in sys::io::stdio. The code before this change misused the ReentrantMutexes, by calling init() on them and moving them afterwards. Now that ReentrantMutex requires Pin for init(), this mistake is no longer easy to make. --- library/std/src/io/stdio.rs | 54 ++++++++++++++++++++----------------- library/std/src/lib.rs | 1 + 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 9b6bd70523da1..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. @@ -760,11 +765,10 @@ pub fn stderr() -> Stderr { 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/lib.rs b/library/std/src/lib.rs index e9ac7875cc26f..5aa9d6a3562f1 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -291,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)] From 956238e369e2ebacf7b86682511724110575d9d9 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 8 Oct 2020 23:51:56 +0200 Subject: [PATCH 15/22] Add Pin::new_static. --- library/core/src/pin.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 9f0284d5d9542..cc93f0fa5fc6f 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -781,6 +781,19 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { } } +impl Pin<&'static T> { + /// Get a pinned reference from a static reference. + /// + /// This is safe, because the `'static` lifetime guarantees the data will + /// never be moved. + #[unstable(feature = "pin_static_ref", issue = "none")] + pub fn new_static(r: &'static T) -> Pin<&'static T> { + // SAFETY: The 'static lifetime 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; From 9edb1ab76d796a6aeb8f7e36efec70c5ff159bff Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 9 Oct 2020 00:06:39 +0200 Subject: [PATCH 16/22] Make Pin::new_static const. --- library/core/src/pin.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index cc93f0fa5fc6f..3f058124d2bde 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -787,7 +787,8 @@ impl Pin<&'static T> { /// This is safe, because the `'static` lifetime guarantees the data will /// never be moved. #[unstable(feature = "pin_static_ref", issue = "none")] - pub fn new_static(r: &'static T) -> Pin<&'static T> { + #[rustc_const_unstable(feature = "const_pin", issue = "76654")] + pub const fn new_static(r: &'static T) -> Pin<&'static T> { // SAFETY: The 'static lifetime guarantees the data will not be // moved/invalidated until it gets dropped (which is never). unsafe { Pin::new_unchecked(r) } From 41eb822306db2cd24ac35f2078fe8f357c306425 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 12 Oct 2020 20:00:44 +0200 Subject: [PATCH 17/22] Rename Pin::new_static to Pin::static_ref. --- library/core/src/pin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 3f058124d2bde..9e2d64a866fbb 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -788,7 +788,7 @@ impl Pin<&'static T> { /// never be moved. #[unstable(feature = "pin_static_ref", issue = "none")] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] - pub const fn new_static(r: &'static T) -> Pin<&'static T> { + pub const fn static_ref(r: &'static T) -> Pin<&'static T> { // SAFETY: The 'static lifetime guarantees the data will not be // moved/invalidated until it gets dropped (which is never). unsafe { Pin::new_unchecked(r) } From e72afdeb2f16cb5de6719aa8b0b55dc5e8e09fba Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 12 Oct 2020 20:00:56 +0200 Subject: [PATCH 18/22] Add Pin::static_mut. --- library/core/src/pin.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 9e2d64a866fbb..b27167a7e7c66 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -795,6 +795,20 @@ impl Pin<&'static T> { } } +impl Pin<&'static T> { + /// Get a pinned mutable reference from a static mutable reference. + /// + /// This is safe, because the `'static` lifetime guarantees the data will + /// never be moved. + #[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 lifetime 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; From 735b0754b6987f3f9e570c516a77fede9a7f2968 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 13 Oct 2020 13:13:09 +0200 Subject: [PATCH 19/22] Reword safety guarantee of Pin::static_{ref,mut}. Co-authored-by: Peter Todd --- library/core/src/pin.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index b27167a7e7c66..633e96eb7d811 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -784,12 +784,12 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { impl Pin<&'static T> { /// Get a pinned reference from a static reference. /// - /// This is safe, because the `'static` lifetime guarantees the data will - /// never be moved. + /// 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 lifetime guarantees the data will not be + // SAFETY: The 'static borrow guarantees the data will not be // moved/invalidated until it gets dropped (which is never). unsafe { Pin::new_unchecked(r) } } @@ -798,12 +798,12 @@ impl Pin<&'static T> { impl Pin<&'static T> { /// Get a pinned mutable reference from a static mutable reference. /// - /// This is safe, because the `'static` lifetime guarantees the data will - /// never be moved. + /// 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 lifetime guarantees the data will not be + // SAFETY: The 'static borrow guarantees the data will not be // moved/invalidated until it gets dropped (which is never). unsafe { Pin::new_unchecked(r) } } From e68b265a2275d396dc87f217309600763385e7a4 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 15 Oct 2020 21:45:09 +0200 Subject: [PATCH 20/22] Add missing `mut`. Co-authored-by: David Tolnay --- library/core/src/pin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 633e96eb7d811..b73cd046e5a65 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -795,7 +795,7 @@ impl Pin<&'static T> { } } -impl Pin<&'static T> { +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 From d9beaaf2f0fc36c13ba4da400ddd55499908f878 Mon Sep 17 00:00:00 2001 From: Darshan Kathiriya Date: Wed, 7 Oct 2020 09:09:59 -0300 Subject: [PATCH 21/22] Replace run_compiler with RunCompiler builder pattern. RunCompiler::new takes non-optional params, and optional params can be set using set_*field_name* method. finally `run` will forward all fields to `run_compiler`. --- compiler/rustc_driver/src/lib.rs | 47 ++++++++++++++++++++++++-- src/test/ui-fulldeps/compiler-calls.rs | 11 ++---- src/tools/clippy/src/driver.rs | 4 +-- 3 files changed, 50 insertions(+), 12 deletions(-) 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/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/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() })) } From 0b6785f8701ccfe627390f0acff26e241db6de62 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 15 Nov 2020 14:18:04 -0500 Subject: [PATCH 22/22] Miri is not required on beta --- src/bootstrap/dist.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 289781b96ab6e..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 })?;