Skip to content

Commit 3f32e30

Browse files
committed
Auto merge of #69062 - Dylan-DPC:rollup-7wpjpqu, r=Dylan-DPC
Rollup of 8 pull requests Successful merges: - #66498 (Remove unused feature gates) - #68816 (Tweak borrow error on `FnMut` when `Fn` is expected) - #68824 (Enable Control Flow Guard in rustbuild) - #69022 (traits: preallocate 2 Vecs of known initial size) - #69031 (Use `dyn Trait` more in tests) - #69044 (Don't run coherence twice for future-compat lints) - #69047 (Don't rustfmt check the vendor directory.) - #69055 (Clean up E0307 explanation) Failed merges: r? @ghost
2 parents 95e0a2c + 82a366a commit 3f32e30

File tree

45 files changed

+533
-375
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+533
-375
lines changed

config.toml.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,10 @@
444444
# Use LLVM libunwind as the implementation for Rust's unwinder.
445445
#llvm-libunwind = false
446446

447+
# Enable Windows Control Flow Guard checks in the standard library.
448+
# This only applies from stage 1 onwards, and only for Windows targets.
449+
#control-flow-guard = false
450+
447451
# =============================================================================
448452
# Options for specific targets
449453
#

rustfmt.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ merge_derives = false
77
# tidy only checks files which are not ignored, each entry follows gitignore style
88
ignore = [
99
"build",
10+
"/vendor/",
1011

1112
# tests for now are not formatted, as they are sometimes pretty-printing constrained
1213
# (and generally rustfmt can move around comments in UI-testing incompatible ways)

src/bootstrap/builder.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,20 @@ impl<'a> Builder<'a> {
11351135
);
11361136
}
11371137

1138+
// If Control Flow Guard is enabled, pass the `control_flow_guard=checks` flag to rustc
1139+
// when compiling the standard library, since this might be linked into the final outputs
1140+
// produced by rustc. Since this mitigation is only available on Windows, only enable it
1141+
// for the standard library in case the compiler is run on a non-Windows platform.
1142+
// This is not needed for stage 0 artifacts because these will only be used for building
1143+
// the stage 1 compiler.
1144+
if cfg!(windows)
1145+
&& mode == Mode::Std
1146+
&& self.config.control_flow_guard
1147+
&& compiler.stage >= 1
1148+
{
1149+
rustflags.arg("-Zcontrol_flow_guard=checks");
1150+
}
1151+
11381152
// For `cargo doc` invocations, make rustdoc print the Rust version into the docs
11391153
cargo.env("RUSTDOC_CRATE_VERSION", self.rust_version());
11401154

src/bootstrap/config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ pub struct Config {
116116
pub targets: Vec<Interned<String>>,
117117
pub local_rebuild: bool,
118118
pub jemalloc: bool,
119+
pub control_flow_guard: bool,
119120

120121
// dist misc
121122
pub dist_sign_folder: Option<PathBuf>,
@@ -333,6 +334,7 @@ struct Rust {
333334
jemalloc: Option<bool>,
334335
test_compare_mode: Option<bool>,
335336
llvm_libunwind: Option<bool>,
337+
control_flow_guard: Option<bool>,
336338
}
337339

338340
/// TOML representation of how each build target is configured.
@@ -580,6 +582,7 @@ impl Config {
580582
set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
581583
config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
582584
set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
585+
set(&mut config.control_flow_guard, rust.control_flow_guard);
583586

584587
if let Some(ref backends) = rust.codegen_backends {
585588
config.rust_codegen_backends =

src/bootstrap/configure.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def v(*args):
6060
o("lldb", "rust.lldb", "build lldb")
6161
o("missing-tools", "dist.missing-tools", "allow failures when building tools")
6262
o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++")
63+
o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard")
6364

6465
o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
6566
o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags")

src/bootstrap/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@
103103
//! More documentation can be found in each respective module below, and you can
104104
//! also check out the `src/bootstrap/README.md` file for more information.
105105
106-
#![feature(core_intrinsics)]
107106
#![feature(drain_filter)]
108107

109108
use std::cell::{Cell, RefCell};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# `control_flow_guard`
2+
3+
The tracking issue for this feature is: [#68793](https://github.com/rust-lang/rust/issues/68793).
4+
5+
------------------------
6+
7+
The `-Zcontrol_flow_guard=checks` compiler flag enables the Windows [Control Flow Guard][cfguard-docs] platform security feature. When enabled, the compiler outputs a list of valid indirect call targets, and inserts runtime checks on all indirect jump instructions to ensure that the destination is in the list of valid call targets.
8+
9+
[cfguard-docs]: https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard
10+
11+
For testing purposes, the `-Zcontrol_flow_guard=nochecks` compiler flag can be used to emit only the list of valid call targets, but not the runtime checks.
12+
13+
It is strongly recommended to also enable Control Flow Guard checks in all linked libraries, including the standard library.
14+
15+
To enable Control Flow Guard in the standard library, you can use the [cargo `-Zbuild-std` functionality][build-std] to recompile the standard library with the same configuration options as the main program.
16+
17+
[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
18+
19+
For example:
20+
```cmd
21+
rustup toolchain install --force nightly
22+
rustup component add rust-src
23+
SET RUSTFLAGS=-Zcontrol_flow_guard=checks
24+
cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
25+
```
26+
27+
```PowerShell
28+
rustup toolchain install --force nightly
29+
rustup component add rust-src
30+
$Env:RUSTFLAGS = "-Zcontrol_flow_guard=checks"
31+
cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
32+
```
33+
34+
Alternatively, if you are building the standard library from source, you can set `control-flow-guard = true` in the config.toml file.

src/librustc/lib.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
//! This API is completely unstable and subject to change.
2828
2929
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
30-
#![feature(arbitrary_self_types)]
3130
#![feature(bool_to_option)]
3231
#![feature(box_patterns)]
3332
#![feature(box_syntax)]
@@ -39,21 +38,15 @@
3938
#![feature(marker_trait_attr)]
4039
#![feature(extern_types)]
4140
#![feature(nll)]
42-
#![feature(optin_builtin_traits)]
4341
#![feature(option_expect_none)]
4442
#![feature(range_is_empty)]
4543
#![feature(specialization)]
46-
#![feature(unboxed_closures)]
47-
#![feature(thread_local)]
48-
#![feature(trace_macros)]
4944
#![feature(trusted_len)]
5045
#![feature(vec_remove_item)]
5146
#![feature(stmt_expr_attributes)]
52-
#![feature(integer_atomics)]
5347
#![feature(test)]
5448
#![feature(in_band_lifetimes)]
5549
#![feature(crate_visibility_modifier)]
56-
#![feature(log_syntax)]
5750
#![feature(associated_type_bounds)]
5851
#![feature(rustc_attrs)]
5952
#![feature(hash_raw_entry)]

src/librustc/traits/select.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3472,7 +3472,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
34723472
// that order.
34733473
let predicates = tcx.predicates_of(def_id);
34743474
assert_eq!(predicates.parent, None);
3475-
let mut obligations = Vec::new();
3475+
let mut obligations = Vec::with_capacity(predicates.predicates.len());
34763476
for (predicate, _) in predicates.predicates {
34773477
let predicate = normalize_with_depth_to(
34783478
self,

src/librustc/traits/specialize/specialization_graph.rs

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ impl<'tcx> Children {
8686
impl_def_id, simplified_self, possible_sibling,
8787
);
8888

89-
let overlap_error = |overlap: traits::coherence::OverlapResult<'_>| {
90-
// Found overlap, but no specialization; error out.
89+
let create_overlap_error = |overlap: traits::coherence::OverlapResult<'_>| {
9190
let trait_ref = overlap.impl_header.trait_ref.unwrap();
9291
let self_ty = trait_ref.self_ty();
92+
9393
OverlapError {
9494
with_impl: possible_sibling,
9595
trait_desc: trait_ref.print_only_trait_path().to_string(),
@@ -106,21 +106,49 @@ impl<'tcx> Children {
106106
}
107107
};
108108

109-
let allowed_to_overlap =
110-
tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling);
109+
let report_overlap_error = |overlap: traits::coherence::OverlapResult<'_>,
110+
last_lint: &mut _| {
111+
// Found overlap, but no specialization; error out or report future-compat warning.
112+
113+
// Do we *still* get overlap if we disable the future-incompatible modes?
114+
let should_err = traits::overlapping_impls(
115+
tcx,
116+
possible_sibling,
117+
impl_def_id,
118+
traits::SkipLeakCheck::default(),
119+
|_| true,
120+
|| false,
121+
);
122+
123+
let error = create_overlap_error(overlap);
124+
125+
if should_err {
126+
Err(error)
127+
} else {
128+
*last_lint = Some(FutureCompatOverlapError {
129+
error,
130+
kind: FutureCompatOverlapErrorKind::LeakCheck,
131+
});
132+
133+
Ok((false, false))
134+
}
135+
};
111136

137+
let last_lint_mut = &mut last_lint;
112138
let (le, ge) = traits::overlapping_impls(
113139
tcx,
114140
possible_sibling,
115141
impl_def_id,
116-
traits::SkipLeakCheck::default(),
142+
traits::SkipLeakCheck::Yes,
117143
|overlap| {
118-
if let Some(overlap_kind) = &allowed_to_overlap {
144+
if let Some(overlap_kind) =
145+
tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
146+
{
119147
match overlap_kind {
120148
ty::ImplOverlapKind::Permitted { marker: _ } => {}
121149
ty::ImplOverlapKind::Issue33140 => {
122-
last_lint = Some(FutureCompatOverlapError {
123-
error: overlap_error(overlap),
150+
*last_lint_mut = Some(FutureCompatOverlapError {
151+
error: create_overlap_error(overlap),
124152
kind: FutureCompatOverlapErrorKind::Issue33140,
125153
});
126154
}
@@ -132,7 +160,11 @@ impl<'tcx> Children {
132160
let le = tcx.specializes((impl_def_id, possible_sibling));
133161
let ge = tcx.specializes((possible_sibling, impl_def_id));
134162

135-
if le == ge { Err(overlap_error(overlap)) } else { Ok((le, ge)) }
163+
if le == ge {
164+
report_overlap_error(overlap, last_lint_mut)
165+
} else {
166+
Ok((le, ge))
167+
}
136168
},
137169
|| Ok((false, false)),
138170
)?;
@@ -153,27 +185,8 @@ impl<'tcx> Children {
153185

154186
replace_children.push(possible_sibling);
155187
} else {
156-
if let None = allowed_to_overlap {
157-
// Do future-compat checks for overlap.
158-
159-
if last_lint.is_none() {
160-
traits::overlapping_impls(
161-
tcx,
162-
possible_sibling,
163-
impl_def_id,
164-
traits::SkipLeakCheck::Yes,
165-
|overlap| {
166-
last_lint = Some(FutureCompatOverlapError {
167-
error: overlap_error(overlap),
168-
kind: FutureCompatOverlapErrorKind::LeakCheck,
169-
});
170-
},
171-
|| (),
172-
);
173-
}
174-
}
175-
176-
// no overlap (error bailed already via ?)
188+
// Either there's no overlap, or the overlap was already reported by
189+
// `overlap_error`.
177190
}
178191
}
179192

0 commit comments

Comments
 (0)