Skip to content

Rollup of 9 pull requests #102377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Sep 28, 2022
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5510a69
Stabilize `#![feature(mixed_integer_ops)]`
jhpratt Sep 8, 2022
c19daa4
make invalid_value lint a bit smarter around enums
RalfJung Sep 25, 2022
3fac709
rustdoc: remove no-op CSS `.srclink { font-weight; font-size }`
notriddle Sep 26, 2022
35adb36
Avoid LLVM-deprecated `Optional::hasValue`
cuviper Sep 26, 2022
594134d
Structured suggestion for missing mut/const in pointer
compiler-errors Sep 25, 2022
2286888
session: remove now-unnecessary lint `#[allow]`s
davidtwco Sep 27, 2022
67fd09d
also query type_uninhabited_from
RalfJung Sep 27, 2022
8846c08
rustdoc: use CSS containment to speed up render
jsha Sep 27, 2022
b5b77a2
Update src/test/rustdoc-gui/sidebar-mobile-scroll.goml
jsha Sep 27, 2022
3bbb328
rustdoc: remove redundant `#help-button` CSS
notriddle Sep 27, 2022
ef410f1
Fix regression for results colors
GuillaumeGomez Sep 27, 2022
a925e20
Add GUI regression test for search results colors
GuillaumeGomez Sep 27, 2022
ad57d5f
Rollup merge of #101555 - jhpratt:stabilize-mixed_integer_ops, r=josh…
matthiaskrgr Sep 27, 2022
4cef648
Rollup merge of #102253 - jsha:css-contain, r=notriddle
matthiaskrgr Sep 27, 2022
8d2faa2
Rollup merge of #102281 - RalfJung:invalid-enums, r=cjgillot
matthiaskrgr Sep 27, 2022
8b635cb
Rollup merge of #102284 - compiler-errors:missing-type-in-raw-ptr, r=…
matthiaskrgr Sep 27, 2022
b32ce95
Rollup merge of #102330 - notriddle:notriddle/srclink, r=GuillaumeGomez
matthiaskrgr Sep 27, 2022
e1fb698
Rollup merge of #102337 - cuviper:llvm-optional-bool, r=nikic
matthiaskrgr Sep 27, 2022
3ca0cd0
Rollup merge of #102356 - davidtwco:translation-bootstrap-bump-allow-…
matthiaskrgr Sep 27, 2022
5971b1a
Rollup merge of #102367 - notriddle:notriddle/help-text-align, r=Guil…
matthiaskrgr Sep 27, 2022
f28ac30
Rollup merge of #102369 - GuillaumeGomez:results-colors, r=notriddle
matthiaskrgr Sep 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 117 additions & 51 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -46,8 +46,7 @@ use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::Instance;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef};
use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason};
use rustc_span::edition::Edition;
use rustc_span::source_map::Spanned;
@@ -2425,12 +2424,63 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
None
}

/// Test if this enum has several actually "existing" variants.
/// Zero-sized uninhabited variants do not always have a tag assigned and thus do not "exist".
fn is_multi_variant<'tcx>(adt: ty::AdtDef<'tcx>) -> bool {
// As an approximation, we only count dataless variants. Those are definitely inhabited.
let existing_variants = adt.variants().iter().filter(|v| v.fields.is_empty()).count();
existing_variants > 1
/// Determines whether the given type is inhabited. `None` means that we don't know.
fn ty_inhabited<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<bool> {
use rustc_type_ir::sty::TyKind::*;
if !cx.tcx.type_uninhabited_from(cx.param_env.and(ty)).is_empty() {
// This is definitely uninhabited from some module.
return Some(false);
}
match ty.kind() {
Never => Some(false),
Int(_) | Uint(_) | Float(_) | Bool | Char | RawPtr(_) => Some(true),
// Fallback for more complicated types. (Note that `&!` might be considered
// uninhabited so references are "complicated", too.)
_ => None,
}
}
/// Determines whether a product type formed from a list of types is inhabited.
fn tys_inhabited<'tcx>(
cx: &LateContext<'tcx>,
tys: impl Iterator<Item = Ty<'tcx>>,
) -> Option<bool> {
let mut definitely_inhabited = true; // with no fields, we are definitely inhabited.
for ty in tys {
match ty_inhabited(cx, ty) {
// If any type is uninhabited, the product is uninhabited.
Some(false) => return Some(false),
// Otherwise go searching for a `None`.
None => {
// We don't know.
definitely_inhabited = false;
}
Some(true) => {}
}
}
if definitely_inhabited { Some(true) } else { None }
}

fn variant_find_init_error<'tcx>(
cx: &LateContext<'tcx>,
variant: &VariantDef,
substs: ty::SubstsRef<'tcx>,
descr: &str,
init: InitKind,
) -> Option<InitError> {
variant.fields.iter().find_map(|field| {
ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(|(mut msg, span)| {
if span.is_none() {
// Point to this field, should be helpful for figuring
// out where the source of the error is.
let span = cx.tcx.def_span(field.did);
write!(&mut msg, " (in this {descr})").unwrap();
(msg, Some(span))
} else {
// Just forward.
(msg, span)
}
})
})
}

/// Return `Some` only if we are sure this type does *not*
@@ -2468,14 +2518,15 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
RawPtr(_) if init == InitKind::Uninit => {
Some(("raw pointers must not be uninitialized".to_string(), None))
}
// Recurse and checks for some compound types.
// Recurse and checks for some compound types. (but not unions)
Adt(adt_def, substs) if !adt_def.is_union() => {
// First check if this ADT has a layout attribute (like `NonNull` and friends).
use std::ops::Bound;
match cx.tcx.layout_scalar_valid_range(adt_def.did()) {
// We exploit here that `layout_scalar_valid_range` will never
// return `Bound::Excluded`. (And we have tests checking that we
// handle the attribute correctly.)
// We don't add a span since users cannot declare such types anyway.
(Bound::Included(lo), _) if lo > 0 => {
return Some((format!("`{}` must be non-null", ty), None));
}
@@ -2492,50 +2543,65 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
}
_ => {}
}
// Now, recurse.
match adt_def.variants().len() {
0 => Some(("enums with no variants have no valid value".to_string(), None)),
1 => {
// Struct, or enum with exactly one variant.
// Proceed recursively, check all fields.
let variant = &adt_def.variant(VariantIdx::from_u32(0));
variant.fields.iter().find_map(|field| {
ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(
|(mut msg, span)| {
if span.is_none() {
// Point to this field, should be helpful for figuring
// out where the source of the error is.
let span = cx.tcx.def_span(field.did);
write!(
&mut msg,
" (in this {} field)",
adt_def.descr()
)
.unwrap();
(msg, Some(span))
} else {
// Just forward.
(msg, span)
}
},
)
})
}
// Multi-variant enum.
_ => {
if init == InitKind::Uninit && is_multi_variant(*adt_def) {
let span = cx.tcx.def_span(adt_def.did());
Some((
"enums have to be initialized to a variant".to_string(),
Some(span),
))
} else {
// In principle, for zero-initialization we could figure out which variant corresponds
// to tag 0, and check that... but for now we just accept all zero-initializations.
None
}
// Handle structs.
if adt_def.is_struct() {
return variant_find_init_error(
cx,
adt_def.non_enum_variant(),
substs,
"struct field",
init,
);
}
// And now, enums.
let span = cx.tcx.def_span(adt_def.did());
let mut potential_variants = adt_def.variants().iter().filter_map(|variant| {
let inhabited = tys_inhabited(
cx,
variant.fields.iter().map(|field| field.ty(cx.tcx, substs)),
);
let definitely_inhabited = match inhabited {
// Entirely skip uninhbaited variants.
Some(false) => return None,
// Forward the others, but remember which ones are definitely inhabited.
Some(true) => true,
None => false,
};
Some((variant, definitely_inhabited))
});
let Some(first_variant) = potential_variants.next() else {
return Some(("enums with no inhabited variants have no valid value".to_string(), Some(span)));
};
// So we have at least one potentially inhabited variant. Might we have two?
let Some(second_variant) = potential_variants.next() else {
// There is only one potentially inhabited variant. So we can recursively check that variant!
return variant_find_init_error(
cx,
&first_variant.0,
substs,
"field of the only potentially inhabited enum variant",
init,
);
};
// So we have at least two potentially inhabited variants.
// If we can prove that we have at least two *definitely* inhabited variants,
// then we have a tag and hence leaving this uninit is definitely disallowed.
// (Leaving it zeroed could be okay, depending on which variant is encoded as zero tag.)
if init == InitKind::Uninit {
let definitely_inhabited = (first_variant.1 as usize)
+ (second_variant.1 as usize)
+ potential_variants
.filter(|(_variant, definitely_inhabited)| *definitely_inhabited)
.count();
if definitely_inhabited > 1 {
return Some((
"enums with multiple inhabited variants have to be initialized to a variant".to_string(),
Some(span),
));
}
}
// We couldn't find anything wrong here.
None
}
Tuple(..) => {
// Proceed recursively, check all fields.
2 changes: 1 addition & 1 deletion compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Original file line number Diff line number Diff line change
@@ -1044,7 +1044,7 @@ extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
LLVMRustCodeModel Model) {
auto CM = fromRust(Model);
if (!CM.hasValue())
if (!CM)
return;
unwrap(M)->setCodeModel(*CM);
}
11 changes: 7 additions & 4 deletions compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
@@ -397,10 +397,13 @@ impl<'a> Parser<'a> {
fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
let span = self.prev_token.span;
let msg = "expected mut or const in raw pointer type";
self.struct_span_err(span, msg)
.span_label(span, msg)
.help("use `*mut T` or `*const T` as appropriate")
self.struct_span_err(span, "expected `mut` or `const` keyword in raw pointer type")
.span_suggestions(
span.shrink_to_hi(),
"add `mut` or `const` here",
["mut ".to_string(), "const ".to_string()].into_iter(),
Applicability::HasPlaceholders,
)
.emit();
Mutability::Not
});
8 changes: 0 additions & 8 deletions compiler/rustc_session/src/parse.rs
Original file line number Diff line number Diff line change
@@ -376,8 +376,6 @@ impl ParseSess {
}

#[rustc_lint_diagnostics]
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -386,22 +384,16 @@ impl ParseSess {
}

#[rustc_lint_diagnostics]
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.span_diagnostic.struct_warn(msg)
}

#[rustc_lint_diagnostics]
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
self.span_diagnostic.struct_fatal(msg)
}

#[rustc_lint_diagnostics]
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
pub fn struct_diagnostic<G: EmissionGuarantee>(
&self,
msg: impl Into<DiagnosticMessage>,
44 changes: 0 additions & 44 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
@@ -288,8 +288,6 @@ impl Session {
}

#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_warn<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -298,8 +296,6 @@ impl Session {
self.diagnostic().struct_span_warn(sp, msg)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -309,8 +305,6 @@ impl Session {
self.diagnostic().struct_span_warn_with_expectation(sp, msg, id)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -320,14 +314,10 @@ impl Session {
self.diagnostic().struct_span_warn_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_warn(msg)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_warn_with_expectation(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -336,8 +326,6 @@ impl Session {
self.diagnostic().struct_warn_with_expectation(msg, id)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_allow<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -346,14 +334,10 @@ impl Session {
self.diagnostic().struct_span_allow(sp, msg)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_allow(msg)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_expect(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -362,8 +346,6 @@ impl Session {
self.diagnostic().struct_expect(msg, id)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -372,8 +354,6 @@ impl Session {
self.diagnostic().struct_span_err(sp, msg)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -384,17 +364,13 @@ impl Session {
}
// FIXME: This method should be removed (every error should have an associated error code).
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
self.parse_sess.struct_err(msg)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_err_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -403,8 +379,6 @@ impl Session {
self.diagnostic().struct_err_with_code(msg, code)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_warn_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -413,8 +387,6 @@ impl Session {
self.diagnostic().struct_warn_with_code(msg, code)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_fatal<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -423,8 +395,6 @@ impl Session {
self.diagnostic().struct_span_fatal(sp, msg)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -434,21 +404,15 @@ impl Session {
self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
self.diagnostic().struct_fatal(msg)
}

#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
self.diagnostic().span_fatal(sp, msg)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_fatal_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -458,14 +422,10 @@ impl Session {
self.diagnostic().span_fatal_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! {
self.diagnostic().fatal(msg).raise()
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_err_or_warn<S: Into<MultiSpan>>(
&self,
is_warning: bool,
@@ -479,8 +439,6 @@ impl Session {
}
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -489,8 +447,6 @@ impl Session {
self.diagnostic().span_err(sp, msg)
}
#[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
1 change: 0 additions & 1 deletion library/core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -195,7 +195,6 @@
#![feature(link_llvm_intrinsics)]
#![feature(macro_metavar_expr)]
#![feature(min_specialization)]
#![feature(mixed_integer_ops)]
#![feature(must_not_suspend)]
#![feature(negative_impls)]
#![feature(never_type)]
40 changes: 16 additions & 24 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
@@ -464,12 +464,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_unsigned(2), Some(3));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_unsigned(3), None);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -533,12 +532,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_unsigned(2), Some(-1));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub_unsigned(3), None);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -907,12 +905,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_unsigned(2), 3);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add_unsigned(100), ", stringify!($SelfT), "::MAX);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -954,12 +951,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub_unsigned(127), -27);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub_unsigned(100), ", stringify!($SelfT), "::MIN);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1135,12 +1131,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_add_unsigned(27), 127);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add_unsigned(2), ", stringify!($SelfT), "::MIN + 1);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
@@ -1176,12 +1171,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".wrapping_sub_unsigned(127), -127);")]
#[doc = concat!("assert_eq!((-2", stringify!($SelfT), ").wrapping_sub_unsigned(", stringify!($UnsignedT), "::MAX), -1);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
@@ -1574,13 +1568,12 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_unsigned(2), (3, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN).overflowing_add_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MAX, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_unsigned(3), (", stringify!($SelfT), "::MIN, true));")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1658,13 +1651,12 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_unsigned(2), (-1, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX).overflowing_sub_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MIN, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).overflowing_sub_unsigned(3), (", stringify!($SelfT), "::MAX, true));")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
20 changes: 8 additions & 12 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
@@ -474,13 +474,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(2), Some(3));")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(-2), None);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_signed(3), None);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1057,13 +1056,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(2), 3);")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(-2), 0);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_add_signed(4), ", stringify!($SelfT), "::MAX);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1198,13 +1196,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(2), 3);")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(-2), ", stringify!($SelfT), "::MAX);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_add_signed(4), 1);")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1564,13 +1561,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
/// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(2), (3, false));")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(-2), (", stringify!($SelfT), "::MAX, true));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_signed(4), (1, true));")]
/// ```
#[unstable(feature = "mixed_integer_ops", issue = "87840")]
#[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
#[stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "mixed_integer_ops", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
1 change: 0 additions & 1 deletion library/std/src/lib.rs
Original file line number Diff line number Diff line change
@@ -294,7 +294,6 @@
#![feature(is_some_with)]
#![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_write_slice)]
#![feature(mixed_integer_ops)]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(panic_can_unwind)]
#![feature(panic_info_message)]
58 changes: 32 additions & 26 deletions src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
@@ -132,7 +132,7 @@ h1, h2, h3, h4, h5, h6 {
font-weight: 500;
}
h1, h2, h3, h4 {
margin: 20px 0 15px 0;
margin: 25px 0 15px 0;
padding-bottom: 6px;
}
.docblock h3, .docblock h4, h5, h6 {
@@ -176,8 +176,6 @@ h4.code-header {
border-bottom-style: none;
margin: 0;
padding: 0;
margin-top: 0.6rem;
margin-bottom: 0.4rem;
}
.impl,
.impl-items .method,
@@ -257,7 +255,9 @@ pre.rust a,
}

.content span.fn, .content a.fn,
.content .fnname {
.content .fnname,
.content span.method, .content a.method,
.content span.tymethod, .content a.tymethod {
color: var(--function-link-color);
}

@@ -292,6 +292,11 @@ p {
https://www.w3.org/WAI/WCAG21/Understanding/visual-presentation.html */
margin: 0 0 .75em 0;
}
/* For the last child of a div, the margin will be taken care of
by the margin-top of the next item. */
p:last-child {
margin: 0;
}

summary {
outline: none;
@@ -565,9 +570,16 @@ h2.location a {

.rustdoc .example-wrap {
display: flex;
margin-bottom: 10px;
position: relative;
}
.rustdoc .example-wrap {
margin-bottom: 10px;
}
/* For the last child of a div, the margin will be taken care of
by the margin-top of the next item. */
.rustdoc .example-wrap:last-child {
margin-bottom: 0px;
}

pre.example-line-numbers {
overflow: initial;
@@ -726,10 +738,6 @@ pre, .rustdoc.source .example-wrap {
margin-left: 24px;
}

.content .impl-items .docblock, .content .impl-items .item-info {
margin-bottom: .6em;
}

#main-content > .item-info {
margin-top: 0;
margin-left: 0;
@@ -1019,8 +1027,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
font-size: 1.125rem;
}
#help-button span.top {
text-align: center;
display: block;
margin: 10px 0;
border-bottom: 1px solid var(--border-color);
padding-bottom: 4px;
@@ -1030,9 +1036,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
clear: both;
border-top: 1px solid var(--border-color);
}
.side-by-side {
text-align: initial;
}
.side-by-side > div {
width: 50%;
float: left;
@@ -1110,13 +1113,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
color: var(--right-side-color);
}


.impl-items .srclink, .impl .srclink, .methods .srclink {
/* Override header settings otherwise it's too bold */
font-weight: normal;
font-size: 1rem;
}

pre.rust .question-mark {
font-weight: bold;
}
@@ -1532,6 +1528,16 @@ details.dir-entry a {
display: block;
}

/* We use CSS containment on the details elements because most sizeable elements
of the page are contained in one of these. This also makes re-rendering
faster on document changes (like closing and opening toggles).
Unfortunately we can't yet specify contain: content or contain: strict
because the [-]/[+] toggles extend past the boundaries of the <details>
https://developer.mozilla.org/en-US/docs/Web/CSS/contain */
details.rustdoc-toggle {
contain: layout;
}

/* The hideme class is used on summary tags that contain a span with
placeholder text shown only when the toggle is closed. For instance,
"Expand description" or "Show methods". */
@@ -2012,17 +2018,17 @@ in storage.js plus the media query with (min-width: 701px)
margin-bottom: 0.75em;
}

.method-toggle[open] {
.method-toggle[open]:not(:last-child) {
margin-bottom: 2em;
}

.implementors-toggle[open] {
.implementors-toggle[open]:not(:last-child) {
margin-bottom: 2em;
}

#trait-implementations-list .method-toggle,
#synthetic-implementations-list .method-toggle,
#blanket-implementations-list .method-toggle {
#trait-implementations-list .method-toggle:not(:last-child),
#synthetic-implementations-list .method-toggle:not(:last-child),
#blanket-implementations-list .method-toggle:not(:last-child) {
margin-bottom: 1em;
}

153 changes: 149 additions & 4 deletions src/test/rustdoc-gui/search-result-color.goml
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@ show-text: true
// Ayu theme
local-storage: {
"rustdoc-theme": "ayu",
"rustdoc-preferred-dark-theme": "ayu",
"rustdoc-use-system-theme": "false",
}
reload:
@@ -23,16 +22,66 @@ assert-css: (
{"color": "rgb(0, 150, 207)"},
)

// Checking the color for "keyword".
// Checking the color of "keyword" text.
assert-css: (
"//*[@class='result-name']//*[text()='(keyword)']",
{"color": "rgb(120, 135, 151)"},
)

// Checking the color of "keyword".
assert-css: (
".result-name .keyword",
{"color": "rgb(57, 175, 215)"},
ALL,
)
// Check the color of "struct".
assert-css: (
".result-name .struct",
{"color": "rgb(255, 160, 165)"},
ALL,
)
// Check the color of "associated type".
assert-css: (
".result-name .associatedtype",
{"color": "rgb(57, 175, 215)"},
ALL,
)
// Check the color of "type method".
assert-css: (
".result-name .tymethod",
{"color": "rgb(253, 214, 135)"},
ALL,
)
// Check the color of "method".
assert-css: (
".result-name .method",
{"color": "rgb(253, 214, 135)"},
ALL,
)
// Check the color of "struct field".
assert-css: (
".result-name .structfield",
{"color": "rgb(0, 150, 207)"},
ALL,
)
// Check the color of "macro".
assert-css: (
".result-name .macro",
{"color": "rgb(163, 122, 204)"},
ALL,
)
// Check the color of "fn".
assert-css: (
".result-name .fn",
{"color": "rgb(253, 214, 135)"},
ALL,
)

// Checking the `<a>` container.
assert-css: (
"//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
{"color": "rgb(0, 150, 207)", "background-color": "rgba(0, 0, 0, 0)"},
ALL,
)

// Checking color and background on hover.
@@ -49,7 +98,6 @@ assert-css: (
// Dark theme
local-storage: {
"rustdoc-theme": "dark",
"rustdoc-preferred-dark-theme": "dark",
"rustdoc-use-system-theme": "false",
}
reload:
@@ -71,6 +119,55 @@ assert-css: (
{"color": "rgb(221, 221, 221)"},
)

// Checking the color of "keyword".
assert-css: (
".result-name .keyword",
{"color": "rgb(210, 153, 29)"},
ALL,
)
// Check the color of "struct".
assert-css: (
".result-name .struct",
{"color": "rgb(45, 191, 184)"},
ALL,
)
// Check the color of "associated type".
assert-css: (
".result-name .associatedtype",
{"color": "rgb(210, 153, 29)"},
ALL,
)
// Check the color of "type method".
assert-css: (
".result-name .tymethod",
{"color": "rgb(43, 171, 99)"},
ALL,
)
// Check the color of "method".
assert-css: (
".result-name .method",
{"color": "rgb(43, 171, 99)"},
ALL,
)
// Check the color of "struct field".
assert-css: (
".result-name .structfield",
{"color": "rgb(221, 221, 221)"},
ALL,
)
// Check the color of "macro".
assert-css: (
".result-name .macro",
{"color": "rgb(9, 189, 0)"},
ALL,
)
// Check the color of "fn".
assert-css: (
".result-name .fn",
{"color": "rgb(43, 171, 99)"},
ALL,
)

// Checking the `<a>` container.
assert-css: (
"//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
@@ -109,6 +206,55 @@ assert-css: (
{"color": "rgb(0, 0, 0)"},
)

// Checking the color of "keyword".
assert-css: (
".result-name .keyword",
{"color": "rgb(56, 115, 173)"},
ALL,
)
// Check the color of "struct".
assert-css: (
".result-name .struct",
{"color": "rgb(173, 55, 138)"},
ALL,
)
// Check the color of "associated type".
assert-css: (
".result-name .associatedtype",
{"color": "rgb(56, 115, 173)"},
ALL,
)
// Check the color of "type method".
assert-css: (
".result-name .tymethod",
{"color": "rgb(173, 124, 55)"},
ALL,
)
// Check the color of "method".
assert-css: (
".result-name .method",
{"color": "rgb(173, 124, 55)"},
ALL,
)
// Check the color of "struct field".
assert-css: (
".result-name .structfield",
{"color": "rgb(0, 0, 0)"},
ALL,
)
// Check the color of "macro".
assert-css: (
".result-name .macro",
{"color": "rgb(6, 128, 0)"},
ALL,
)
// Check the color of "fn".
assert-css: (
".result-name .fn",
{"color": "rgb(173, 124, 55)"},
ALL,
)

// Checking the `<a>` container.
assert-css: (
"//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
@@ -132,7 +278,6 @@ goto: file://|DOC_PATH|/test_docs/index.html
// this test is running on.
local-storage: {
"rustdoc-theme": "dark",
"rustdoc-preferred-dark-theme": "dark",
"rustdoc-use-system-theme": "false",
}
// If the text isn't displayed, the browser doesn't compute color style correctly...
6 changes: 3 additions & 3 deletions src/test/rustdoc-gui/sidebar-mobile-scroll.goml
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ assert-css: (".sidebar", {"display": "block", "left": "-1000px"})

// Scroll down.
scroll-to: "//h2[@id='blanket-implementations']"
assert-window-property: {"pageYOffset": "643"}
assert-window-property: {"pageYOffset": "639"}

// Open the sidebar menu.
click: ".sidebar-menu-toggle"
@@ -21,11 +21,11 @@ assert-window-property: {"pageYOffset": "0"}
// Close the sidebar menu. Make sure the scroll position gets restored.
click: ".sidebar-menu-toggle"
wait-for-css: (".sidebar", {"left": "-1000px"})
assert-window-property: {"pageYOffset": "643"}
assert-window-property: {"pageYOffset": "639"}

// Now test that scrollability returns when the browser window is just resized.
click: ".sidebar-menu-toggle"
wait-for-css: (".sidebar", {"left": "0px"})
assert-window-property: {"pageYOffset": "0"}
size: (900, 600)
assert-window-property: {"pageYOffset": "643"}
assert-window-property: {"pageYOffset": "639"}
3 changes: 3 additions & 0 deletions src/test/rustdoc-gui/src/lib2/lib.rs
Original file line number Diff line number Diff line change
@@ -38,11 +38,14 @@ pub trait Trait {

#[deprecated = "Whatever [`Foo`](#tadam)"]
fn foo() {}
fn fooo();
}

impl Trait for Foo {
type X = u32;
const Y: u32 = 0;

fn fooo() {}
}

impl implementors::Whatever for Foo {
36 changes: 18 additions & 18 deletions src/test/ui/consts/const-eval/ub-enum.32bit.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:23:1
--> $DIR/ub-enum.rs:24:1
|
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000001, but expected a valid enum tag
@@ -10,7 +10,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:26:1
--> $DIR/ub-enum.rs:27:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -22,7 +22,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:30:1
--> $DIR/ub-enum.rs:31:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -33,7 +33,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:43:1
--> $DIR/ub-enum.rs:44:1
|
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000000, but expected a valid enum tag
@@ -44,7 +44,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:45:1
--> $DIR/ub-enum.rs:46:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -55,7 +55,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:49:1
--> $DIR/ub-enum.rs:50:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -66,13 +66,13 @@ LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:59:42
--> $DIR/ub-enum.rs:60:42
|
LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:64:1
--> $DIR/ub-enum.rs:65:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -83,7 +83,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:82:1
--> $DIR/ub-enum.rs:83:1
|
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(B)>.0: encountered a value of the never type `!`
@@ -94,7 +94,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:84:1
--> $DIR/ub-enum.rs:85:1
|
LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
@@ -105,7 +105,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:92:1
--> $DIR/ub-enum.rs:93:1
|
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
@@ -116,13 +116,13 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
}

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:97:77
--> $DIR/ub-enum.rs:98:77
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:99:77
--> $DIR/ub-enum.rs:100:77
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
@@ -132,7 +132,7 @@ error: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0080`.
Future incompatibility report: Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:26:1
--> $DIR/ub-enum.rs:27:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -145,7 +145,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:30:1
--> $DIR/ub-enum.rs:31:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -158,7 +158,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:45:1
--> $DIR/ub-enum.rs:46:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -171,7 +171,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:49:1
--> $DIR/ub-enum.rs:50:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -184,7 +184,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:64:1
--> $DIR/ub-enum.rs:65:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
36 changes: 18 additions & 18 deletions src/test/ui/consts/const-eval/ub-enum.64bit.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:23:1
--> $DIR/ub-enum.rs:24:1
|
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000001, but expected a valid enum tag
@@ -10,7 +10,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:26:1
--> $DIR/ub-enum.rs:27:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -22,7 +22,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:30:1
--> $DIR/ub-enum.rs:31:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -33,7 +33,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:43:1
--> $DIR/ub-enum.rs:44:1
|
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag
@@ -44,7 +44,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:45:1
--> $DIR/ub-enum.rs:46:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -55,7 +55,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:49:1
--> $DIR/ub-enum.rs:50:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -66,13 +66,13 @@ LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:59:42
--> $DIR/ub-enum.rs:60:42
|
LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:64:1
--> $DIR/ub-enum.rs:65:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -83,7 +83,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:82:1
--> $DIR/ub-enum.rs:83:1
|
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(B)>.0: encountered a value of the never type `!`
@@ -94,7 +94,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:84:1
--> $DIR/ub-enum.rs:85:1
|
LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
@@ -105,7 +105,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:92:1
--> $DIR/ub-enum.rs:93:1
|
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
@@ -116,13 +116,13 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
}

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:97:77
--> $DIR/ub-enum.rs:98:77
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:99:77
--> $DIR/ub-enum.rs:100:77
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
@@ -132,7 +132,7 @@ error: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0080`.
Future incompatibility report: Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:26:1
--> $DIR/ub-enum.rs:27:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -145,7 +145,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:30:1
--> $DIR/ub-enum.rs:31:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -158,7 +158,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:45:1
--> $DIR/ub-enum.rs:46:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -171,7 +171,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:49:1
--> $DIR/ub-enum.rs:50:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -184,7 +184,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:64:1
--> $DIR/ub-enum.rs:65:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
1 change: 1 addition & 0 deletions src/test/ui/consts/const-eval/ub-enum.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// stderr-per-bitwidth
#![feature(never_type)]
#![allow(invalid_value)]

use std::mem;

Original file line number Diff line number Diff line change
@@ -40,11 +40,11 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
note: enums with no variants have no valid value (in this struct field)
--> $DIR/validate_uninhabited_zsts.rs:16:22
note: enums with no inhabited variants have no valid value
--> $DIR/validate_uninhabited_zsts.rs:13:5
|
LL | pub struct Empty(Void);
| ^^^^
LL | enum Void {}
| ^^^^^^^^^

error: aborting due to 2 previous errors; 2 warnings emitted

Original file line number Diff line number Diff line change
@@ -40,11 +40,11 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
note: enums with no variants have no valid value (in this struct field)
--> $DIR/validate_uninhabited_zsts.rs:16:22
note: enums with no inhabited variants have no valid value
--> $DIR/validate_uninhabited_zsts.rs:13:5
|
LL | pub struct Empty(Void);
| ^^^^
LL | enum Void {}
| ^^^^^^^^^

error: aborting due to 2 previous errors; 2 warnings emitted

Original file line number Diff line number Diff line change
@@ -34,6 +34,16 @@ enum OneFruit {
Banana,
}

enum OneFruitNonZero {
Apple(!),
Banana(NonZeroU32),
}

enum TwoUninhabited {
A(!),
B(Void),
}

#[allow(unused)]
fn generic<T: 'static>() {
unsafe {
@@ -84,6 +94,12 @@ fn main() {
let _val: [fn(); 2] = mem::zeroed(); //~ ERROR: does not permit zero-initialization
let _val: [fn(); 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

let _val: TwoUninhabited = mem::zeroed(); //~ ERROR: does not permit zero-initialization
let _val: TwoUninhabited = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

let _val: OneFruitNonZero = mem::zeroed(); //~ ERROR: does not permit zero-initialization
let _val: OneFruitNonZero = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

// Things that can be zero, but not uninit.
let _val: bool = mem::zeroed();
let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
@@ -112,6 +128,16 @@ fn main() {
let _val: *const [()] = mem::zeroed();
let _val: *const [()] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

// Things where 0 is okay due to rustc implementation details,
// but that are not guaranteed to keep working.
let _val: Result<i32, i32> = mem::zeroed();
let _val: Result<i32, i32> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized

// Some things that happen to work due to rustc implementation details,
// but are not guaranteed to keep working.
let _val: OneFruit = mem::zeroed();
let _val: OneFruit = mem::uninitialized();

// Transmute-from-0
let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization
let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization
@@ -129,9 +155,5 @@ fn main() {
let _val: bool = MaybeUninit::zeroed().assume_init();
let _val: [bool; 0] = MaybeUninit::uninit().assume_init();
let _val: [!; 0] = MaybeUninit::zeroed().assume_init();

// Some things that happen to work due to rustc implementation details,
// but are not guaranteed to keep working.
let _val: OneFruit = mem::uninitialized();
}
}

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/test/ui/parser/bad-pointer-type.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fn foo(_: *()) {
//~^ ERROR expected mut or const in raw pointer type
//~^ ERROR expected `mut` or `const` keyword in raw pointer type
}

fn main() {}
11 changes: 8 additions & 3 deletions src/test/ui/parser/bad-pointer-type.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
error: expected mut or const in raw pointer type
error: expected `mut` or `const` keyword in raw pointer type
--> $DIR/bad-pointer-type.rs:1:11
|
LL | fn foo(_: *()) {
| ^ expected mut or const in raw pointer type
| ^
|
= help: use `*mut T` or `*const T` as appropriate
help: add `mut` or `const` here
|
LL | fn foo(_: *const ()) {
| +++++
LL | fn foo(_: *mut ()) {
| +++

error: aborting due to previous error

7 changes: 7 additions & 0 deletions src/test/ui/parser/double-pointer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn main() {
let x: i32 = 5;
let ptr: *const i32 = &x;
let dptr: **const i32 = &ptr;
//~^ ERROR expected `mut` or `const` keyword in raw pointer type
//~| HELP add `mut` or `const` here
}
15 changes: 15 additions & 0 deletions src/test/ui/parser/double-pointer.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: expected `mut` or `const` keyword in raw pointer type
--> $DIR/double-pointer.rs:4:15
|
LL | let dptr: **const i32 = &ptr;
| ^
|
help: add `mut` or `const` here
|
LL | let dptr: *const *const i32 = &ptr;
| +++++
LL | let dptr: *mut *const i32 = &ptr;
| +++

error: aborting due to previous error

12 changes: 10 additions & 2 deletions src/test/ui/statics/uninhabited-static.stderr
Original file line number Diff line number Diff line change
@@ -59,7 +59,11 @@ LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
= note: `#[warn(invalid_value)]` on by default
= note: enums with no variants have no valid value
note: enums with no inhabited variants have no valid value
--> $DIR/uninhabited-static.rs:4:1
|
LL | enum Void {}
| ^^^^^^^^^

error[E0080]: could not evaluate static initializer
--> $DIR/uninhabited-static.rs:16:32
@@ -76,7 +80,11 @@ LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
= note: enums with no variants have no valid value
note: enums with no inhabited variants have no valid value
--> $DIR/uninhabited-static.rs:4:1
|
LL | enum Void {}
| ^^^^^^^^^

error: aborting due to 6 previous errors; 2 warnings emitted