Skip to content
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

Rollup of 12 pull requests #122229

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
709ea74
Add Read Impl for &Stdin
Dajamante Jul 11, 2022
1ea6cd7
Add std::ffi::c_str modules
clarfonthey Aug 19, 2023
b921a34
Fix stable feature name and stabilization version of Read for &Stdin
dtolnay Feb 26, 2024
b18280f
Fill in Read::read_buf for &Stdin
dtolnay Feb 26, 2024
f27a22c
try_with_capacity for RawVec
kornelski Jan 30, 2024
78fb977
try_with_capacity for Vec, VecDeque, String
kornelski Jan 30, 2024
784e6a1
Move capacity_overflow function to make ui tests change less
kornelski Jan 31, 2024
c3954b3
Add a tidy check that checks whether the fluent slugs only appear once
mu001999 Mar 2, 2024
d88c7ff
Remove unused fluent messages
mu001999 Mar 2, 2024
0a00749
Implement MaybeUninit::fill{,_with,_from}
ajwock Feb 18, 2024
5c87ca2
Add some weird test cases to the non_local_definitions lint tests
Urgau Feb 29, 2024
20200f6
Remove useless smallvec dependency in rustc_lint::non_local_def
Urgau Feb 29, 2024
6c4eadd
Add early-return when checking if a path is local
Urgau Feb 29, 2024
98dbe9a
Use was_invoked_from_cargo method instead of hand-written one
Urgau Feb 29, 2024
1195518
Helper function for resolve_path
kornelski Mar 1, 2024
25ab1c7
Suggest correct path in include_bytes!
kornelski Mar 1, 2024
4663fbb
Eagerly translate HelpUseLatestEdition in parser diagnostics
jieyouxu Mar 7, 2024
bef1cd8
ci: add a runner for vanilla LLVM 18
cuviper Mar 8, 2024
446708b
Remove a workaround for a bug
bjorn3 Sep 19, 2021
87ab9e8
Some tweaks to the parallel query cycle handler
Zoxc Mar 8, 2024
564837e
Fix typo in `VisitorResult`
Jarcho Mar 9, 2024
286e813
Rollup merge of #99153 - Dajamante:issue/95622, r=dtolnay
jhpratt Mar 9, 2024
6eaab82
Rollup merge of #112136 - clarfonthey:ffi-c_str, r=cuviper
jhpratt Mar 9, 2024
05b67c6
Rollup merge of #120504 - kornelski:try_with_capacity, r=Amanieu
jhpratt Mar 9, 2024
3c6b895
Rollup merge of #121280 - ajwock:maybeuninit_fill, r=Amanieu
jhpratt Mar 9, 2024
32b2e63
Rollup merge of #121813 - Urgau:misc-non_local_defs-lint, r=cjgillot
jhpratt Mar 9, 2024
936c182
Rollup merge of #121833 - kornelski:parent_include, r=estebank
jhpratt Mar 9, 2024
9aff53d
Rollup merge of #121860 - mu001999:master, r=Nilstrieb
jhpratt Mar 9, 2024
d16fd38
Rollup merge of #122160 - jieyouxu:eager-translate-help-use-latest-ed…
jhpratt Mar 9, 2024
74f17ea
Rollup merge of #122178 - cuviper:ci-llvm-18, r=Kobzol
jhpratt Mar 9, 2024
437ba6a
Rollup merge of #122186 - bjorn3:remove_bug_workaround, r=petrochenkov
jhpratt Mar 9, 2024
6a582de
Rollup merge of #122215 - Zoxc:cycle-detect-names, r=oli-obk
jhpratt Mar 9, 2024
d5956a9
Rollup merge of #122223 - Jarcho:visit_fix, r=oli-obk
jhpratt Mar 9, 2024
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
150 changes: 120 additions & 30 deletions compiler/rustc_builtin_macros/src/source_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast_pretty::pprust;
use rustc_data_structures::sync::Lrc;
use rustc_expand::base::{
check_zero_tts, get_single_str_from_tts, parse_expr, resolve_path, DummyResult, ExtCtxt,
MacEager, MacResult,
check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
resolve_path, DummyResult, ExtCtxt, MacEager, MacResult,
};
use rustc_expand::module::DirOwnership;
use rustc_parse::new_parser_from_file;
use rustc_parse::parser::{ForceCollect, Parser};
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::Symbol;
use rustc_span::{Pos, Span};

use smallvec::SmallVec;
use std::path::{Path, PathBuf};
use std::rc::Rc;

// These macros all relate to the file system; they either return
Expand Down Expand Up @@ -180,32 +182,22 @@ pub fn expand_include_str(
tts: TokenStream,
) -> Box<dyn MacResult + 'static> {
let sp = cx.with_def_site_ctxt(sp);
let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
Ok(file) => file,
let (path, path_span) = match get_single_str_spanned_from_tts(cx, sp, tts, "include_str!") {
Ok(res) => res,
Err(guar) => return DummyResult::any(sp, guar),
};
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
Ok(f) => f,
Err(err) => {
let guar = err.emit();
return DummyResult::any(sp, guar);
}
};
match cx.source_map().load_binary_file(&file) {
match load_binary_file(cx, path.as_str().as_ref(), sp, path_span) {
Ok(bytes) => match std::str::from_utf8(&bytes) {
Ok(src) => {
let interned_src = Symbol::intern(src);
MacEager::expr(cx.expr_str(sp, interned_src))
}
Err(_) => {
let guar = cx.dcx().span_err(sp, format!("{} wasn't a utf-8 file", file.display()));
let guar = cx.dcx().span_err(sp, format!("`{path}` wasn't a utf-8 file"));
DummyResult::any(sp, guar)
}
},
Err(e) => {
let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e));
DummyResult::any(sp, guar)
}
Err(dummy) => dummy,
}
}

Expand All @@ -215,25 +207,123 @@ pub fn expand_include_bytes(
tts: TokenStream,
) -> Box<dyn MacResult + 'static> {
let sp = cx.with_def_site_ctxt(sp);
let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") {
Ok(file) => file,
let (path, path_span) = match get_single_str_spanned_from_tts(cx, sp, tts, "include_bytes!") {
Ok(res) => res,
Err(guar) => return DummyResult::any(sp, guar),
};
let file = match resolve_path(&cx.sess, file.as_str(), sp) {
Ok(f) => f,
match load_binary_file(cx, path.as_str().as_ref(), sp, path_span) {
Ok(bytes) => {
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes));
MacEager::expr(expr)
}
Err(dummy) => dummy,
}
}

fn load_binary_file(
cx: &mut ExtCtxt<'_>,
original_path: &Path,
macro_span: Span,
path_span: Span,
) -> Result<Lrc<[u8]>, Box<dyn MacResult>> {
let resolved_path = match resolve_path(&cx.sess, original_path, macro_span) {
Ok(path) => path,
Err(err) => {
let guar = err.emit();
return DummyResult::any(sp, guar);
return Err(DummyResult::any(macro_span, guar));
}
};
match cx.source_map().load_binary_file(&file) {
Ok(bytes) => {
let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes));
MacEager::expr(expr)
match cx.source_map().load_binary_file(&resolved_path) {
Ok(data) => Ok(data),
Err(io_err) => {
let mut err = cx.dcx().struct_span_err(
macro_span,
format!("couldn't read `{}`: {io_err}", resolved_path.display()),
);

if original_path.is_relative() {
let source_map = cx.sess.source_map();
let new_path = source_map
.span_to_filename(macro_span.source_callsite())
.into_local_path()
.and_then(|src| find_path_suggestion(source_map, src.parent()?, original_path))
.and_then(|path| path.into_os_string().into_string().ok());

if let Some(new_path) = new_path {
err.span_suggestion(
path_span,
"there is a file with the same name in a different directory",
format!("\"{}\"", new_path.escape_debug()),
rustc_lint_defs::Applicability::MachineApplicable,
);
}
}
let guar = err.emit();
Err(DummyResult::any(macro_span, guar))
}
Err(e) => {
let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e));
DummyResult::any(sp, guar)
}
}

fn find_path_suggestion(
source_map: &SourceMap,
base_dir: &Path,
wanted_path: &Path,
) -> Option<PathBuf> {
// Fix paths that assume they're relative to cargo manifest dir
let mut base_c = base_dir.components();
let mut wanted_c = wanted_path.components();
let mut without_base = None;
while let Some(wanted_next) = wanted_c.next() {
if wanted_c.as_path().file_name().is_none() {
break;
}
// base_dir may be absolute
while let Some(base_next) = base_c.next() {
if base_next == wanted_next {
without_base = Some(wanted_c.as_path());
break;
}
}
}
let root_absolute = without_base.into_iter().map(PathBuf::from);

let base_dir_components = base_dir.components().count();
// Avoid going all the way to the root dir
let max_parent_components = if base_dir.is_relative() {
base_dir_components + 1
} else {
base_dir_components.saturating_sub(1)
};

// Try with additional leading ../
let mut prefix = PathBuf::new();
let add = std::iter::from_fn(|| {
prefix.push("..");
Some(prefix.join(wanted_path))
})
.take(max_parent_components.min(3));

// Try without leading directories
let mut trimmed_path = wanted_path;
let remove = std::iter::from_fn(|| {
let mut components = trimmed_path.components();
let removed = components.next()?;
trimmed_path = components.as_path();
let _ = trimmed_path.file_name()?; // ensure there is a file name left
Some([
Some(trimmed_path.to_path_buf()),
(removed != std::path::Component::ParentDir)
.then(|| Path::new("..").join(trimmed_path)),
])
})
.flatten()
.flatten()
.take(4);

for new_path in root_absolute.chain(add).chain(remove) {
if source_map.file_exists(&base_dir.join(&new_path)) {
return Some(new_path);
}
}
None
}
41 changes: 26 additions & 15 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1233,21 +1233,18 @@ pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PRe
// after macro expansion (that is, they are unhygienic).
if !path.is_absolute() {
let callsite = span.source_callsite();
let mut result = match sess.source_map().span_to_filename(callsite) {
FileName::Real(name) => name
.into_local_path()
.expect("attempting to resolve a file path in an external file"),
FileName::DocTest(path, _) => path,
other => {
return Err(sess.dcx().create_err(errors::ResolveRelativePath {
span,
path: sess.source_map().filename_for_diagnostics(&other).to_string(),
}));
}
let source_map = sess.source_map();
let Some(mut base_path) = source_map.span_to_filename(callsite).into_local_path() else {
return Err(sess.dcx().create_err(errors::ResolveRelativePath {
span,
path: source_map
.filename_for_diagnostics(&source_map.span_to_filename(callsite))
.to_string(),
}));
};
result.pop();
result.push(path);
Ok(result)
base_path.pop();
base_path.push(path);
Ok(base_path)
} else {
Ok(path)
}
Expand Down Expand Up @@ -1344,6 +1341,15 @@ pub fn get_single_str_from_tts(
tts: TokenStream,
name: &str,
) -> Result<Symbol, ErrorGuaranteed> {
get_single_str_spanned_from_tts(cx, span, tts, name).map(|(s, _)| s)
}

pub fn get_single_str_spanned_from_tts(
cx: &mut ExtCtxt<'_>,
span: Span,
tts: TokenStream,
name: &str,
) -> Result<(Symbol, Span), ErrorGuaranteed> {
let mut p = cx.new_parser_from_tts(tts);
if p.token == token::Eof {
let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name });
Expand All @@ -1355,7 +1361,12 @@ pub fn get_single_str_from_tts(
if p.token != token::Eof {
cx.dcx().emit_err(errors::OnlyOneArgument { span, name });
}
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
expr_to_spanned_string(cx, ret, "argument must be a string literal")
.map_err(|err| match err {
Ok((err, _)) => err.emit(),
Err(guar) => guar,
})
.map(|(symbol, _style, span)| (symbol, span))
}

/// Extracts comma-separated expressions from `tts`.
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,17 @@ impl FileName {
src.hash(&mut hasher);
FileName::InlineAsm(hasher.finish())
}

/// Returns the path suitable for reading from the file system on the local host,
/// if this information exists.
/// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that.
pub fn into_local_path(self) -> Option<PathBuf> {
match self {
FileName::Real(path) => path.into_local_path(),
FileName::DocTest(path, _) => Some(path),
_ => None,
}
}
}

/// Represents a span.
Expand Down
12 changes: 12 additions & 0 deletions tests/ui/include-macros/parent_dir.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//@ normalize-stderr-test: "`: .*\(os error" -> "`: $$FILE_NOT_FOUND_MSG (os error"

fn main() {
let _ = include_str!("include-macros/file.txt"); //~ ERROR couldn't read
//~^HELP different directory
let _ = include_str!("hello.rs"); //~ ERROR couldn't read
//~^HELP different directory
let _ = include_bytes!("../../data.bin"); //~ ERROR couldn't read
//~^HELP different directory
let _ = include_str!("tests/ui/include-macros/file.txt"); //~ ERROR couldn't read
//~^HELP different directory
}
50 changes: 50 additions & 0 deletions tests/ui/include-macros/parent_dir.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
error: couldn't read `$DIR/include-macros/file.txt`: $FILE_NOT_FOUND_MSG (os error 2)
--> $DIR/parent_dir.rs:4:13
|
LL | let _ = include_str!("include-macros/file.txt");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
help: there is a file with the same name in a different directory
|
LL | let _ = include_str!("file.txt");
| ~~~~~~~~~~

error: couldn't read `$DIR/hello.rs`: $FILE_NOT_FOUND_MSG (os error 2)
--> $DIR/parent_dir.rs:6:13
|
LL | let _ = include_str!("hello.rs");
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
help: there is a file with the same name in a different directory
|
LL | let _ = include_str!("../hello.rs");
| ~~~~~~~~~~~~~

error: couldn't read `$DIR/../../data.bin`: $FILE_NOT_FOUND_MSG (os error 2)
--> $DIR/parent_dir.rs:8:13
|
LL | let _ = include_bytes!("../../data.bin");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
help: there is a file with the same name in a different directory
|
LL | let _ = include_bytes!("data.bin");
| ~~~~~~~~~~

error: couldn't read `$DIR/tests/ui/include-macros/file.txt`: $FILE_NOT_FOUND_MSG (os error 2)
--> $DIR/parent_dir.rs:10:13
|
LL | let _ = include_str!("tests/ui/include-macros/file.txt");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
help: there is a file with the same name in a different directory
|
LL | let _ = include_str!("file.txt");
| ~~~~~~~~~~

error: aborting due to 4 previous errors

2 changes: 1 addition & 1 deletion tests/ui/macros/macros-nonfatal-errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@ normalize-stderr-test: "existed:.*\(" -> "existed: $$FILE_NOT_FOUND_MSG ("
//@ normalize-stderr-test: "`: .*\(" -> "`: $$FILE_NOT_FOUND_MSG ("

// test that errors in a (selection) of macros don't kill compilation
// immediately, so that we get more errors listed at a time.
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/macros/macros-nonfatal-errors.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ error: argument must be a string literal
LL | include_str!(invalid);
| ^^^^^^^

error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG (os error 2)
--> $DIR/macros-nonfatal-errors.rs:113:5
|
LL | include_str!("i'd be quite surprised if a file with this name existed");
Expand All @@ -214,7 +214,7 @@ error: argument must be a string literal
LL | include_bytes!(invalid);
| ^^^^^^^

error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
error: couldn't read `$DIR/i'd be quite surprised if a file with this name existed`: $FILE_NOT_FOUND_MSG (os error 2)
--> $DIR/macros-nonfatal-errors.rs:115:5
|
LL | include_bytes!("i'd be quite surprised if a file with this name existed");
Expand Down