Skip to content

Commit 0465e63

Browse files
committed
Auto merge of rust-lang#129256 - matthiaskrgr:rollup-kzuxwb6, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#128084 (Suggest adding Result return type for associated method in E0277.) - rust-lang#128902 (doc: std::env::var: Returns None for names with '=' or NUL byte) - rust-lang#129187 (bootstrap: fix clean's remove_dir_all implementation) - rust-lang#129194 (Fix bootstrap test `detect_src_and_out` on Windows) - rust-lang#129231 (improve submodule updates) - rust-lang#129235 (Check that `#[may_dangle]` is properly applied) - rust-lang#129245 (Typo) r? `@ghost` `@rustbot` modify labels: rollup
2 parents d0293c6 + a9919ec commit 0465e63

File tree

19 files changed

+415
-231
lines changed

19 files changed

+415
-231
lines changed

compiler/rustc_hir/src/hir.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1395,7 +1395,7 @@ pub struct LetExpr<'hir> {
13951395
pub pat: &'hir Pat<'hir>,
13961396
pub ty: Option<&'hir Ty<'hir>>,
13971397
pub init: &'hir Expr<'hir>,
1398-
/// `Recovered::Yes` when this let expressions is not in a syntanctically valid location.
1398+
/// `Recovered::Yes` when this let expressions is not in a syntactically valid location.
13991399
/// Used to prevent building MIR in such situations.
14001400
pub recovered: ast::Recovered,
14011401
}

compiler/rustc_passes/messages.ftl

+5-2
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,9 @@ passes_macro_export_on_decl_macro =
444444
passes_macro_use =
445445
`#[{$name}]` only has an effect on `extern crate` and modules
446446
447+
passes_may_dangle =
448+
`#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
449+
447450
passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
448451
passes_missing_const_err =
449452
attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
@@ -475,8 +478,8 @@ passes_multiple_start_functions =
475478
.previous = previous `#[start]` function here
476479
477480
passes_must_not_suspend =
478-
`must_not_suspend` attribute should be applied to a struct, enum, or trait
479-
.label = is not a struct, enum, or trait
481+
`must_not_suspend` attribute should be applied to a struct, enum, union, or trait
482+
.label = is not a struct, enum, union, or trait
480483
481484
passes_must_use_async =
482485
`must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within

compiler/rustc_passes/src/check_attr.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
189189
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
190190
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
191191
[sym::must_use, ..] => self.check_must_use(hir_id, attr, target),
192+
[sym::may_dangle, ..] => self.check_may_dangle(hir_id, attr),
192193
[sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target),
193194
[sym::rustc_allow_incoherent_impl, ..] => {
194195
self.check_allow_incoherent_impl(attr, span, target)
@@ -255,7 +256,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
255256
| sym::cfg_attr
256257
// need to be fixed
257258
| sym::cfi_encoding // FIXME(cfi_encoding)
258-
| sym::may_dangle // FIXME(dropck_eyepatch)
259259
| sym::pointee // FIXME(derive_smart_pointer)
260260
| sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
261261
| sym::used // handled elsewhere to restrict to static items
@@ -1363,7 +1363,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
13631363
}
13641364
}
13651365

1366-
/// Checks if `#[must_not_suspend]` is applied to a function.
1366+
/// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait.
13671367
fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) {
13681368
match target {
13691369
Target::Struct | Target::Enum | Target::Union | Target::Trait => {}
@@ -1373,6 +1373,27 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
13731373
}
13741374
}
13751375

1376+
/// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl.
1377+
fn check_may_dangle(&self, hir_id: HirId, attr: &Attribute) {
1378+
if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id)
1379+
&& matches!(
1380+
param.kind,
1381+
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. }
1382+
)
1383+
&& matches!(param.source, hir::GenericParamSource::Generics)
1384+
&& let parent_hir_id = self.tcx.parent_hir_id(hir_id)
1385+
&& let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id)
1386+
&& let hir::ItemKind::Impl(impl_) = item.kind
1387+
&& let Some(trait_) = impl_.of_trait
1388+
&& let Some(def_id) = trait_.trait_def_id()
1389+
&& self.tcx.is_lang_item(def_id, hir::LangItem::Drop)
1390+
{
1391+
return;
1392+
}
1393+
1394+
self.dcx().emit_err(errors::InvalidMayDangle { attr_span: attr.span });
1395+
}
1396+
13761397
/// Checks if `#[cold]` is applied to a non-function.
13771398
fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
13781399
match target {

compiler/rustc_passes/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,13 @@ pub struct NonExportedMacroInvalidAttrs {
737737
pub attr_span: Span,
738738
}
739739

740+
#[derive(Diagnostic)]
741+
#[diag(passes_may_dangle)]
742+
pub struct InvalidMayDangle {
743+
#[primary_span]
744+
pub attr_span: Span,
745+
}
746+
740747
#[derive(LintDiagnostic)]
741748
#[diag(passes_unused_duplicate)]
742749
pub struct UnusedDuplicate {

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

+36-5
Original file line numberDiff line numberDiff line change
@@ -4610,6 +4610,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
46104610
})
46114611
}
46124612

4613+
// For E0277 when use `?` operator, suggest adding
4614+
// a suitable return type in `FnSig`, and a default
4615+
// return value at the end of the function's body.
46134616
pub(super) fn suggest_add_result_as_return_type(
46144617
&self,
46154618
obligation: &PredicateObligation<'tcx>,
@@ -4620,19 +4623,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
46204623
return;
46214624
}
46224625

4626+
// Only suggest for local function and associated method,
4627+
// because this suggest adding both return type in
4628+
// the `FnSig` and a default return value in the body, so it
4629+
// is not suitable for foreign function without a local body,
4630+
// and neighter for trait method which may be also implemented
4631+
// in other place, so shouldn't change it's FnSig.
4632+
fn choose_suggest_items<'tcx, 'hir>(
4633+
tcx: TyCtxt<'tcx>,
4634+
node: hir::Node<'hir>,
4635+
) -> Option<(&'hir hir::FnDecl<'hir>, hir::BodyId)> {
4636+
match node {
4637+
hir::Node::Item(item) if let hir::ItemKind::Fn(sig, _, body_id) = item.kind => {
4638+
Some((sig.decl, body_id))
4639+
}
4640+
hir::Node::ImplItem(item)
4641+
if let hir::ImplItemKind::Fn(sig, body_id) = item.kind =>
4642+
{
4643+
let parent = tcx.parent_hir_node(item.hir_id());
4644+
if let hir::Node::Item(item) = parent
4645+
&& let hir::ItemKind::Impl(imp) = item.kind
4646+
&& imp.of_trait.is_none()
4647+
{
4648+
return Some((sig.decl, body_id));
4649+
}
4650+
None
4651+
}
4652+
_ => None,
4653+
}
4654+
}
4655+
46234656
let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id);
4624-
if let hir::Node::Item(item) = node
4625-
&& let hir::ItemKind::Fn(sig, _, body_id) = item.kind
4626-
&& let hir::FnRetTy::DefaultReturn(ret_span) = sig.decl.output
4657+
if let Some((fn_decl, body_id)) = choose_suggest_items(self.tcx, node)
4658+
&& let hir::FnRetTy::DefaultReturn(ret_span) = fn_decl.output
46274659
&& self.tcx.is_diagnostic_item(sym::FromResidual, trait_pred.def_id())
46284660
&& trait_pred.skip_binder().trait_ref.args.type_at(0).is_unit()
46294661
&& let ty::Adt(def, _) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
46304662
&& self.tcx.is_diagnostic_item(sym::Result, def.did())
46314663
{
4632-
let body = self.tcx.hir().body(body_id);
46334664
let mut sugg_spans =
46344665
vec![(ret_span, " -> Result<(), Box<dyn std::error::Error>>".to_string())];
4635-
4666+
let body = self.tcx.hir().body(body_id);
46364667
if let hir::ExprKind::Block(b, _) = body.value.kind
46374668
&& b.expr.is_none()
46384669
{

library/std/src/env.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,12 @@ impl fmt::Debug for VarsOs {
198198
///
199199
/// # Errors
200200
///
201-
/// This function will return an error if the environment variable isn't set.
201+
/// Returns [`VarError::NotPresent`] if:
202+
/// - The variable is not set.
203+
/// - The variable's name contains an equal sign or NUL (`'='` or `'\0'`).
202204
///
203-
/// This function may return an error if the environment variable's name contains
204-
/// the equal sign character (`=`) or the NUL character.
205-
///
206-
/// This function will return an error if the environment variable's value is
207-
/// not valid Unicode. If this is not desired, consider using [`var_os`].
205+
/// Returns [`VarError::NotUnicode`] if the variable's value is not valid
206+
/// Unicode. If this is not desired, consider using [`var_os`].
208207
///
209208
/// # Examples
210209
///

src/bootstrap/src/core/build_steps/clean.rs

+15-78
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
//! directory unless the `--all` flag is present.
77
88
use std::fs;
9-
use std::io::{self, ErrorKind};
109
use std::path::Path;
1110

1211
use crate::core::builder::{crate_description, Builder, RunConfig, ShouldRun, Step};
@@ -101,11 +100,11 @@ fn clean(build: &Build, all: bool, stage: Option<u32>) {
101100
return;
102101
}
103102

104-
rm_rf("tmp".as_ref());
103+
remove_dir_recursive("tmp");
105104

106105
// Clean the entire build directory
107106
if all {
108-
rm_rf(&build.out);
107+
remove_dir_recursive(&build.out);
109108
return;
110109
}
111110

@@ -136,17 +135,17 @@ fn clean_specific_stage(build: &Build, stage: u32) {
136135
}
137136

138137
let path = t!(entry.path().canonicalize());
139-
rm_rf(&path);
138+
remove_dir_recursive(&path);
140139
}
141140
}
142141
}
143142

144143
fn clean_default(build: &Build) {
145-
rm_rf(&build.out.join("tmp"));
146-
rm_rf(&build.out.join("dist"));
147-
rm_rf(&build.out.join("bootstrap").join(".last-warned-change-id"));
148-
rm_rf(&build.out.join("bootstrap-shims-dump"));
149-
rm_rf(&build.out.join("rustfmt.stamp"));
144+
remove_dir_recursive(build.out.join("tmp"));
145+
remove_dir_recursive(build.out.join("dist"));
146+
remove_dir_recursive(build.out.join("bootstrap").join(".last-warned-change-id"));
147+
remove_dir_recursive(build.out.join("bootstrap-shims-dump"));
148+
remove_dir_recursive(build.out.join("rustfmt.stamp"));
150149

151150
let mut hosts: Vec<_> = build.hosts.iter().map(|t| build.out.join(t)).collect();
152151
// After cross-compilation, artifacts of the host architecture (which may differ from build.host)
@@ -166,78 +165,16 @@ fn clean_default(build: &Build) {
166165
continue;
167166
}
168167
let path = t!(entry.path().canonicalize());
169-
rm_rf(&path);
168+
remove_dir_recursive(&path);
170169
}
171170
}
172171
}
173172

174-
fn rm_rf(path: &Path) {
175-
match path.symlink_metadata() {
176-
Err(e) => {
177-
if e.kind() == ErrorKind::NotFound {
178-
return;
179-
}
180-
panic!("failed to get metadata for file {}: {}", path.display(), e);
181-
}
182-
Ok(metadata) => {
183-
if metadata.file_type().is_file() || metadata.file_type().is_symlink() {
184-
do_op(path, "remove file", |p| match fs::remove_file(p) {
185-
#[cfg(windows)]
186-
Err(e)
187-
if e.kind() == std::io::ErrorKind::PermissionDenied
188-
&& p.file_name().and_then(std::ffi::OsStr::to_str)
189-
== Some("bootstrap.exe") =>
190-
{
191-
eprintln!("WARNING: failed to delete '{}'.", p.display());
192-
Ok(())
193-
}
194-
r => r,
195-
});
196-
197-
return;
198-
}
199-
200-
for file in t!(fs::read_dir(path)) {
201-
rm_rf(&t!(file).path());
202-
}
203-
204-
do_op(path, "remove dir", |p| match fs::remove_dir(p) {
205-
// Check for dir not empty on Windows
206-
// FIXME: Once `ErrorKind::DirectoryNotEmpty` is stabilized,
207-
// match on `e.kind()` instead.
208-
#[cfg(windows)]
209-
Err(e) if e.raw_os_error() == Some(145) => Ok(()),
210-
r => r,
211-
});
212-
}
213-
};
214-
}
215-
216-
fn do_op<F>(path: &Path, desc: &str, mut f: F)
217-
where
218-
F: FnMut(&Path) -> io::Result<()>,
219-
{
220-
match f(path) {
221-
Ok(()) => {}
222-
// On windows we can't remove a readonly file, and git will often clone files as readonly.
223-
// As a result, we have some special logic to remove readonly files on windows.
224-
// This is also the reason that we can't use things like fs::remove_dir_all().
225-
#[cfg(windows)]
226-
Err(ref e) if e.kind() == ErrorKind::PermissionDenied => {
227-
let m = t!(path.symlink_metadata());
228-
let mut p = m.permissions();
229-
p.set_readonly(false);
230-
t!(fs::set_permissions(path, p));
231-
f(path).unwrap_or_else(|e| {
232-
// Delete symlinked directories on Windows
233-
if m.file_type().is_symlink() && path.is_dir() && fs::remove_dir(path).is_ok() {
234-
return;
235-
}
236-
panic!("failed to {} {}: {}", desc, path.display(), e);
237-
});
238-
}
239-
Err(e) => {
240-
panic!("failed to {} {}: {}", desc, path.display(), e);
241-
}
173+
/// Wrapper for [`std::fs::remove_dir_all`] that panics on failure and prints the `path` we failed
174+
/// on.
175+
fn remove_dir_recursive<P: AsRef<Path>>(path: P) {
176+
let path = path.as_ref();
177+
if let Err(e) = fs::remove_dir_all(path) {
178+
panic!("failed to `remove_dir_all` at `{}`: {e}", path.display());
242179
}
243180
}

src/bootstrap/src/core/build_steps/llvm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L
110110

111111
// Initialize the llvm submodule if not initialized already.
112112
// If submodules are disabled, this does nothing.
113-
builder.update_submodule("src/llvm-project");
113+
builder.config.update_submodule("src/llvm-project");
114114

115115
let root = "src/llvm-project/llvm";
116116
let out_dir = builder.llvm_out(target);

0 commit comments

Comments
 (0)