Skip to content

Commit a30f915

Browse files
committed
Auto merge of rust-lang#135896 - matthiaskrgr:rollup-g6rv7za, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - rust-lang#132983 (Edit dangling pointers ) - rust-lang#135409 (Fix ICE-133117: multiple never-pattern arm doesn't have false_edge_start_block) - rust-lang#135557 (Point at invalid utf-8 span on user's source code) - rust-lang#135596 (Properly note when query stack is being cut off) - rust-lang#135794 (Detect missing fields with default values and suggest `..`) - rust-lang#135814 (ci: use ghcr buildkit image) - rust-lang#135826 (Misc. `rustc_resolve` cleanups) - rust-lang#135837 (Remove test panic from File::open) - rust-lang#135856 (Library: Finalize dyn compatibility renaming) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 649b995 + 3962bfa commit a30f915

File tree

55 files changed

+1079
-682
lines changed

Some content is hidden

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

55 files changed

+1079
-682
lines changed

compiler/rustc_builtin_macros/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#![feature(proc_macro_internals)]
1717
#![feature(proc_macro_quote)]
1818
#![feature(rustdoc_internals)]
19+
#![feature(string_from_utf8_lossy_owned)]
1920
#![feature(try_blocks)]
2021
#![warn(unreachable_pub)]
2122
// tidy-alphabetical-end

compiler/rustc_builtin_macros/src/source_util.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_expand::base::{
1313
use rustc_expand::module::DirOwnership;
1414
use rustc_lint_defs::BuiltinLintDiag;
1515
use rustc_parse::parser::{ForceCollect, Parser};
16-
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal};
16+
use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error};
1717
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
1818
use rustc_span::source_map::SourceMap;
1919
use rustc_span::{Pos, Span, Symbol};
@@ -209,9 +209,10 @@ pub(crate) fn expand_include_str(
209209
let interned_src = Symbol::intern(src);
210210
MacEager::expr(cx.expr_str(cx.with_def_site_ctxt(bsp), interned_src))
211211
}
212-
Err(_) => {
213-
let guar = cx.dcx().span_err(sp, format!("`{path}` wasn't a utf-8 file"));
214-
DummyResult::any(sp, guar)
212+
Err(utf8err) => {
213+
let mut err = cx.dcx().struct_span_err(sp, format!("`{path}` wasn't a utf-8 file"));
214+
utf8_error(cx.source_map(), path.as_str(), None, &mut err, utf8err, &bytes[..]);
215+
DummyResult::any(sp, err.emit())
215216
}
216217
},
217218
Err(dummy) => dummy,
@@ -273,7 +274,7 @@ fn load_binary_file(
273274
.and_then(|path| path.into_os_string().into_string().ok());
274275

275276
if let Some(new_path) = new_path {
276-
err.span_suggestion(
277+
err.span_suggestion_verbose(
277278
path_span,
278279
"there is a file with the same name in a different directory",
279280
format!("\"{}\"", new_path.replace('\\', "/").escape_debug()),

compiler/rustc_driver_impl/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1528,9 +1528,9 @@ fn report_ice(
15281528
// If backtraces are enabled, also print the query stack
15291529
let backtrace = env::var_os("RUST_BACKTRACE").is_some_and(|x| &x != "0");
15301530

1531-
let num_frames = if backtrace { None } else { Some(2) };
1531+
let limit_frames = if backtrace { None } else { Some(2) };
15321532

1533-
interface::try_print_query_stack(dcx, num_frames, file);
1533+
interface::try_print_query_stack(dcx, limit_frames, file);
15341534

15351535
// We don't trust this callback not to panic itself, so run it at the end after we're sure we've
15361536
// printed all the relevant info.

compiler/rustc_hir_typeck/src/expr.rs

+30
Original file line numberDiff line numberDiff line change
@@ -2349,6 +2349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23492349
self.report_missing_fields(
23502350
adt_ty,
23512351
path_span,
2352+
expr.span,
23522353
remaining_fields,
23532354
variant,
23542355
hir_fields,
@@ -2386,6 +2387,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23862387
&self,
23872388
adt_ty: Ty<'tcx>,
23882389
span: Span,
2390+
full_span: Span,
23892391
remaining_fields: UnordMap<Ident, (FieldIdx, &ty::FieldDef)>,
23902392
variant: &'tcx ty::VariantDef,
23912393
hir_fields: &'tcx [hir::ExprField<'tcx>],
@@ -2425,6 +2427,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24252427
);
24262428
err.span_label(span, format!("missing {remaining_fields_names}{truncated_fields_error}"));
24272429

2430+
if remaining_fields.items().all(|(_, (_, field))| field.value.is_some())
2431+
&& self.tcx.sess.is_nightly_build()
2432+
{
2433+
let msg = format!(
2434+
"all remaining fields have default values, {you_can} use those values with `..`",
2435+
you_can = if self.tcx.features().default_field_values() {
2436+
"you can"
2437+
} else {
2438+
"if you added `#![feature(default_field_values)]` to your crate you could"
2439+
},
2440+
);
2441+
if let Some(hir_field) = hir_fields.last() {
2442+
err.span_suggestion_verbose(
2443+
hir_field.span.shrink_to_hi(),
2444+
msg,
2445+
", ..".to_string(),
2446+
Applicability::MachineApplicable,
2447+
);
2448+
} else if hir_fields.is_empty() {
2449+
err.span_suggestion_verbose(
2450+
span.shrink_to_hi().with_hi(full_span.hi()),
2451+
msg,
2452+
" { .. }".to_string(),
2453+
Applicability::MachineApplicable,
2454+
);
2455+
}
2456+
}
2457+
24282458
if let Some(hir_field) = hir_fields.last() {
24292459
self.suggest_fru_from_range_and_emit(hir_field, variant, args, err);
24302460
} else {

compiler/rustc_interface/src/interface.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -533,31 +533,36 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
533533

534534
pub fn try_print_query_stack(
535535
dcx: DiagCtxtHandle<'_>,
536-
num_frames: Option<usize>,
536+
limit_frames: Option<usize>,
537537
file: Option<std::fs::File>,
538538
) {
539539
eprintln!("query stack during panic:");
540540

541541
// Be careful relying on global state here: this code is called from
542542
// a panic hook, which means that the global `DiagCtxt` may be in a weird
543543
// state if it was responsible for triggering the panic.
544-
let i = ty::tls::with_context_opt(|icx| {
544+
let all_frames = ty::tls::with_context_opt(|icx| {
545545
if let Some(icx) = icx {
546546
ty::print::with_no_queries!(print_query_stack(
547547
QueryCtxt::new(icx.tcx),
548548
icx.query,
549549
dcx,
550-
num_frames,
550+
limit_frames,
551551
file,
552552
))
553553
} else {
554554
0
555555
}
556556
});
557557

558-
if num_frames == None || num_frames >= Some(i) {
559-
eprintln!("end of query stack");
558+
if let Some(limit_frames) = limit_frames
559+
&& all_frames > limit_frames
560+
{
561+
eprintln!(
562+
"... and {} other queries... use `env RUST_BACKTRACE=1` to see the full query stack",
563+
all_frames - limit_frames
564+
);
560565
} else {
561-
eprintln!("we're just showing a limited slice of the query stack");
566+
eprintln!("end of query stack");
562567
}
563568
}

compiler/rustc_lint/messages.ftl

+3-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,9 @@ lint_dangling_pointers_from_temporaries = a dangling pointer will be produced be
209209
.label_ptr = this pointer will immediately be invalid
210210
.label_temporary = this `{$ty}` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
211211
.note = pointers do not have a lifetime; when calling `{$callee}` the `{$ty}` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
212-
.help = for more information, see <https://doc.rust-lang.org/reference/destructors.html>
212+
.help_bind = you must make sure that the variable you bind the `{$ty}` to lives at least as long as the pointer returned by the call to `{$callee}`
213+
.help_returned = in particular, if this pointer is returned from the current function, binding the `{$ty}` inside the function will not suffice
214+
.help_visit = for more information, see <https://doc.rust-lang.org/reference/destructors.html>
213215
214216
lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance
215217
.note = a `use rustc_data_structures::fx::{$preferred}` may be necessary

compiler/rustc_lint/src/lints.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,9 @@ pub(crate) struct IgnoredUnlessCrateSpecified<'a> {
11391139
#[derive(LintDiagnostic)]
11401140
#[diag(lint_dangling_pointers_from_temporaries)]
11411141
#[note]
1142-
#[help]
1142+
#[help(lint_help_bind)]
1143+
#[help(lint_help_returned)]
1144+
#[help(lint_help_visit)]
11431145
// FIXME: put #[primary_span] on `ptr_span` once it does not cause conflicts
11441146
pub(crate) struct DanglingPointersFromTemporaries<'tcx> {
11451147
pub callee: Symbol,

compiler/rustc_mir_build/src/builder/matches/mod.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1986,6 +1986,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19861986
return;
19871987
}
19881988

1989+
let false_edge_start_block = candidate.subcandidates[0].false_edge_start_block;
19891990
candidate.subcandidates.retain_mut(|candidate| {
19901991
if candidate.extra_data.is_never {
19911992
candidate.visit_leaves(|subcandidate| {
@@ -2000,8 +2001,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
20002001
}
20012002
});
20022003
if candidate.subcandidates.is_empty() {
2003-
// If `candidate` has become a leaf candidate, ensure it has a `pre_binding_block`.
2004-
candidate.pre_binding_block = Some(self.cfg.start_new_block());
2004+
// If `candidate` has become a leaf candidate, ensure it has a `pre_binding_block` and `otherwise_block`.
2005+
let next_block = self.cfg.start_new_block();
2006+
candidate.pre_binding_block = Some(next_block);
2007+
candidate.otherwise_block = Some(next_block);
2008+
// In addition, if `candidate` doesn't have `false_edge_start_block`, it should be assigned here.
2009+
if candidate.false_edge_start_block.is_none() {
2010+
candidate.false_edge_start_block = false_edge_start_block;
2011+
}
20052012
}
20062013
}
20072014

compiler/rustc_parse/src/lib.rs

+63-4
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,21 @@
1111
#![feature(if_let_guard)]
1212
#![feature(iter_intersperse)]
1313
#![feature(let_chains)]
14+
#![feature(string_from_utf8_lossy_owned)]
1415
#![warn(unreachable_pub)]
1516
// tidy-alphabetical-end
1617

17-
use std::path::Path;
18+
use std::path::{Path, PathBuf};
19+
use std::str::Utf8Error;
1820

1921
use rustc_ast as ast;
2022
use rustc_ast::tokenstream::TokenStream;
2123
use rustc_ast::{AttrItem, Attribute, MetaItemInner, token};
2224
use rustc_ast_pretty::pprust;
2325
use rustc_data_structures::sync::Lrc;
24-
use rustc_errors::{Diag, FatalError, PResult};
26+
use rustc_errors::{Diag, EmissionGuarantee, FatalError, PResult, pluralize};
2527
use rustc_session::parse::ParseSess;
28+
use rustc_span::source_map::SourceMap;
2629
use rustc_span::{FileName, SourceFile, Span};
2730
pub use unicode_normalization::UNICODE_VERSION as UNICODE_NORMALIZATION_VERSION;
2831

@@ -73,9 +76,22 @@ pub fn new_parser_from_file<'a>(
7376
path: &Path,
7477
sp: Option<Span>,
7578
) -> Result<Parser<'a>, Vec<Diag<'a>>> {
76-
let source_file = psess.source_map().load_file(path).unwrap_or_else(|e| {
77-
let msg = format!("couldn't read {}: {}", path.display(), e);
79+
let sm = psess.source_map();
80+
let source_file = sm.load_file(path).unwrap_or_else(|e| {
81+
let msg = format!("couldn't read `{}`: {}", path.display(), e);
7882
let mut err = psess.dcx().struct_fatal(msg);
83+
if let Ok(contents) = std::fs::read(path)
84+
&& let Err(utf8err) = String::from_utf8(contents.clone())
85+
{
86+
utf8_error(
87+
sm,
88+
&path.display().to_string(),
89+
sp,
90+
&mut err,
91+
utf8err.utf8_error(),
92+
&contents,
93+
);
94+
}
7995
if let Some(sp) = sp {
8096
err.span(sp);
8197
}
@@ -84,6 +100,49 @@ pub fn new_parser_from_file<'a>(
84100
new_parser_from_source_file(psess, source_file)
85101
}
86102

103+
pub fn utf8_error<E: EmissionGuarantee>(
104+
sm: &SourceMap,
105+
path: &str,
106+
sp: Option<Span>,
107+
err: &mut Diag<'_, E>,
108+
utf8err: Utf8Error,
109+
contents: &[u8],
110+
) {
111+
// The file exists, but it wasn't valid UTF-8.
112+
let start = utf8err.valid_up_to();
113+
let note = format!("invalid utf-8 at byte `{start}`");
114+
let msg = if let Some(len) = utf8err.error_len() {
115+
format!(
116+
"byte{s} `{bytes}` {are} not valid utf-8",
117+
bytes = if len == 1 {
118+
format!("{:?}", contents[start])
119+
} else {
120+
format!("{:?}", &contents[start..start + len])
121+
},
122+
s = pluralize!(len),
123+
are = if len == 1 { "is" } else { "are" },
124+
)
125+
} else {
126+
note.clone()
127+
};
128+
let contents = String::from_utf8_lossy(contents).to_string();
129+
let source = sm.new_source_file(PathBuf::from(path).into(), contents);
130+
let span = Span::with_root_ctxt(
131+
source.normalized_byte_pos(start as u32),
132+
source.normalized_byte_pos(start as u32),
133+
);
134+
if span.is_dummy() {
135+
err.note(note);
136+
} else {
137+
if sp.is_some() {
138+
err.span_note(span, msg);
139+
} else {
140+
err.span(span);
141+
err.span_label(span, msg);
142+
}
143+
}
144+
}
145+
87146
/// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing
88147
/// the initial token stream.
89148
fn new_parser_from_source_file(

compiler/rustc_query_system/src/query/job.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ pub fn print_query_stack<Qcx: QueryContext>(
567567
qcx: Qcx,
568568
mut current_query: Option<QueryJobId>,
569569
dcx: DiagCtxtHandle<'_>,
570-
num_frames: Option<usize>,
570+
limit_frames: Option<usize>,
571571
mut file: Option<std::fs::File>,
572572
) -> usize {
573573
// Be careful relying on global state here: this code is called from
@@ -584,7 +584,7 @@ pub fn print_query_stack<Qcx: QueryContext>(
584584
let Some(query_info) = query_map.get(&query) else {
585585
break;
586586
};
587-
if Some(count_printed) < num_frames || num_frames.is_none() {
587+
if Some(count_printed) < limit_frames || limit_frames.is_none() {
588588
// Only print to stderr as many stack frames as `num_frames` when present.
589589
// FIXME: needs translation
590590
#[allow(rustc::diagnostic_outside_of_impl)]
@@ -615,5 +615,5 @@ pub fn print_query_stack<Qcx: QueryContext>(
615615
if let Some(ref mut file) = file {
616616
let _ = writeln!(file, "end of query stack");
617617
}
618-
count_printed
618+
count_total
619619
}

compiler/rustc_resolve/src/build_reduced_graph.rs

+26-28
Original file line numberDiff line numberDiff line change
@@ -645,10 +645,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
645645
let self_spans = items
646646
.iter()
647647
.filter_map(|(use_tree, _)| {
648-
if let ast::UseTreeKind::Simple(..) = use_tree.kind {
649-
if use_tree.ident().name == kw::SelfLower {
650-
return Some(use_tree.span);
651-
}
648+
if let ast::UseTreeKind::Simple(..) = use_tree.kind
649+
&& use_tree.ident().name == kw::SelfLower
650+
{
651+
return Some(use_tree.span);
652652
}
653653

654654
None
@@ -947,19 +947,19 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
947947
let imported_binding = self.r.import(binding, import);
948948
if parent == self.r.graph_root {
949949
let ident = ident.normalize_to_macros_2_0();
950-
if let Some(entry) = self.r.extern_prelude.get(&ident) {
951-
if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() {
952-
self.r.dcx().emit_err(
953-
errors::MacroExpandedExternCrateCannotShadowExternArguments {
954-
span: item.span,
955-
},
956-
);
957-
// `return` is intended to discard this binding because it's an
958-
// unregistered ambiguity error which would result in a panic
959-
// caused by inconsistency `path_res`
960-
// more details: https://github.com/rust-lang/rust/pull/111761
961-
return;
962-
}
950+
if let Some(entry) = self.r.extern_prelude.get(&ident)
951+
&& expansion != LocalExpnId::ROOT
952+
&& orig_name.is_some()
953+
&& !entry.is_import()
954+
{
955+
self.r.dcx().emit_err(
956+
errors::MacroExpandedExternCrateCannotShadowExternArguments { span: item.span },
957+
);
958+
// `return` is intended to discard this binding because it's an
959+
// unregistered ambiguity error which would result in a panic
960+
// caused by inconsistency `path_res`
961+
// more details: https://github.com/rust-lang/rust/pull/111761
962+
return;
963963
}
964964
let entry = self
965965
.r
@@ -1040,10 +1040,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
10401040
span: item.span,
10411041
});
10421042
}
1043-
if let ItemKind::ExternCrate(Some(orig_name)) = item.kind {
1044-
if orig_name == kw::SelfLower {
1045-
self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span });
1046-
}
1043+
if let ItemKind::ExternCrate(Some(orig_name)) = item.kind
1044+
&& orig_name == kw::SelfLower
1045+
{
1046+
self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span });
10471047
}
10481048
let ill_formed = |span| {
10491049
self.r.dcx().emit_err(errors::BadMacroImport { span });
@@ -1179,14 +1179,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
11791179
return Some((MacroKind::Bang, item.ident, item.span));
11801180
} else if ast::attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
11811181
return Some((MacroKind::Attr, item.ident, item.span));
1182-
} else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive) {
1183-
if let Some(meta_item_inner) =
1182+
} else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive)
1183+
&& let Some(meta_item_inner) =
11841184
attr.meta_item_list().and_then(|list| list.get(0).cloned())
1185-
{
1186-
if let Some(ident) = meta_item_inner.ident() {
1187-
return Some((MacroKind::Derive, ident, ident.span));
1188-
}
1189-
}
1185+
&& let Some(ident) = meta_item_inner.ident()
1186+
{
1187+
return Some((MacroKind::Derive, ident, ident.span));
11901188
}
11911189
None
11921190
}

0 commit comments

Comments
 (0)