Skip to content

Commit 88de7b1

Browse files
committed
Auto merge of rust-lang#122260 - matthiaskrgr:rollup-ik8lga9, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - rust-lang#121561 (Detect typos for compiletest test directives) - rust-lang#121567 (Avoid some interning in bootstrap) - rust-lang#121685 (Fixing shellcheck comments on lvi test script) - rust-lang#121833 (Suggest correct path in include_bytes!) - rust-lang#121860 (Add a tidy check that checks whether the fluent slugs only appear once) - rust-lang#121907 (skip sanity check for non-host targets in `check` builds) - rust-lang#122029 (When displaying multispans, ignore empty lines adjacent to `...`) - rust-lang#122221 (match lowering: define a convenient struct) - rust-lang#122244 (fix: LocalWaker memory leak and some stability attributes) - rust-lang#122251 (Add test to check unused_lifetimes don't duplicate "parameter is never used" error) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 2d24fe5 + 9814eda commit 88de7b1

File tree

59 files changed

+1067
-391
lines changed

Some content is hidden

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

59 files changed

+1067
-391
lines changed

compiler/rustc_builtin_macros/src/source_util.rs

+120-30
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@ use rustc_ast::ptr::P;
33
use rustc_ast::token;
44
use rustc_ast::tokenstream::TokenStream;
55
use rustc_ast_pretty::pprust;
6+
use rustc_data_structures::sync::Lrc;
67
use rustc_expand::base::{
7-
check_zero_tts, get_single_str_from_tts, parse_expr, resolve_path, DummyResult, ExtCtxt,
8-
MacEager, MacResult,
8+
check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
9+
resolve_path, DummyResult, ExtCtxt, MacEager, MacResult,
910
};
1011
use rustc_expand::module::DirOwnership;
1112
use rustc_parse::new_parser_from_file;
1213
use rustc_parse::parser::{ForceCollect, Parser};
1314
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
15+
use rustc_span::source_map::SourceMap;
1416
use rustc_span::symbol::Symbol;
1517
use rustc_span::{Pos, Span};
16-
1718
use smallvec::SmallVec;
19+
use std::path::{Path, PathBuf};
1820
use std::rc::Rc;
1921

2022
// These macros all relate to the file system; they either return
@@ -180,32 +182,22 @@ pub fn expand_include_str(
180182
tts: TokenStream,
181183
) -> Box<dyn MacResult + 'static> {
182184
let sp = cx.with_def_site_ctxt(sp);
183-
let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
184-
Ok(file) => file,
185+
let (path, path_span) = match get_single_str_spanned_from_tts(cx, sp, tts, "include_str!") {
186+
Ok(res) => res,
185187
Err(guar) => return DummyResult::any(sp, guar),
186188
};
187-
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
188-
Ok(f) => f,
189-
Err(err) => {
190-
let guar = err.emit();
191-
return DummyResult::any(sp, guar);
192-
}
193-
};
194-
match cx.source_map().load_binary_file(&file) {
189+
match load_binary_file(cx, path.as_str().as_ref(), sp, path_span) {
195190
Ok(bytes) => match std::str::from_utf8(&bytes) {
196191
Ok(src) => {
197192
let interned_src = Symbol::intern(src);
198193
MacEager::expr(cx.expr_str(sp, interned_src))
199194
}
200195
Err(_) => {
201-
let guar = cx.dcx().span_err(sp, format!("{} wasn't a utf-8 file", file.display()));
196+
let guar = cx.dcx().span_err(sp, format!("`{path}` wasn't a utf-8 file"));
202197
DummyResult::any(sp, guar)
203198
}
204199
},
205-
Err(e) => {
206-
let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e));
207-
DummyResult::any(sp, guar)
208-
}
200+
Err(dummy) => dummy,
209201
}
210202
}
211203

@@ -215,25 +207,123 @@ pub fn expand_include_bytes(
215207
tts: TokenStream,
216208
) -> Box<dyn MacResult + 'static> {
217209
let sp = cx.with_def_site_ctxt(sp);
218-
let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
219-
Ok(file) => file,
210+
let (path, path_span) = match get_single_str_spanned_from_tts(cx, sp, tts, "include_bytes!") {
211+
Ok(res) => res,
220212
Err(guar) => return DummyResult::any(sp, guar),
221213
};
222-
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
223-
Ok(f) => f,
214+
match load_binary_file(cx, path.as_str().as_ref(), sp, path_span) {
215+
Ok(bytes) => {
216+
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes));
217+
MacEager::expr(expr)
218+
}
219+
Err(dummy) => dummy,
220+
}
221+
}
222+
223+
fn load_binary_file(
224+
cx: &mut ExtCtxt<'_>,
225+
original_path: &Path,
226+
macro_span: Span,
227+
path_span: Span,
228+
) -> Result<Lrc<[u8]>, Box<dyn MacResult>> {
229+
let resolved_path = match resolve_path(&cx.sess, original_path, macro_span) {
230+
Ok(path) => path,
224231
Err(err) => {
225232
let guar = err.emit();
226-
return DummyResult::any(sp, guar);
233+
return Err(DummyResult::any(macro_span, guar));
227234
}
228235
};
229-
match cx.source_map().load_binary_file(&file) {
230-
Ok(bytes) => {
231-
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes));
232-
MacEager::expr(expr)
236+
match cx.source_map().load_binary_file(&resolved_path) {
237+
Ok(data) => Ok(data),
238+
Err(io_err) => {
239+
let mut err = cx.dcx().struct_span_err(
240+
macro_span,
241+
format!("couldn't read `{}`: {io_err}", resolved_path.display()),
242+
);
243+
244+
if original_path.is_relative() {
245+
let source_map = cx.sess.source_map();
246+
let new_path = source_map
247+
.span_to_filename(macro_span.source_callsite())
248+
.into_local_path()
249+
.and_then(|src| find_path_suggestion(source_map, src.parent()?, original_path))
250+
.and_then(|path| path.into_os_string().into_string().ok());
251+
252+
if let Some(new_path) = new_path {
253+
err.span_suggestion(
254+
path_span,
255+
"there is a file with the same name in a different directory",
256+
format!("\"{}\"", new_path.escape_debug()),
257+
rustc_lint_defs::Applicability::MachineApplicable,
258+
);
259+
}
260+
}
261+
let guar = err.emit();
262+
Err(DummyResult::any(macro_span, guar))
233263
}
234-
Err(e) => {
235-
let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e));
236-
DummyResult::any(sp, guar)
264+
}
265+
}
266+
267+
fn find_path_suggestion(
268+
source_map: &SourceMap,
269+
base_dir: &Path,
270+
wanted_path: &Path,
271+
) -> Option<PathBuf> {
272+
// Fix paths that assume they're relative to cargo manifest dir
273+
let mut base_c = base_dir.components();
274+
let mut wanted_c = wanted_path.components();
275+
let mut without_base = None;
276+
while let Some(wanted_next) = wanted_c.next() {
277+
if wanted_c.as_path().file_name().is_none() {
278+
break;
279+
}
280+
// base_dir may be absolute
281+
while let Some(base_next) = base_c.next() {
282+
if base_next == wanted_next {
283+
without_base = Some(wanted_c.as_path());
284+
break;
285+
}
286+
}
287+
}
288+
let root_absolute = without_base.into_iter().map(PathBuf::from);
289+
290+
let base_dir_components = base_dir.components().count();
291+
// Avoid going all the way to the root dir
292+
let max_parent_components = if base_dir.is_relative() {
293+
base_dir_components + 1
294+
} else {
295+
base_dir_components.saturating_sub(1)
296+
};
297+
298+
// Try with additional leading ../
299+
let mut prefix = PathBuf::new();
300+
let add = std::iter::from_fn(|| {
301+
prefix.push("..");
302+
Some(prefix.join(wanted_path))
303+
})
304+
.take(max_parent_components.min(3));
305+
306+
// Try without leading directories
307+
let mut trimmed_path = wanted_path;
308+
let remove = std::iter::from_fn(|| {
309+
let mut components = trimmed_path.components();
310+
let removed = components.next()?;
311+
trimmed_path = components.as_path();
312+
let _ = trimmed_path.file_name()?; // ensure there is a file name left
313+
Some([
314+
Some(trimmed_path.to_path_buf()),
315+
(removed != std::path::Component::ParentDir)
316+
.then(|| Path::new("..").join(trimmed_path)),
317+
])
318+
})
319+
.flatten()
320+
.flatten()
321+
.take(4);
322+
323+
for new_path in root_absolute.chain(add).chain(remove) {
324+
if source_map.file_exists(&base_dir.join(&new_path)) {
325+
return Some(new_path);
237326
}
238327
}
328+
None
239329
}

compiler/rustc_const_eval/messages.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,6 @@ const_eval_intern_kind = {$kind ->
146146
*[other] {""}
147147
}
148148
149-
const_eval_invalid_align =
150-
align has to be a power of 2
151-
152149
const_eval_invalid_align_details =
153150
invalid align passed to `{$name}`: {$align} is {$err_kind ->
154151
[not_power_of_two] not a power of 2

compiler/rustc_errors/src/emitter.rs

+48-1
Original file line numberDiff line numberDiff line change
@@ -1638,6 +1638,27 @@ impl HumanEmitter {
16381638
*style,
16391639
);
16401640
}
1641+
if let Some(line) = annotated_file.lines.get(line_idx) {
1642+
for ann in &line.annotations {
1643+
if let AnnotationType::MultilineStart(pos) = ann.annotation_type
1644+
{
1645+
// In the case where we have elided the entire start of the
1646+
// multispan because those lines were empty, we still need
1647+
// to draw the `|`s across the `...`.
1648+
draw_multiline_line(
1649+
&mut buffer,
1650+
last_buffer_line_num,
1651+
width_offset,
1652+
pos,
1653+
if ann.is_primary {
1654+
Style::UnderlinePrimary
1655+
} else {
1656+
Style::UnderlineSecondary
1657+
},
1658+
);
1659+
}
1660+
}
1661+
}
16411662
} else if line_idx_delta == 2 {
16421663
let unannotated_line = annotated_file
16431664
.file
@@ -1665,6 +1686,24 @@ impl HumanEmitter {
16651686
*style,
16661687
);
16671688
}
1689+
if let Some(line) = annotated_file.lines.get(line_idx) {
1690+
for ann in &line.annotations {
1691+
if let AnnotationType::MultilineStart(pos) = ann.annotation_type
1692+
{
1693+
draw_multiline_line(
1694+
&mut buffer,
1695+
last_buffer_line_num,
1696+
width_offset,
1697+
pos,
1698+
if ann.is_primary {
1699+
Style::UnderlinePrimary
1700+
} else {
1701+
Style::UnderlineSecondary
1702+
},
1703+
);
1704+
}
1705+
}
1706+
}
16681707
}
16691708
}
16701709

@@ -2417,7 +2456,15 @@ impl FileWithAnnotatedLines {
24172456
// the beginning doesn't have an underline, but the current logic seems to be
24182457
// working correctly.
24192458
let middle = min(ann.line_start + 4, ann.line_end);
2420-
for line in ann.line_start + 1..middle {
2459+
// We'll show up to 4 lines past the beginning of the multispan start.
2460+
// We will *not* include the tail of lines that are only whitespace.
2461+
let until = (ann.line_start..middle)
2462+
.rev()
2463+
.filter_map(|line| file.get_line(line - 1).map(|s| (line + 1, s)))
2464+
.find(|(_, s)| !s.trim().is_empty())
2465+
.map(|(line, _)| line)
2466+
.unwrap_or(ann.line_start);
2467+
for line in ann.line_start + 1..until {
24212468
// Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`).
24222469
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
24232470
}

compiler/rustc_expand/src/base.rs

+26-15
Original file line numberDiff line numberDiff line change
@@ -1233,21 +1233,18 @@ pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PRe
12331233
// after macro expansion (that is, they are unhygienic).
12341234
if !path.is_absolute() {
12351235
let callsite = span.source_callsite();
1236-
let mut result = match sess.source_map().span_to_filename(callsite) {
1237-
FileName::Real(name) => name
1238-
.into_local_path()
1239-
.expect("attempting to resolve a file path in an external file"),
1240-
FileName::DocTest(path, _) => path,
1241-
other => {
1242-
return Err(sess.dcx().create_err(errors::ResolveRelativePath {
1243-
span,
1244-
path: sess.source_map().filename_for_diagnostics(&other).to_string(),
1245-
}));
1246-
}
1236+
let source_map = sess.source_map();
1237+
let Some(mut base_path) = source_map.span_to_filename(callsite).into_local_path() else {
1238+
return Err(sess.dcx().create_err(errors::ResolveRelativePath {
1239+
span,
1240+
path: source_map
1241+
.filename_for_diagnostics(&source_map.span_to_filename(callsite))
1242+
.to_string(),
1243+
}));
12471244
};
1248-
result.pop();
1249-
result.push(path);
1250-
Ok(result)
1245+
base_path.pop();
1246+
base_path.push(path);
1247+
Ok(base_path)
12511248
} else {
12521249
Ok(path)
12531250
}
@@ -1344,6 +1341,15 @@ pub fn get_single_str_from_tts(
13441341
tts: TokenStream,
13451342
name: &str,
13461343
) -> Result<Symbol, ErrorGuaranteed> {
1344+
get_single_str_spanned_from_tts(cx, span, tts, name).map(|(s, _)| s)
1345+
}
1346+
1347+
pub fn get_single_str_spanned_from_tts(
1348+
cx: &mut ExtCtxt<'_>,
1349+
span: Span,
1350+
tts: TokenStream,
1351+
name: &str,
1352+
) -> Result<(Symbol, Span), ErrorGuaranteed> {
13471353
let mut p = cx.new_parser_from_tts(tts);
13481354
if p.token == token::Eof {
13491355
let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name });
@@ -1355,7 +1361,12 @@ pub fn get_single_str_from_tts(
13551361
if p.token != token::Eof {
13561362
cx.dcx().emit_err(errors::OnlyOneArgument { span, name });
13571363
}
1358-
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
1364+
expr_to_spanned_string(cx, ret, "argument must be a string literal")
1365+
.map_err(|err| match err {
1366+
Ok((err, _)) => err.emit(),
1367+
Err(guar) => guar,
1368+
})
1369+
.map(|(symbol, _style, span)| (symbol, span))
13591370
}
13601371

13611372
/// Extracts comma-separated expressions from `tts`.

compiler/rustc_expand/src/tests.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,7 @@ error: foo
276276
|
277277
2 | fn foo() {
278278
| __________^
279-
3 | |
280-
4 | |
279+
... |
281280
5 | | }
282281
| |___^ test
283282

compiler/rustc_infer/messages.ftl

-8
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,6 @@ infer_more_targeted = {$has_param_name ->
181181
182182
infer_msl_introduces_static = introduces a `'static` lifetime requirement
183183
infer_msl_unmet_req = because this has an unmet lifetime requirement
184-
infer_need_type_info_in_coroutine =
185-
type inside {$coroutine_kind ->
186-
[async_block] `async` block
187-
[async_closure] `async` closure
188-
[async_fn] `async fn` body
189-
*[coroutine] coroutine
190-
} must be known in this context
191-
192184
193185
infer_nothing = {""}
194186

compiler/rustc_lint/messages.ftl

-2
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,6 @@ lint_suspicious_double_ref_clone =
562562
lint_suspicious_double_ref_deref =
563563
using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type
564564
565-
lint_trivial_untranslatable_diag = diagnostic with static strings only
566-
567565
lint_ty_qualified = usage of qualified `ty::{$ty}`
568566
.suggestion = try importing it and using it unqualified
569567

0 commit comments

Comments
 (0)