Skip to content

Commit

Permalink
Auto merge of rust-lang#94061 - matthiaskrgr:rollup-oduekp5, r=matthi…
Browse files Browse the repository at this point in the history
…askrgr

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
  • Loading branch information
bors committed Feb 16, 2022
2 parents f90b06d + be858fa commit 75d9a0a
Show file tree
Hide file tree
Showing 25 changed files with 177 additions and 68 deletions.
3 changes: 0 additions & 3 deletions compiler/rustc_builtin_macros/src/deriving/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,6 @@ fn validate_default_attribute(
"this method must only be called with a variant that has a `#[default]` attribute",
),
[first, rest @ ..] => {
// FIXME(jhpratt) Do we want to perform this check? It doesn't exist
// for `#[inline]`, `#[non_exhaustive]`, and presumably others.

let suggestion_text =
if rest.len() == 1 { "try removing this" } else { "try removing these" };

Expand Down
38 changes: 18 additions & 20 deletions compiler/rustc_const_eval/src/const_eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ use rustc_middle::{
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};

use crate::interpret::{
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, MPlaceTy, MemPlaceMeta, Scalar,
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MPlaceTy,
MemPlaceMeta, Scalar,
};

mod error;
Expand Down Expand Up @@ -132,42 +133,39 @@ fn const_to_valtree_inner<'tcx>(
}
}

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

// We go to `usize` as we cannot allocate anything bigger anyway.
let (field_count, variant, down) = match val.ty().kind() {
ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
ty::Adt(def, _) if def.variants.is_empty() => {
return mir::DestructuredConst { variant: None, fields: &[] };
}
ty::Adt(def, _) => {
let variant = ecx.read_discriminant(&op).unwrap().1;
let down = ecx.operand_downcast(&op, variant).unwrap();
let variant = ecx.read_discriminant(&op)?.1;
let down = ecx.operand_downcast(&op, variant)?;
(def.variants[variant].fields.len(), Some(variant), down)
}
ty::Tuple(substs) => (substs.len(), None, op),
_ => bug!("cannot destructure constant {:?}", val),
};

let fields_iter = (0..field_count).map(|i| {
let field_op = ecx.operand_field(&down, i).unwrap();
let val = op_to_const(&ecx, &field_op);
ty::Const::from_value(tcx, val, field_op.layout.ty)
});
let fields = tcx.arena.alloc_from_iter(fields_iter);
let fields = (0..field_count)
.map(|i| {
let field_op = ecx.operand_field(&down, i)?;
let val = op_to_const(&ecx, &field_op);
Ok(ty::Const::from_value(tcx, val, field_op.layout.ty))
})
.collect::<InterpResult<'tcx, Vec<_>>>()?;
let fields = tcx.arena.alloc_from_iter(fields);

mir::DestructuredConst { variant, fields }
Ok(mir::DestructuredConst { variant, fields })
}

pub(crate) fn deref_const<'tcx>(
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ pub fn provide(providers: &mut Providers) {
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
providers.const_caller_location = const_eval::const_caller_location;
providers.destructure_const = |tcx, param_env_and_value| {
providers.try_destructure_const = |tcx, param_env_and_value| {
let (param_env, value) = param_env_and_value.into_parts();
const_eval::destructure_const(tcx, param_env, value)
const_eval::try_destructure_const(tcx, param_env, value).ok()
};
providers.const_to_valtree = |tcx, param_env_and_value| {
let (param_env, raw) = param_env_and_value.into_parts();
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/mir/interpret/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,12 @@ impl<'tcx> TyCtxt<'tcx> {
let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?;
Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
}

/// Destructure a constant ADT or array into its variant index and its field values.
pub fn destructure_const(
self,
param_env_and_val: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>,
) -> mir::DestructuredConst<'tcx> {
self.try_destructure_const(param_env_and_val).unwrap()
}
}
6 changes: 4 additions & 2 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2270,11 +2270,13 @@ pub enum BinOp {
Mul,
/// The `/` operator (division)
///
/// Division by zero is UB.
/// Division by zero is UB, because the compiler should have inserted checks
/// prior to this.
Div,
/// The `%` operator (modulus)
///
/// Using zero as the modulus (second operand) is UB.
/// Using zero as the modulus (second operand) is UB, because the compiler
/// should have inserted checks prior to this.
Rem,
/// The `^` operator (bitwise xor)
BitXor,
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -924,10 +924,12 @@ rustc_queries! {
}

/// Destructure a constant ADT or array into its variant index and its
/// field values.
query destructure_const(
/// field values or return `None` if constant is invalid.
///
/// Use infallible `TyCtxt::destructure_const` when you know that constant is valid.
query try_destructure_const(
key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>
) -> mir::DestructuredConst<'tcx> {
) -> Option<mir::DestructuredConst<'tcx>> {
desc { "destructure constant" }
remap_env_constness
}
Expand Down
5 changes: 0 additions & 5 deletions compiler/rustc_middle/src/ty/print/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,6 @@ pub trait Printer<'tcx>: Sized {
own_params.start = 1;
}

// If we're in verbose mode, then print default-equal args too
if self.tcx().sess.verbose() {
return &substs[own_params];
}

// Don't print args that are the defaults of their respective parameters.
own_params.end -= generics
.params
Expand Down
16 changes: 12 additions & 4 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1459,10 +1459,18 @@ pub trait PrettyPrinter<'tcx>:
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
// correct `ty::ParamEnv` to allow printing *all* constant values.
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
let contents =
self.tcx().destructure_const(ty::ParamEnv::reveal_all().and(
self.tcx().mk_const(ty::ConstS { val: ty::ConstKind::Value(ct), ty }),
));
let Some(contents) = self.tcx().try_destructure_const(
ty::ParamEnv::reveal_all()
.and(self.tcx().mk_const(ty::ConstS { val: ty::ConstKind::Value(ct), ty })),
) else {
// Fall back to debug pretty printing for invalid constants.
p!(write("{:?}", ct));
if print_ty {
p!(": ", print(ty));
}
return Ok(self);
};

let fields = contents.fields.iter().copied();

match *ty.kind() {
Expand Down
23 changes: 11 additions & 12 deletions library/core/src/slice/cmp.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Comparison traits for `[T]`.

use crate::cmp;
use crate::cmp::Ordering::{self, Greater, Less};
use crate::cmp::{self, Ordering};
use crate::mem;

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

Expand Down
2 changes: 1 addition & 1 deletion src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}"
# https://github.com/puppeteer/puppeteer/issues/375
#
# We also specify the version in case we need to update it to go around cache limitations.
RUN npm install -g browser-ui-test@0.7.1 --unsafe-perm=true
RUN npm install -g browser-ui-test@0.7.2 --unsafe-perm=true

ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
Expand Down
2 changes: 1 addition & 1 deletion src/doc/nomicon
15 changes: 14 additions & 1 deletion src/doc/rustdoc/src/command-line-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ the same CSS rules as the official `light` theme.
`--check-theme` flag, it discards all other flags and only performs the CSS rule
comparison operation.

### `--crate-version`: control the crate version
## `--crate-version`: control the crate version

Using this flag looks like this:

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

# Unstable command line arguments

## `--nocapture`

When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be
captured by rustdoc. Instead, the output will be directed to your terminal,
as if you had run the test executable manually. This is especially useful
for debugging your tests!

## `--check`

When this flag is supplied, rustdoc will type check and lint your code, but will not generate any
documentation or run your doctests.

Using this flag looks like:

```bash
rustdoc -Z unstable-options --check src/lib.rs
```
2 changes: 1 addition & 1 deletion src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,7 @@ table,
outline: none;
border: 1px solid;
border-radius: 2px;
padding: 5px 8px;
padding: 8px;
font-size: 1rem;
transition: border-color 300ms ease;
width: 100%;
Expand Down
55 changes: 55 additions & 0 deletions src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
- // MIR for `main` before ConstProp
+ // MIR for `main` after ConstProp

fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:15:11: 15:11
let _1: std::option::Option<()>; // in scope 0 at $DIR/invalid_constant.rs:16:5: 16:12
let mut _2: std::option::Option<std::option::Option<()>>; // in scope 0 at $DIR/invalid_constant.rs:16:7: 16:11
scope 1 (inlined f) { // at $DIR/invalid_constant.rs:16:5: 16:12
debug x => _2; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
let mut _3: isize; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
let _4: std::option::Option<()>; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
scope 2 {
debug y => _4; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
}
}

bb0: {
discriminant(_2) = 0; // scope 0 at $DIR/invalid_constant.rs:16:7: 16:11
- _3 = discriminant(_2); // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
- switchInt(move _3) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
+ _3 = const 0_isize; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
+ switchInt(const 0_isize) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
}

bb1: {
nop; // scope 0 at $DIR/invalid_constant.rs:15:11: 17:2
return; // scope 0 at $DIR/invalid_constant.rs:17:2: 17:2
}

bb2: {
- _4 = ((_2 as Some).0: std::option::Option<()>); // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
- _1 = _4; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
+ _4 = const Scalar(0x02): Option::<()>; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
+ // ty::Const
+ // + ty: std::option::Option<()>
+ // + val: Value(Scalar(0x02))
+ // mir::Constant
+ // + span: $DIR/invalid_constant.rs:16:5: 16:12
+ // + literal: Const { ty: std::option::Option<()>, val: Value(Scalar(0x02)) }
+ _1 = const Scalar(0x02): Option::<()>; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
+ // ty::Const
+ // + ty: std::option::Option<()>
+ // + val: Value(Scalar(0x02))
+ // mir::Constant
+ // + span: $DIR/invalid_constant.rs:16:5: 16:12
+ // + literal: Const { ty: std::option::Option<()>, val: Value(Scalar(0x02)) }
goto -> bb1; // scope 0 at $DIR/invalid_constant.rs:10:20: 10:21
}

bb3: {
discriminant(_1) = 0; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12
goto -> bb1; // scope 0 at $DIR/invalid_constant.rs:9:17: 9:21
}
}

17 changes: 17 additions & 0 deletions src/test/mir-opt/const_prop/invalid_constant.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Verify that we can pretty print invalid constant introduced
// by constant propagation. Regression test for issue #93688.
//
// compile-flags: -Copt-level=0 -Zinline-mir

#[inline(always)]
pub fn f(x: Option<Option<()>>) -> Option<()> {
match x {
None => None,
Some(y) => y,
}
}

// EMIT_MIR invalid_constant.main.ConstProp.diff
fn main() {
f(None);
}
2 changes: 1 addition & 1 deletion src/test/rustdoc-gui/item-info-width.goml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html
size: (1100, 800)
// We check that ".item-info" is bigger than its content.
assert-css: (".item-info", {"width": "790px"})
assert-css: (".item-info .stab", {"width": "339.562px"})
assert-css: (".item-info .stab", {"width": "340px"})
assert-position: (".item-info .stab", {"x": 295})
2 changes: 1 addition & 1 deletion src/test/ui/associated-types/substs-ppaux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fn foo<'z>() where &'z (): Sized {
let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>;
//[verbose]~^ ERROR mismatched types
//[verbose]~| expected unit type `()`
//[verbose]~| found fn item `fn() {<i8 as Foo<ReStatic, ReStatic, u32>>::bar::<ReStatic, char>}`
//[verbose]~| found fn item `fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>}`
//[normal]~^^^^ ERROR mismatched types
//[normal]~| expected unit type `()`
//[normal]~| found fn item `fn() {<i8 as Foo<'static, 'static>>::bar::<'static, char>}`
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/associated-types/substs-ppaux.verbose.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ error[E0308]: mismatched types
--> $DIR/substs-ppaux.rs:25:17
|
LL | fn bar<'a, T>() where T: 'a {}
| --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic, u32>>::bar::<ReStatic, char>} defined here
| --------------------------- fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>} defined here
...
LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>;
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found fn item
| |
| expected due to this
|
= note: expected unit type `()`
found fn item `fn() {<i8 as Foo<ReStatic, ReStatic, u32>>::bar::<ReStatic, char>}`
found fn item `fn() {<i8 as Foo<ReStatic, ReStatic>>::bar::<ReStatic, char>}`
help: use parentheses to call this function
|
LL | let x: () = <i8 as Foo<'static, 'static, u32>>::bar::<'static, char>();
Expand Down
Loading

0 comments on commit 75d9a0a

Please sign in to comment.