Skip to content

Commit 75d9a0a

Browse files
committed
Auto merge of rust-lang#94061 - matthiaskrgr:rollup-oduekp5, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - rust-lang#92366 (Resolve concern of `derive_default_enum`) - rust-lang#93382 (Add a bit more padding in search box) - rust-lang#93962 (Make [u8]::cmp implementation branchless) - rust-lang#94015 (rustdoc --check option documentation) - rust-lang#94017 (Clarify confusing UB statement in MIR) - rust-lang#94020 (Support pretty printing of invalid constants) - rust-lang#94027 (Update browser UI test version) - rust-lang#94037 (Fix inconsistent symbol mangling with -Zverbose) - rust-lang#94045 (Update books) - rust-lang#94054 (:arrow_up: rust-analyzer) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents f90b06d + be858fa commit 75d9a0a

File tree

25 files changed

+177
-68
lines changed

25 files changed

+177
-68
lines changed

compiler/rustc_builtin_macros/src/deriving/default.rs

-3
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,6 @@ fn validate_default_attribute(
222222
"this method must only be called with a variant that has a `#[default]` attribute",
223223
),
224224
[first, rest @ ..] => {
225-
// FIXME(jhpratt) Do we want to perform this check? It doesn't exist
226-
// for `#[inline]`, `#[non_exhaustive]`, and presumably others.
227-
228225
let suggestion_text =
229226
if rest.len() == 1 { "try removing this" } else { "try removing these" };
230227

compiler/rustc_const_eval/src/const_eval/mod.rs

+18-20
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ use rustc_middle::{
1111
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
1212

1313
use crate::interpret::{
14-
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, MPlaceTy, MemPlaceMeta, Scalar,
14+
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MPlaceTy,
15+
MemPlaceMeta, Scalar,
1516
};
1617

1718
mod error;
@@ -132,42 +133,39 @@ fn const_to_valtree_inner<'tcx>(
132133
}
133134
}
134135

135-
/// This function uses `unwrap` copiously, because an already validated constant
136-
/// must have valid fields and can thus never fail outside of compiler bugs. However, it is
137-
/// invoked from the pretty printer, where it can receive enums with no variants and e.g.
138-
/// `read_discriminant` needs to be able to handle that.
139-
pub(crate) fn destructure_const<'tcx>(
136+
/// This function should never fail for validated constants. However, it is also invoked from the
137+
/// pretty printer which might attempt to format invalid constants and in that case it might fail.
138+
pub(crate) fn try_destructure_const<'tcx>(
140139
tcx: TyCtxt<'tcx>,
141140
param_env: ty::ParamEnv<'tcx>,
142141
val: ty::Const<'tcx>,
143-
) -> mir::DestructuredConst<'tcx> {
142+
) -> InterpResult<'tcx, mir::DestructuredConst<'tcx>> {
144143
trace!("destructure_const: {:?}", val);
145144
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
146-
let op = ecx.const_to_op(val, None).unwrap();
145+
let op = ecx.const_to_op(val, None)?;
147146

148147
// We go to `usize` as we cannot allocate anything bigger anyway.
149148
let (field_count, variant, down) = match val.ty().kind() {
150149
ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
151-
ty::Adt(def, _) if def.variants.is_empty() => {
152-
return mir::DestructuredConst { variant: None, fields: &[] };
153-
}
154150
ty::Adt(def, _) => {
155-
let variant = ecx.read_discriminant(&op).unwrap().1;
156-
let down = ecx.operand_downcast(&op, variant).unwrap();
151+
let variant = ecx.read_discriminant(&op)?.1;
152+
let down = ecx.operand_downcast(&op, variant)?;
157153
(def.variants[variant].fields.len(), Some(variant), down)
158154
}
159155
ty::Tuple(substs) => (substs.len(), None, op),
160156
_ => bug!("cannot destructure constant {:?}", val),
161157
};
162158

163-
let fields_iter = (0..field_count).map(|i| {
164-
let field_op = ecx.operand_field(&down, i).unwrap();
165-
let val = op_to_const(&ecx, &field_op);
166-
ty::Const::from_value(tcx, val, field_op.layout.ty)
167-
});
168-
let fields = tcx.arena.alloc_from_iter(fields_iter);
159+
let fields = (0..field_count)
160+
.map(|i| {
161+
let field_op = ecx.operand_field(&down, i)?;
162+
let val = op_to_const(&ecx, &field_op);
163+
Ok(ty::Const::from_value(tcx, val, field_op.layout.ty))
164+
})
165+
.collect::<InterpResult<'tcx, Vec<_>>>()?;
166+
let fields = tcx.arena.alloc_from_iter(fields);
169167

170-
mir::DestructuredConst { variant, fields }
168+
Ok(mir::DestructuredConst { variant, fields })
171169
}
172170

173171
pub(crate) fn deref_const<'tcx>(

compiler/rustc_const_eval/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ pub fn provide(providers: &mut Providers) {
4141
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
4242
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
4343
providers.const_caller_location = const_eval::const_caller_location;
44-
providers.destructure_const = |tcx, param_env_and_value| {
44+
providers.try_destructure_const = |tcx, param_env_and_value| {
4545
let (param_env, value) = param_env_and_value.into_parts();
46-
const_eval::destructure_const(tcx, param_env, value)
46+
const_eval::try_destructure_const(tcx, param_env, value).ok()
4747
};
4848
providers.const_to_valtree = |tcx, param_env_and_value| {
4949
let (param_env, raw) = param_env_and_value.into_parts();

compiler/rustc_middle/src/mir/interpret/queries.rs

+8
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,12 @@ impl<'tcx> TyCtxt<'tcx> {
9898
let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?;
9999
Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
100100
}
101+
102+
/// Destructure a constant ADT or array into its variant index and its field values.
103+
pub fn destructure_const(
104+
self,
105+
param_env_and_val: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>,
106+
) -> mir::DestructuredConst<'tcx> {
107+
self.try_destructure_const(param_env_and_val).unwrap()
108+
}
101109
}

compiler/rustc_middle/src/mir/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -2270,11 +2270,13 @@ pub enum BinOp {
22702270
Mul,
22712271
/// The `/` operator (division)
22722272
///
2273-
/// Division by zero is UB.
2273+
/// Division by zero is UB, because the compiler should have inserted checks
2274+
/// prior to this.
22742275
Div,
22752276
/// The `%` operator (modulus)
22762277
///
2277-
/// Using zero as the modulus (second operand) is UB.
2278+
/// Using zero as the modulus (second operand) is UB, because the compiler
2279+
/// should have inserted checks prior to this.
22782280
Rem,
22792281
/// The `^` operator (bitwise xor)
22802282
BitXor,

compiler/rustc_middle/src/query/mod.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -924,10 +924,12 @@ rustc_queries! {
924924
}
925925

926926
/// Destructure a constant ADT or array into its variant index and its
927-
/// field values.
928-
query destructure_const(
927+
/// field values or return `None` if constant is invalid.
928+
///
929+
/// Use infallible `TyCtxt::destructure_const` when you know that constant is valid.
930+
query try_destructure_const(
929931
key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>
930-
) -> mir::DestructuredConst<'tcx> {
932+
) -> Option<mir::DestructuredConst<'tcx>> {
931933
desc { "destructure constant" }
932934
remap_env_constness
933935
}

compiler/rustc_middle/src/ty/print/mod.rs

-5
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,6 @@ pub trait Printer<'tcx>: Sized {
188188
own_params.start = 1;
189189
}
190190

191-
// If we're in verbose mode, then print default-equal args too
192-
if self.tcx().sess.verbose() {
193-
return &substs[own_params];
194-
}
195-
196191
// Don't print args that are the defaults of their respective parameters.
197192
own_params.end -= generics
198193
.params

compiler/rustc_middle/src/ty/print/pretty.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -1459,10 +1459,18 @@ pub trait PrettyPrinter<'tcx>:
14591459
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
14601460
// correct `ty::ParamEnv` to allow printing *all* constant values.
14611461
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
1462-
let contents =
1463-
self.tcx().destructure_const(ty::ParamEnv::reveal_all().and(
1464-
self.tcx().mk_const(ty::ConstS { val: ty::ConstKind::Value(ct), ty }),
1465-
));
1462+
let Some(contents) = self.tcx().try_destructure_const(
1463+
ty::ParamEnv::reveal_all()
1464+
.and(self.tcx().mk_const(ty::ConstS { val: ty::ConstKind::Value(ct), ty })),
1465+
) else {
1466+
// Fall back to debug pretty printing for invalid constants.
1467+
p!(write("{:?}", ct));
1468+
if print_ty {
1469+
p!(": ", print(ty));
1470+
}
1471+
return Ok(self);
1472+
};
1473+
14661474
let fields = contents.fields.iter().copied();
14671475

14681476
match *ty.kind() {

library/core/src/slice/cmp.rs

+11-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Comparison traits for `[T]`.
22
3-
use crate::cmp;
4-
use crate::cmp::Ordering::{self, Greater, Less};
3+
use crate::cmp::{self, Ordering};
54
use crate::mem;
65

76
use super::from_raw_parts;
@@ -189,18 +188,18 @@ impl<A: Ord> SliceOrd for A {
189188
impl SliceOrd for u8 {
190189
#[inline]
191190
fn compare(left: &[Self], right: &[Self]) -> Ordering {
192-
let order =
193-
// SAFETY: `left` and `right` are references and are thus guaranteed to be valid.
194-
// We use the minimum of both lengths which guarantees that both regions are
195-
// valid for reads in that interval.
196-
unsafe { memcmp(left.as_ptr(), right.as_ptr(), cmp::min(left.len(), right.len())) };
191+
// Since the length of a slice is always less than or equal to isize::MAX, this never underflows.
192+
let diff = left.len() as isize - right.len() as isize;
193+
// This comparison gets optimized away (on x86_64 and ARM) because the subtraction updates flags.
194+
let len = if left.len() < right.len() { left.len() } else { right.len() };
195+
// SAFETY: `left` and `right` are references and are thus guaranteed to be valid.
196+
// We use the minimum of both lengths which guarantees that both regions are
197+
// valid for reads in that interval.
198+
let mut order = unsafe { memcmp(left.as_ptr(), right.as_ptr(), len) as isize };
197199
if order == 0 {
198-
left.len().cmp(&right.len())
199-
} else if order < 0 {
200-
Less
201-
} else {
202-
Greater
200+
order = diff;
203201
}
202+
order.cmp(&0)
204203
}
205204
}
206205

src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}"
7272
# https://github.com/puppeteer/puppeteer/issues/375
7373
#
7474
# We also specify the version in case we need to update it to go around cache limitations.
75-
RUN npm install -g [email protected].1 --unsafe-perm=true
75+
RUN npm install -g [email protected].2 --unsafe-perm=true
7676

7777
ENV RUST_CONFIGURE_ARGS \
7878
--build=x86_64-unknown-linux-gnu \

src/doc/rustdoc/src/command-line-arguments.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ the same CSS rules as the official `light` theme.
381381
`--check-theme` flag, it discards all other flags and only performs the CSS rule
382382
comparison operation.
383383

384-
### `--crate-version`: control the crate version
384+
## `--crate-version`: control the crate version
385385

386386
Using this flag looks like this:
387387

@@ -418,9 +418,22 @@ Rustdoc only supports Rust source code and Markdown input formats. If the
418418
file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file.
419419
Otherwise, it assumes that the input file is Rust.
420420

421+
# Unstable command line arguments
422+
421423
## `--nocapture`
422424

423425
When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be
424426
captured by rustdoc. Instead, the output will be directed to your terminal,
425427
as if you had run the test executable manually. This is especially useful
426428
for debugging your tests!
429+
430+
## `--check`
431+
432+
When this flag is supplied, rustdoc will type check and lint your code, but will not generate any
433+
documentation or run your doctests.
434+
435+
Using this flag looks like:
436+
437+
```bash
438+
rustdoc -Z unstable-options --check src/lib.rs
439+
```

src/librustdoc/html/static/css/rustdoc.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ table,
933933
outline: none;
934934
border: 1px solid;
935935
border-radius: 2px;
936-
padding: 5px 8px;
936+
padding: 8px;
937937
font-size: 1rem;
938938
transition: border-color 300ms ease;
939939
width: 100%;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
- // MIR for `main` before ConstProp
2+
+ // MIR for `main` after ConstProp
3+
4+
fn main() -> () {
5+
let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:15:11: 15:11
6+
let _1: std::option::Option<()>; // in scope 0 at $DIR/invalid_constant.rs:16:5: 16:12
7+
let mut _2: std::option::Option<std::option::Option<()>>; // in scope 0 at $DIR/invalid_constant.rs:16:7: 16:11
8+
scope 1 (inlined f) { // at $DIR/invalid_constant.rs:16:5: 16:12
9+
debug x => _2; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
10+
let mut _3: isize; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
11+
let _4: std::option::Option<()>; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
12+
scope 2 {
13+
debug y => _4; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
14+
}
15+
}
16+
17+
bb0: {
18+
discriminant(_2) = 0; // scope 0 at $DIR/invalid_constant.rs:16:7: 16:11
19+
- _3 = discriminant(_2); // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
20+
- switchInt(move _3) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
21+
+ _3 = const 0_isize; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
22+
+ switchInt(const 0_isize) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
23+
}
24+
25+
bb1: {
26+
nop; // scope 0 at $DIR/invalid_constant.rs:15:11: 17:2
27+
return; // scope 0 at $DIR/invalid_constant.rs:17:2: 17:2
28+
}
29+
30+
bb2: {
31+
- _4 = ((_2 as Some).0: std::option::Option<()>); // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
32+
- _1 = _4; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
33+
+ _4 = const Scalar(0x02): Option::<()>; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
34+
+ // ty::Const
35+
+ // + ty: std::option::Option<()>
36+
+ // + val: Value(Scalar(0x02))
37+
+ // mir::Constant
38+
+ // + span: $DIR/invalid_constant.rs:16:5: 16:12
39+
+ // + literal: Const { ty: std::option::Option<()>, val: Value(Scalar(0x02)) }
40+
+ _1 = const Scalar(0x02): Option::<()>; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
41+
+ // ty::Const
42+
+ // + ty: std::option::Option<()>
43+
+ // + val: Value(Scalar(0x02))
44+
+ // mir::Constant
45+
+ // + span: $DIR/invalid_constant.rs:16:5: 16:12
46+
+ // + literal: Const { ty: std::option::Option<()>, val: Value(Scalar(0x02)) }
47+
goto -> bb1; // scope 0 at $DIR/invalid_constant.rs:10:20: 10:21
48+
}
49+
50+
bb3: {
51+
discriminant(_1) = 0; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
52+
goto -> bb1; // scope 0 at $DIR/invalid_constant.rs:9:17: 9:21
53+
}
54+
}
55+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Verify that we can pretty print invalid constant introduced
2+
// by constant propagation. Regression test for issue #93688.
3+
//
4+
// compile-flags: -Copt-level=0 -Zinline-mir
5+
6+
#[inline(always)]
7+
pub fn f(x: Option<Option<()>>) -> Option<()> {
8+
match x {
9+
None => None,
10+
Some(y) => y,
11+
}
12+
}
13+
14+
// EMIT_MIR invalid_constant.main.ConstProp.diff
15+
fn main() {
16+
f(None);
17+
}

src/test/rustdoc-gui/item-info-width.goml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html
44
size: (1100, 800)
55
// We check that ".item-info" is bigger than its content.
66
assert-css: (".item-info", {"width": "790px"})
7-
assert-css: (".item-info .stab", {"width": "339.562px"})
7+
assert-css: (".item-info .stab", {"width": "340px"})
88
assert-position: (".item-info .stab", {"x": 295})

src/test/ui/associated-types/substs-ppaux.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ fn foo<'z>() where &'z (): Sized {
2525
let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>;
2626
//[verbose]~^ ERROR mismatched types
2727
//[verbose]~| expected unit type `()`
28-
//[verbose]~| found fn item `fn() {<i8 as Foo<ReStatic, ReStatic, u32>>::bar::<ReStatic, char>}`
28+
//[verbose]~| found fn item `fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>}`
2929
//[normal]~^^^^ ERROR mismatched types
3030
//[normal]~| expected unit type `()`
3131
//[normal]~| found fn item `fn() {<i8 as Foo<'static, 'static>>::bar::<'static, char>}`

src/test/ui/associated-types/substs-ppaux.verbose.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ error[E0308]: mismatched types
2020
--> $DIR/substs-ppaux.rs:25:17
2121
|
2222
LL | fn bar<'a, T>() where T: 'a {}
23-
| --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic, u32>>::bar::<ReStatic, char>} defined here
23+
| --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>} defined here
2424
...
2525
LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>;
2626
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
2727
| |
2828
| expected due to this
2929
|
3030
= note: expected unit type `()`
31-
found fn item `fn() {<i8 as Foo<ReStatic, ReStatic, u32>>::bar::<ReStatic, char>}`
31+
found fn item `fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>}`
3232
help: use parentheses to call this function
3333
|
3434
LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>();

0 commit comments

Comments
 (0)