Skip to content

Commit f22819b

Browse files
committed
Auto merge of #100456 - Dylan-DPC:rollup-fn17z9f, r=Dylan-DPC
Rollup of 9 pull requests Successful merges: - #100022 (Optimize thread ID generation) - #100030 (cleanup code w/ pointers in std a little) - #100229 (add -Zextra-const-ub-checks to enable more UB checking in const-eval) - #100247 (Generalize trait object generic param check to aliases.) - #100255 (Adding more verbose documentation for `std::fmt::Write`) - #100366 (errors: don't fail on broken primary translations) - #100396 (Suggest const and static for global variable) - #100409 (rustdoc: don't generate DOM element for operator) - #100443 (Add two let else regression tests) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 0068b8b + 3bc30bb commit f22819b

Some content is hidden

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

50 files changed

+584
-258
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

+10
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,16 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
236236

237237
const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error
238238

239+
#[inline(always)]
240+
fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
241+
ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks
242+
}
243+
244+
#[inline(always)]
245+
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
246+
ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks
247+
}
248+
239249
fn load_mir(
240250
ecx: &InterpCx<'mir, 'tcx, Self>,
241251
instance: ty::InstanceDef<'tcx>,

compiler/rustc_const_eval/src/interpret/machine.rs

-12
Original file line numberDiff line numberDiff line change
@@ -436,24 +436,12 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
436436
type AllocExtra = ();
437437
type FrameExtra = ();
438438

439-
#[inline(always)]
440-
fn enforce_alignment(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
441-
// We do not check for alignment to avoid having to carry an `Align`
442-
// in `ConstValue::ByRef`.
443-
false
444-
}
445-
446439
#[inline(always)]
447440
fn force_int_for_alignment_check(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
448441
// We do not support `force_int`.
449442
false
450443
}
451444

452-
#[inline(always)]
453-
fn enforce_validity(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
454-
false // for now, we don't enforce validity
455-
}
456-
457445
#[inline(always)]
458446
fn enforce_number_init(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
459447
true

compiler/rustc_const_eval/src/interpret/validity.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
10051005
/// It will error if the bits at the destination do not match the ones described by the layout.
10061006
#[inline(always)]
10071007
pub fn validate_operand(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
1008+
// Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's
1009+
// still correct to not use `ctfe_mode`: that mode is for validation of the final constant
1010+
// value, it rules out things like `UnsafeCell` in awkward places. It also can make checking
1011+
// recurse through references which, for now, we don't want here, either.
10081012
self.validate_operand_internal(op, vec![], None, None)
10091013
}
10101014
}

compiler/rustc_errors/src/emitter.rs

+49-31
Original file line numberDiff line numberDiff line change
@@ -273,40 +273,58 @@ pub trait Emitter {
273273
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
274274
};
275275

276-
let bundle = match self.fluent_bundle() {
277-
Some(bundle) if bundle.has_message(&identifier) => bundle,
278-
_ => self.fallback_fluent_bundle(),
279-
};
276+
let translate_with_bundle = |bundle: &'a FluentBundle| -> Option<(Cow<'_, str>, Vec<_>)> {
277+
let message = bundle.get_message(&identifier)?;
278+
let value = match attr {
279+
Some(attr) => message.get_attribute(attr)?.value(),
280+
None => message.value()?,
281+
};
282+
debug!(?message, ?value);
280283

281-
let message = bundle.get_message(&identifier).expect("missing diagnostic in fluent bundle");
282-
let value = match attr {
283-
Some(attr) => {
284-
if let Some(attr) = message.get_attribute(attr) {
285-
attr.value()
286-
} else {
287-
panic!("missing attribute `{attr}` in fluent message `{identifier}`")
288-
}
289-
}
290-
None => {
291-
if let Some(value) = message.value() {
292-
value
293-
} else {
294-
panic!("missing value in fluent message `{identifier}`")
295-
}
296-
}
284+
let mut errs = vec![];
285+
let translated = bundle.format_pattern(value, Some(&args), &mut errs);
286+
debug!(?translated, ?errs);
287+
Some((translated, errs))
297288
};
298289

299-
let mut err = vec![];
300-
let translated = bundle.format_pattern(value, Some(&args), &mut err);
301-
trace!(?translated, ?err);
302-
debug_assert!(
303-
err.is_empty(),
304-
"identifier: {:?}, args: {:?}, errors: {:?}",
305-
identifier,
306-
args,
307-
err
308-
);
309-
translated
290+
self.fluent_bundle()
291+
.and_then(|bundle| translate_with_bundle(bundle))
292+
// If `translate_with_bundle` returns `None` with the primary bundle, this is likely
293+
// just that the primary bundle doesn't contain the message being translated, so
294+
// proceed to the fallback bundle.
295+
//
296+
// However, when errors are produced from translation, then that means the translation
297+
// is broken (e.g. `{$foo}` exists in a translation but `foo` isn't provided).
298+
//
299+
// In debug builds, assert so that compiler devs can spot the broken translation and
300+
// fix it..
301+
.inspect(|(_, errs)| {
302+
debug_assert!(
303+
errs.is_empty(),
304+
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
305+
identifier,
306+
attr,
307+
args,
308+
errs
309+
);
310+
})
311+
// ..otherwise, for end users, an error about this wouldn't be useful or actionable, so
312+
// just hide it and try with the fallback bundle.
313+
.filter(|(_, errs)| errs.is_empty())
314+
.or_else(|| translate_with_bundle(self.fallback_fluent_bundle()))
315+
.map(|(translated, errs)| {
316+
// Always bail out for errors with the fallback bundle.
317+
assert!(
318+
errs.is_empty(),
319+
"identifier: {:?}, attr: {:?}, args: {:?}, errors: {:?}",
320+
identifier,
321+
attr,
322+
args,
323+
errs
324+
);
325+
translated
326+
})
327+
.expect("failed to find message in primary or fallback fluent bundles")
310328
}
311329

312330
/// Formats the substitutions of the primary_span

compiler/rustc_errors/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
#![feature(drain_filter)]
77
#![feature(if_let_guard)]
88
#![cfg_attr(bootstrap, feature(let_chains))]
9+
#![feature(adt_const_params)]
910
#![feature(let_else)]
1011
#![feature(never_type)]
11-
#![feature(adt_const_params)]
12+
#![feature(result_option_inspect)]
1213
#![feature(rustc_attrs)]
1314
#![allow(incomplete_features)]
1415
#![allow(rustc::potential_query_instability)]

compiler/rustc_mir_transform/src/const_prop.rs

+12
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,18 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
183183

184184
type MemoryKind = !;
185185

186+
#[inline(always)]
187+
fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
188+
// We do not check for alignment to avoid having to carry an `Align`
189+
// in `ConstValue::ByRef`.
190+
false
191+
}
192+
193+
#[inline(always)]
194+
fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
195+
false // for now, we don't enforce validity
196+
}
197+
186198
fn load_mir(
187199
_ecx: &InterpCx<'mir, 'tcx, Self>,
188200
_instance: ty::InstanceDef<'tcx>,

compiler/rustc_parse/src/parser/item.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,12 @@ impl<'a> Parser<'a> {
6868
if !self.maybe_consume_incorrect_semicolon(&items) {
6969
let msg = &format!("expected item, found {token_str}");
7070
let mut err = self.struct_span_err(self.token.span, msg);
71-
err.span_label(self.token.span, "expected item");
71+
let label = if self.is_kw_followed_by_ident(kw::Let) {
72+
"consider using `const` or `static` instead of `let` for global variables"
73+
} else {
74+
"expected item"
75+
};
76+
err.span_label(self.token.span, label);
7277
return Err(err);
7378
}
7479
}

compiler/rustc_session/src/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,8 @@ options! {
13101310
"emit the bc module with thin LTO info (default: yes)"),
13111311
export_executable_symbols: bool = (false, parse_bool, [TRACKED],
13121312
"export symbols from executables, as if they were dynamic libraries"),
1313+
extra_const_ub_checks: bool = (false, parse_bool, [TRACKED],
1314+
"turns on more checks to detect const UB, which can be slow (default: no)"),
13131315
#[cfg_attr(not(bootstrap), rustc_lint_opt_deny_field_access("use `Session::fewer_names` instead of this field"))]
13141316
fewer_names: Option<bool> = (None, parse_opt_bool, [TRACKED],
13151317
"reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) \

0 commit comments

Comments
 (0)