Skip to content

Commit 5435ed6

Browse files
committed
Auto merge of #97835 - Dylan-DPC:rollup-0ae3pwp, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #95948 (Improve the safety docs for `CStr`) - #97325 (Fix precise field capture of univariant enums) - #97817 (:arrow_up: rust-analyzer) - #97821 (Remove confusing sentence from `Mutex` docs) - #97826 (Add more information for rustdoc-gui tests) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 7fe2c4b + 4851ec7 commit 5435ed6

File tree

10 files changed

+133
-42
lines changed

10 files changed

+133
-42
lines changed

compiler/rustc_middle/src/thir.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,11 @@ pub enum ExprKind<'tcx> {
317317
lhs: ExprId,
318318
rhs: ExprId,
319319
},
320-
/// Access to a struct or tuple field.
320+
/// Access to a field of a struct, a tuple, an union, or an enum.
321321
Field {
322322
lhs: ExprId,
323+
/// Variant containing the field.
324+
variant_index: VariantIdx,
323325
/// This can be a named (`.foo`) or unnamed (`.0`) field.
324326
name: Field,
325327
},

compiler/rustc_middle/src/thir/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
8080
visitor.visit_expr(&visitor.thir()[lhs]);
8181
visitor.visit_expr(&visitor.thir()[rhs]);
8282
}
83-
Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]),
83+
Field { lhs, variant_index: _, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]),
8484
Index { lhs, index } => {
8585
visitor.visit_expr(&visitor.thir()[lhs]);
8686
visitor.visit_expr(&visitor.thir()[index]);

compiler/rustc_mir_build/src/build/expr/as_place.rs

+48-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
55
use crate::build::{BlockAnd, BlockAndExtension, Builder};
66
use rustc_hir::def_id::DefId;
77
use rustc_hir::HirId;
8+
use rustc_middle::hir::place::Projection as HirProjection;
89
use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
910
use rustc_middle::middle::region;
1011
use rustc_middle::mir::AssertKind::BoundsCheck;
@@ -268,20 +269,52 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
268269
ty::UpvarCapture::ByValue => upvar_resolved_place_builder,
269270
};
270271

271-
let next_projection = capture.place.projections.len();
272-
let mut curr_projections = from_builder.projection;
273-
274272
// We used some of the projections to build the capture itself,
275273
// now we apply the remaining to the upvar resolved place.
276-
upvar_resolved_place_builder
277-
.projection
278-
.extend(curr_projections.drain(next_projection..));
274+
let remaining_projections = strip_prefix(
275+
capture.place.base_ty,
276+
from_builder.projection,
277+
&capture.place.projections,
278+
);
279+
upvar_resolved_place_builder.projection.extend(remaining_projections);
279280

280281
Ok(upvar_resolved_place_builder)
281282
}
282283
}
283284
}
284285

286+
/// Returns projections remaining after stripping an initial prefix of HIR
287+
/// projections.
288+
///
289+
/// Supports only HIR projection kinds that represent a path that might be
290+
/// captured by a closure or a generator, i.e., an `Index` or a `Subslice`
291+
/// projection kinds are unsupported.
292+
fn strip_prefix<'tcx>(
293+
mut base_ty: Ty<'tcx>,
294+
projections: Vec<PlaceElem<'tcx>>,
295+
prefix_projections: &[HirProjection<'tcx>],
296+
) -> impl Iterator<Item = PlaceElem<'tcx>> {
297+
let mut iter = projections.into_iter();
298+
for projection in prefix_projections {
299+
match projection.kind {
300+
HirProjectionKind::Deref => {
301+
assert!(matches!(iter.next(), Some(ProjectionElem::Deref)));
302+
}
303+
HirProjectionKind::Field(..) => {
304+
if base_ty.is_enum() {
305+
assert!(matches!(iter.next(), Some(ProjectionElem::Downcast(..))));
306+
}
307+
assert!(matches!(iter.next(), Some(ProjectionElem::Field(..))));
308+
}
309+
HirProjectionKind::Index | HirProjectionKind::Subslice => {
310+
bug!("unexpected projection kind: {:?}", projection);
311+
}
312+
}
313+
base_ty = projection.ty;
314+
}
315+
iter
316+
}
317+
285318
impl<'tcx> PlaceBuilder<'tcx> {
286319
pub(crate) fn into_place<'a>(
287320
self,
@@ -438,11 +471,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
438471
this.expr_as_place(block, &this.thir[value], mutability, fake_borrow_temps)
439472
})
440473
}
441-
ExprKind::Field { lhs, name } => {
442-
let place_builder = unpack!(
443-
block =
444-
this.expr_as_place(block, &this.thir[lhs], mutability, fake_borrow_temps,)
445-
);
474+
ExprKind::Field { lhs, variant_index, name } => {
475+
let lhs = &this.thir[lhs];
476+
let mut place_builder =
477+
unpack!(block = this.expr_as_place(block, lhs, mutability, fake_borrow_temps,));
478+
if let ty::Adt(adt_def, _) = lhs.ty.kind() {
479+
if adt_def.is_enum() {
480+
place_builder = place_builder.downcast(*adt_def, variant_index);
481+
}
482+
}
446483
block.and(place_builder.field(name, expr.ty))
447484
}
448485
ExprKind::Deref { arg } => {

compiler/rustc_mir_build/src/thir/cx/expr.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ impl<'tcx> Cx<'tcx> {
591591
}
592592
hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
593593
lhs: self.mirror_expr(source),
594+
variant_index: VariantIdx::new(0),
594595
name: Field::new(tcx.field_index(expr.hir_id, self.typeck_results)),
595596
},
596597
hir::ExprKind::Cast(ref source, ref cast_ty) => {
@@ -994,14 +995,11 @@ impl<'tcx> Cx<'tcx> {
994995
HirProjectionKind::Deref => {
995996
ExprKind::Deref { arg: self.thir.exprs.push(captured_place_expr) }
996997
}
997-
HirProjectionKind::Field(field, ..) => {
998-
// Variant index will always be 0, because for multi-variant
999-
// enums, we capture the enum entirely.
1000-
ExprKind::Field {
1001-
lhs: self.thir.exprs.push(captured_place_expr),
1002-
name: Field::new(field as usize),
1003-
}
1004-
}
998+
HirProjectionKind::Field(field, variant_index) => ExprKind::Field {
999+
lhs: self.thir.exprs.push(captured_place_expr),
1000+
variant_index,
1001+
name: Field::new(field as usize),
1002+
},
10051003
HirProjectionKind::Index | HirProjectionKind::Subslice => {
10061004
// We don't capture these projections, so we can ignore them here
10071005
continue;

library/core/src/ffi/c_str.rs

+27-10
Original file line numberDiff line numberDiff line change
@@ -196,20 +196,32 @@ impl CStr {
196196
/// allows inspection and interoperation of non-owned C strings. The total
197197
/// size of the raw C string must be smaller than `isize::MAX` **bytes**
198198
/// in memory due to calling the `slice::from_raw_parts` function.
199-
/// This method is unsafe for a number of reasons:
200199
///
201-
/// * There is no guarantee to the validity of `ptr`.
202-
/// * The returned lifetime is not guaranteed to be the actual lifetime of
203-
/// `ptr`.
204-
/// * There is no guarantee that the memory pointed to by `ptr` contains a
205-
/// valid nul terminator byte at the end of the string.
206-
/// * It is not guaranteed that the memory pointed by `ptr` won't change
207-
/// before the `CStr` has been destroyed.
200+
/// # Safety
201+
///
202+
/// * The memory pointed to by `ptr` must contain a valid nul terminator at the
203+
/// end of the string.
204+
///
205+
/// * `ptr` must be [valid] for reads of bytes up to and including the null terminator.
206+
/// This means in particular:
207+
///
208+
/// * The entire memory range of this `CStr` must be contained within a single allocated object!
209+
/// * `ptr` must be non-null even for a zero-length cstr.
210+
///
211+
/// * The memory referenced by the returned `CStr` must not be mutated for
212+
/// the duration of lifetime `'a`.
208213
///
209214
/// > **Note**: This operation is intended to be a 0-cost cast but it is
210215
/// > currently implemented with an up-front calculation of the length of
211216
/// > the string. This is not guaranteed to always be the case.
212217
///
218+
/// # Caveat
219+
///
220+
/// The lifetime for the returned slice is inferred from its usage. To prevent accidental misuse,
221+
/// it's suggested to tie the lifetime to whichever source lifetime is safe in the context,
222+
/// such as by providing a helper function taking the lifetime of a host value for the slice,
223+
/// or by explicit annotation.
224+
///
213225
/// # Examples
214226
///
215227
/// ```ignore (extern-declaration)
@@ -227,6 +239,8 @@ impl CStr {
227239
/// }
228240
/// # }
229241
/// ```
242+
///
243+
/// [valid]: core::ptr#safety
230244
#[inline]
231245
#[must_use]
232246
#[stable(feature = "rust1", since = "1.0.0")]
@@ -349,8 +363,11 @@ impl CStr {
349363
/// Unsafely creates a C string wrapper from a byte slice.
350364
///
351365
/// This function will cast the provided `bytes` to a `CStr` wrapper without
352-
/// performing any sanity checks. The provided slice **must** be nul-terminated
353-
/// and not contain any interior nul bytes.
366+
/// performing any sanity checks.
367+
///
368+
/// # Safety
369+
/// The provided slice **must** be nul-terminated and not contain any interior
370+
/// nul bytes.
354371
///
355372
/// # Examples
356373
///

library/std/src/sync/mutex.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ use crate::sys_common::mutex as sys;
1010
/// A mutual exclusion primitive useful for protecting shared data
1111
///
1212
/// This mutex will block threads waiting for the lock to become available. The
13-
/// mutex can also be statically initialized or created via a [`new`]
14-
/// constructor. Each mutex has a type parameter which represents the data that
15-
/// it is protecting. The data can only be accessed through the RAII guards
16-
/// returned from [`lock`] and [`try_lock`], which guarantees that the data is only
17-
/// ever accessed when the mutex is locked.
13+
/// mutex can be created via a [`new`] constructor. Each mutex has a type parameter
14+
/// which represents the data that it is protecting. The data can only be accessed
15+
/// through the RAII guards returned from [`lock`] and [`try_lock`], which
16+
/// guarantees that the data is only ever accessed when the mutex is locked.
1817
///
1918
/// # Poisoning
2019
///

src/test/rustdoc-gui/README.md

+15-5
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,24 @@ You can find more information and its documentation in its [repository][browser-
1111
If you need to have more information on the tests run, you can use `--test-args`:
1212

1313
```bash
14-
$ ./x.py test src/test/rustdoc-gui --stage 1 --jobs 8 --test-args --debug
14+
$ ./x.py test src/test/rustdoc-gui --stage 1 --test-args --debug
1515
```
1616

17-
There are three options supported:
17+
If you don't want to run in headless mode (helpful to debug sometimes), you can use
18+
`--no-headless`:
1819

19-
* `--debug`: allows to see puppeteer commands.
20-
* `--no-headless`: disable headless mode so you can see what's going on.
21-
* `--show-text`: by default, text isn't rendered because of issues with fonts, it enables it back.
20+
```bash
21+
$ ./x.py test src/test/rustdoc-gui --stage 1 --test-args --no-headless
22+
```
23+
24+
To see the supported options, use `--help`.
25+
26+
Important to be noted: if the chromium instance crashes when you run it, you might need to
27+
use `--no-sandbox` to make it work:
28+
29+
```bash
30+
$ ./x.py test src/test/rustdoc-gui --stage 1 --test-args --no-sandbox
31+
```
2232

2333
[browser-ui-test]: https://github.com/GuillaumeGomez/browser-UI-test/
2434
[puppeteer]: https://pptr.dev/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// edition:2021
2+
// run-pass
3+
4+
#[derive(Debug, PartialEq, Eq)]
5+
pub enum Color {
6+
RGB(u8, u8, u8),
7+
}
8+
9+
fn main() {
10+
let mut color = Color::RGB(0, 0, 0);
11+
let mut red = |v| {
12+
let Color::RGB(ref mut r, _, _) = color;
13+
*r = v;
14+
};
15+
let mut green = |v| {
16+
let Color::RGB(_, ref mut g, _) = color;
17+
*g = v;
18+
};
19+
let mut blue = |v| {
20+
let Color::RGB(_, _, ref mut b) = color;
21+
*b = v;
22+
};
23+
red(1);
24+
green(2);
25+
blue(3);
26+
assert_eq!(Color::RGB(1, 2, 3), color);
27+
}

src/tools/rust-analyzer

src/tools/rustdoc-gui/tester.js

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ function showHelp() {
1616
console.log(" --debug : show extra information about script run");
1717
console.log(" --show-text : render font in pages");
1818
console.log(" --no-headless : disable headless mode");
19+
console.log(" --no-sandbox : disable sandbox mode");
1920
console.log(" --help : show this message then quit");
2021
console.log(" --tests-folder [PATH] : location of the .GOML tests folder");
2122
console.log(" --jobs [NUMBER] : number of threads to run tests on");

0 commit comments

Comments
 (0)