Skip to content

Commit bf5e6cc

Browse files
committed
Auto merge of #144058 - matthiaskrgr:rollup-xezozsk, r=matthiaskrgr
Rollup of 11 pull requests Successful merges: - #143326 (Remove deprecated `Error::description` impl from `c_str::FromBytesWithNulError`) - #143431 (Use relative visibility when noting sealed trait to reduce false positive) - #143550 (resolve: Use interior mutability for extern module map) - #143631 (update to literal-escaper-0.0.5) - #143793 (Opaque type collection: Guard against endlessly recursing free alias types) - #143880 (tests: Test line debuginfo for linebreaked function parameters) - #143914 (Reword mismatched-lifetime-syntaxes text based on feedback) - #143926 (Remove deprecated fields in bootstrap) - #143955 (Make frame spans appear on a separate trace line) - #143975 (type_id_eq: check that the hash fully matches the type) - #143984 (Fix ice for feature-gated `cfg` attributes applied to the crate) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 8c12d76 + 5286836 commit bf5e6cc

File tree

74 files changed

+1205
-746
lines changed

Some content is hidden

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

74 files changed

+1205
-746
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3136,9 +3136,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
31363136

31373137
[[package]]
31383138
name = "rustc-literal-escaper"
3139-
version = "0.0.4"
3139+
version = "0.0.5"
31403140
source = "registry+https://github.com/rust-lang/crates.io-index"
3141-
checksum = "ab03008eb631b703dd16978282ae36c73282e7922fe101a4bd072a40ecea7b8b"
3141+
checksum = "e4ee29da77c5a54f42697493cd4c9b9f31b74df666a6c04dfc4fde77abe0438b"
31423142

31433143
[[package]]
31443144
name = "rustc-main"

compiler/rustc_ast/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ edition = "2024"
77
# tidy-alphabetical-start
88
bitflags = "2.4.1"
99
memchr = "2.7.4"
10-
rustc-literal-escaper = "0.0.4"
10+
rustc-literal-escaper = "0.0.5"
1111
rustc_ast_ir = { path = "../rustc_ast_ir" }
1212
rustc_data_structures = { path = "../rustc_data_structures" }
1313
rustc_index = { path = "../rustc_index" }

compiler/rustc_ast/src/util/literal.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,11 @@ impl LitKind {
126126
token::CStr => {
127127
let s = symbol.as_str();
128128
let mut buf = Vec::with_capacity(s.len());
129-
unescape_c_str(s, |_span, c| match c {
129+
unescape_c_str(s, |_span, res| match res {
130130
Ok(MixedUnit::Char(c)) => {
131-
buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
131+
buf.extend_from_slice(c.get().encode_utf8(&mut [0; 4]).as_bytes())
132132
}
133-
Ok(MixedUnit::HighByte(b)) => buf.push(b),
133+
Ok(MixedUnit::HighByte(b)) => buf.push(b.get()),
134134
Err(err) => {
135135
assert!(!err.is_fatal(), "failed to unescape C string literal")
136136
}

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_session::parse::feature_err;
99
use rustc_span::{Span, Symbol, sym};
1010
use thin_vec::ThinVec;
1111

12-
use crate::context::{AcceptContext, Stage};
12+
use crate::context::{AcceptContext, ShouldEmit, Stage};
1313
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser};
1414
use crate::{
1515
CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, try_gate_cfg,
@@ -90,7 +90,7 @@ fn parse_cfg_entry_version<S: Stage>(
9090
list: &MetaItemListParser<'_>,
9191
meta_span: Span,
9292
) -> Option<CfgEntry> {
93-
try_gate_cfg(sym::version, meta_span, cx.sess(), Some(cx.features()));
93+
try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option());
9494
let Some(version) = list.single() else {
9595
cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span });
9696
return None;
@@ -119,7 +119,9 @@ fn parse_cfg_entry_target<S: Stage>(
119119
list: &MetaItemListParser<'_>,
120120
meta_span: Span,
121121
) -> Option<CfgEntry> {
122-
if !cx.features().cfg_target_compact() {
122+
if let Some(features) = cx.features_option()
123+
&& !features.cfg_target_compact()
124+
{
123125
feature_err(
124126
cx.sess(),
125127
sym::cfg_target_compact,
@@ -186,12 +188,13 @@ pub fn eval_config_entry(
186188
cfg_entry: &CfgEntry,
187189
id: NodeId,
188190
features: Option<&Features>,
191+
emit_lints: ShouldEmit,
189192
) -> EvalConfigResult {
190193
match cfg_entry {
191194
CfgEntry::All(subs, ..) => {
192195
let mut all = None;
193196
for sub in subs {
194-
let res = eval_config_entry(sess, sub, id, features);
197+
let res = eval_config_entry(sess, sub, id, features, emit_lints);
195198
// We cannot short-circuit because `eval_config_entry` emits some lints
196199
if !res.as_bool() {
197200
all.get_or_insert(res);
@@ -202,7 +205,7 @@ pub fn eval_config_entry(
202205
CfgEntry::Any(subs, span) => {
203206
let mut any = None;
204207
for sub in subs {
205-
let res = eval_config_entry(sess, sub, id, features);
208+
let res = eval_config_entry(sess, sub, id, features, emit_lints);
206209
// We cannot short-circuit because `eval_config_entry` emits some lints
207210
if res.as_bool() {
208211
any.get_or_insert(res);
@@ -214,7 +217,7 @@ pub fn eval_config_entry(
214217
})
215218
}
216219
CfgEntry::Not(sub, span) => {
217-
if eval_config_entry(sess, sub, id, features).as_bool() {
220+
if eval_config_entry(sess, sub, id, features, emit_lints).as_bool() {
218221
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
219222
} else {
220223
EvalConfigResult::True
@@ -228,24 +231,28 @@ pub fn eval_config_entry(
228231
}
229232
}
230233
CfgEntry::NameValue { name, name_span, value, span } => {
231-
match sess.psess.check_config.expecteds.get(name) {
232-
Some(ExpectedValues::Some(values)) if !values.contains(&value.map(|(v, _)| v)) => {
233-
id.emit_span_lint(
234-
sess,
235-
UNEXPECTED_CFGS,
236-
*span,
237-
BuiltinLintDiag::UnexpectedCfgValue((*name, *name_span), *value),
238-
);
234+
if let ShouldEmit::ErrorsAndLints = emit_lints {
235+
match sess.psess.check_config.expecteds.get(name) {
236+
Some(ExpectedValues::Some(values))
237+
if !values.contains(&value.map(|(v, _)| v)) =>
238+
{
239+
id.emit_span_lint(
240+
sess,
241+
UNEXPECTED_CFGS,
242+
*span,
243+
BuiltinLintDiag::UnexpectedCfgValue((*name, *name_span), *value),
244+
);
245+
}
246+
None if sess.psess.check_config.exhaustive_names => {
247+
id.emit_span_lint(
248+
sess,
249+
UNEXPECTED_CFGS,
250+
*span,
251+
BuiltinLintDiag::UnexpectedCfgName((*name, *name_span), *value),
252+
);
253+
}
254+
_ => { /* not unexpected */ }
239255
}
240-
None if sess.psess.check_config.exhaustive_names => {
241-
id.emit_span_lint(
242-
sess,
243-
UNEXPECTED_CFGS,
244-
*span,
245-
BuiltinLintDiag::UnexpectedCfgName((*name, *name_span), *value),
246-
);
247-
}
248-
_ => { /* not unexpected */ }
249256
}
250257

251258
if sess.psess.config.contains(&(*name, value.map(|(v, _)| v))) {

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ impl Stage for Early {
226226
sess: &'sess Session,
227227
diag: impl for<'x> Diagnostic<'x>,
228228
) -> ErrorGuaranteed {
229-
if self.emit_errors {
229+
if self.emit_errors.should_emit() {
230230
sess.dcx().emit_err(diag)
231231
} else {
232232
sess.dcx().create_err(diag).delay_as_bug()
@@ -257,7 +257,7 @@ pub struct Early {
257257
/// Whether to emit errors or delay them as a bug
258258
/// For most attributes, the attribute will be parsed again in the `Late` stage and in this case the errors should be delayed
259259
/// But for some, such as `cfg`, the attribute will be removed before the `Late` stage so errors must be emitted
260-
pub emit_errors: bool,
260+
pub emit_errors: ShouldEmit,
261261
}
262262
/// used when parsing attributes during ast lowering
263263
pub struct Late;
@@ -558,6 +558,25 @@ pub enum OmitDoc {
558558
Skip,
559559
}
560560

561+
#[derive(Copy, Clone)]
562+
pub enum ShouldEmit {
563+
/// The operation will emit errors and lints.
564+
/// This is usually what you need.
565+
ErrorsAndLints,
566+
/// The operation will emit *not* errors and lints.
567+
/// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::Emit`.
568+
Nothing,
569+
}
570+
571+
impl ShouldEmit {
572+
pub fn should_emit(&self) -> bool {
573+
match self {
574+
ShouldEmit::ErrorsAndLints => true,
575+
ShouldEmit::Nothing => false,
576+
}
577+
}
578+
}
579+
561580
/// Context created once, for example as part of the ast lowering
562581
/// context, through which all attributes can be lowered.
563582
pub struct AttributeParser<'sess, S: Stage = Late> {
@@ -600,7 +619,7 @@ impl<'sess> AttributeParser<'sess, Early> {
600619
tools: Vec::new(),
601620
parse_only: Some(sym),
602621
sess,
603-
stage: Early { emit_errors: false },
622+
stage: Early { emit_errors: ShouldEmit::Nothing },
604623
};
605624
let mut parsed = p.parse_attribute_list(
606625
attrs,
@@ -623,7 +642,7 @@ impl<'sess> AttributeParser<'sess, Early> {
623642
target_span: Span,
624643
target_node_id: NodeId,
625644
features: Option<&'sess Features>,
626-
emit_errors: bool,
645+
emit_errors: ShouldEmit,
627646
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
628647
template: &AttributeTemplate,
629648
) -> T {

compiler/rustc_attr_parsing/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ pub use attributes::cfg_old::*;
9595
pub use attributes::util::{
9696
find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version,
9797
};
98-
pub use context::{AttributeParser, Early, Late, OmitDoc};
98+
pub use context::{AttributeParser, Early, Late, OmitDoc, ShouldEmit};
9999
pub use lints::emit_attribute_lint;
100100

101101
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
55
use std::assert_matches::assert_matches;
66

7-
use rustc_abi::{FieldIdx, Size};
7+
use rustc_abi::{FieldIdx, HasDataLayout, Size};
88
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
9+
use rustc_middle::mir::interpret::{read_target_uint, write_target_uint};
910
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
1011
use rustc_middle::ty::layout::TyAndLayout;
1112
use rustc_middle::ty::{Ty, TyCtxt};
@@ -30,7 +31,7 @@ pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAll
3031
}
3132
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
3233
/// Generates a value of `TypeId` for `ty` in-place.
33-
pub(crate) fn write_type_id(
34+
fn write_type_id(
3435
&mut self,
3536
ty: Ty<'tcx>,
3637
dest: &PlaceTy<'tcx, M::Provenance>,
@@ -48,8 +49,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
4849
// Here we rely on `TypeId` being a newtype around an array of pointers, so we
4950
// first project to its only field and then the array elements.
5051
let alloc_id = tcx.reserve_and_set_type_id_alloc(ty);
51-
let first = self.project_field(dest, FieldIdx::ZERO)?;
52-
let mut elem_iter = self.project_array_fields(&first)?;
52+
let arr = self.project_field(dest, FieldIdx::ZERO)?;
53+
let mut elem_iter = self.project_array_fields(&arr)?;
5354
while let Some((_, elem)) = elem_iter.next(self)? {
5455
// Decorate this part of the hash with provenance; leave the integer part unchanged.
5556
let hash_fragment = self.read_scalar(&elem)?.to_target_usize(&tcx)?;
@@ -61,6 +62,52 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
6162
interp_ok(())
6263
}
6364

65+
/// Read a value of type `TypeId`, returning the type it represents.
66+
pub(crate) fn read_type_id(
67+
&self,
68+
op: &OpTy<'tcx, M::Provenance>,
69+
) -> InterpResult<'tcx, Ty<'tcx>> {
70+
// `TypeId` is a newtype around an array of pointers. All pointers must have the same
71+
// provenance, and that provenance represents the type.
72+
let ptr_size = self.pointer_size().bytes_usize();
73+
let arr = self.project_field(op, FieldIdx::ZERO)?;
74+
75+
let mut ty_and_hash = None;
76+
let mut elem_iter = self.project_array_fields(&arr)?;
77+
while let Some((idx, elem)) = elem_iter.next(self)? {
78+
let elem = self.read_pointer(&elem)?;
79+
let (elem_ty, elem_hash) = self.get_ptr_type_id(elem)?;
80+
// If this is the first element, remember the type and its hash.
81+
// If this is not the first element, ensure it is consistent with the previous ones.
82+
let full_hash = match ty_and_hash {
83+
None => {
84+
let hash = self.tcx.type_id_hash(elem_ty).as_u128();
85+
let mut hash_bytes = [0u8; 16];
86+
write_target_uint(self.data_layout().endian, &mut hash_bytes, hash).unwrap();
87+
ty_and_hash = Some((elem_ty, hash_bytes));
88+
hash_bytes
89+
}
90+
Some((ty, hash_bytes)) => {
91+
if ty != elem_ty {
92+
throw_ub_format!(
93+
"invalid `TypeId` value: not all bytes carry the same type id metadata"
94+
);
95+
}
96+
hash_bytes
97+
}
98+
};
99+
// Ensure the elem_hash matches the corresponding part of the full hash.
100+
let hash_frag = &full_hash[(idx as usize) * ptr_size..][..ptr_size];
101+
if read_target_uint(self.data_layout().endian, hash_frag).unwrap() != elem_hash.into() {
102+
throw_ub_format!(
103+
"invalid `TypeId` value: the hash does not match the type id metadata"
104+
);
105+
}
106+
}
107+
108+
interp_ok(ty_and_hash.unwrap().0)
109+
}
110+
64111
/// Returns `true` if emulation happened.
65112
/// Here we implement the intrinsics that are common to all Miri instances; individual machines can add their own
66113
/// intrinsic handling.
@@ -97,47 +144,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
97144
self.write_type_id(tp_ty, dest)?;
98145
}
99146
sym::type_id_eq => {
100-
// Both operands are `TypeId`, which is a newtype around an array of pointers.
101-
// Project until we have the array elements.
102-
let a_fields = self.project_field(&args[0], FieldIdx::ZERO)?;
103-
let b_fields = self.project_field(&args[1], FieldIdx::ZERO)?;
104-
105-
let mut a_fields = self.project_array_fields(&a_fields)?;
106-
let mut b_fields = self.project_array_fields(&b_fields)?;
107-
108-
let mut provenance_a = None;
109-
let mut provenance_b = None;
110-
let mut provenance_matches = true;
111-
112-
while let Some((i, a)) = a_fields.next(self)? {
113-
let (_, b) = b_fields.next(self)?.unwrap();
114-
115-
let a = self.deref_pointer(&a)?;
116-
let (a, offset_a) = self.get_ptr_type_id(a.ptr())?;
117-
118-
let b = self.deref_pointer(&b)?;
119-
let (b, offset_b) = self.get_ptr_type_id(b.ptr())?;
120-
121-
if *provenance_a.get_or_insert(a) != a {
122-
throw_ub_format!(
123-
"type_id_eq: the first TypeId argument is invalid, the provenance of chunk {i} does not match the first chunk's"
124-
)
125-
}
126-
if *provenance_b.get_or_insert(b) != b {
127-
throw_ub_format!(
128-
"type_id_eq: the second TypeId argument is invalid, the provenance of chunk {i} does not match the first chunk's"
129-
)
130-
}
131-
provenance_matches &= a == b;
132-
133-
if offset_a != offset_b && provenance_matches {
134-
throw_ub_format!(
135-
"type_id_eq: one of the TypeId arguments is invalid, chunk {i} of the hash does not match the type it represents"
136-
)
137-
}
138-
}
139-
140-
self.write_scalar(Scalar::from_bool(provenance_matches), dest)?;
147+
let a_ty = self.read_type_id(&args[0])?;
148+
let b_ty = self.read_type_id(&args[1])?;
149+
self.write_scalar(Scalar::from_bool(a_ty == b_ty), dest)?;
141150
}
142151
sym::variant_count => {
143152
let tp_ty = instance.args.type_at(0);

compiler/rustc_const_eval/src/interpret/memory.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -997,12 +997,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
997997
pub fn get_ptr_type_id(
998998
&self,
999999
ptr: Pointer<Option<M::Provenance>>,
1000-
) -> InterpResult<'tcx, (Ty<'tcx>, Size)> {
1000+
) -> InterpResult<'tcx, (Ty<'tcx>, u64)> {
10011001
let (alloc_id, offset, _meta) = self.ptr_get_alloc_id(ptr, 0)?;
10021002
let GlobalAlloc::TypeId { ty } = self.tcx.global_alloc(alloc_id) else {
1003-
throw_ub_format!("type_id_eq: `TypeId` provenance is not a type id")
1003+
throw_ub_format!("invalid `TypeId` value: not all bytes carry type id metadata")
10041004
};
1005-
interp_ok((ty, offset))
1005+
interp_ok((ty, offset.bytes()))
10061006
}
10071007

10081008
pub fn get_ptr_fn(

compiler/rustc_const_eval/src/interpret/stack.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
1212
use rustc_middle::{bug, mir};
1313
use rustc_mir_dataflow::impls::always_storage_live_locals;
1414
use rustc_span::Span;
15+
use tracing::field::Empty;
1516
use tracing::{info_span, instrument, trace};
1617

1718
use super::{
@@ -396,7 +397,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
396397
// Finish things up.
397398
M::after_stack_push(self)?;
398399
self.frame_mut().loc = Left(mir::Location::START);
399-
let span = info_span!("frame", "{}", instance);
400+
// `tracing_separate_thread` is used to instruct the chrome_tracing [tracing::Layer] in Miri
401+
// to put the "frame" span on a separate trace thread/line than other spans, to make the
402+
// visualization in https://ui.perfetto.dev easier to interpret. It is set to a value of
403+
// [tracing::field::Empty] so that other tracing layers (e.g. the logger) will ignore it.
404+
let span = info_span!("frame", tracing_separate_thread = Empty, "{}", instance);
400405
self.frame_mut().tracing_span.enter(span);
401406

402407
interp_ok(())

compiler/rustc_expand/src/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1062,7 +1062,7 @@ pub trait ResolverExpand {
10621062
fn next_node_id(&mut self) -> NodeId;
10631063
fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId;
10641064

1065-
fn resolve_dollar_crates(&mut self);
1065+
fn resolve_dollar_crates(&self);
10661066
fn visit_ast_fragment_with_placeholders(
10671067
&mut self,
10681068
expn_id: LocalExpnId,

0 commit comments

Comments
 (0)