Skip to content

Commit 3d9a6ad

Browse files
authored
Rollup merge of rust-lang#129235 - GoldsteinE:check-may-dangle, r=compiler-errors
Check that `#[may_dangle]` is properly applied It's only valid when applied to a type or lifetime parameter in `Drop` trait implementation. Tracking issue: rust-lang#34761 cc rust-lang#34761 (comment)
2 parents 3f3230b + df6cb95 commit 3d9a6ad

File tree

7 files changed

+142
-8
lines changed

7 files changed

+142
-8
lines changed

Diff for: 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

Diff for: 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 {

Diff for: 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 {

Diff for: tests/ui/attributes/may_dangle.rs

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#![feature(dropck_eyepatch)]
2+
3+
struct Implee1<'a, T, const N: usize>(&'a T);
4+
struct Implee2<'a, T, const N: usize>(&'a T);
5+
struct Implee3<'a, T, const N: usize>(&'a T);
6+
trait NotDrop {}
7+
8+
unsafe impl<#[may_dangle] 'a, T, const N: usize> NotDrop for Implee1<'a, T, N> {}
9+
//~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
10+
11+
unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> {}
12+
//~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
13+
14+
unsafe impl<'a, T, #[may_dangle] const N: usize> Drop for Implee1<'a, T, N> {
15+
//~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
16+
fn drop(&mut self) {}
17+
}
18+
19+
// Ok, lifetime param in a `Drop` impl.
20+
unsafe impl<#[may_dangle] 'a, T, const N: usize> Drop for Implee2<'a, T, N> {
21+
fn drop(&mut self) {}
22+
}
23+
24+
// Ok, type param in a `Drop` impl.
25+
unsafe impl<'a, #[may_dangle] T, const N: usize> Drop for Implee3<'a, T, N> {
26+
fn drop(&mut self) {}
27+
}
28+
29+
// Check that this check is not textual.
30+
mod fake {
31+
trait Drop {
32+
fn drop(&mut self);
33+
}
34+
struct Implee<T>(T);
35+
36+
unsafe impl<#[may_dangle] T> Drop for Implee<T> {
37+
//~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
38+
fn drop(&mut self) {}
39+
}
40+
}
41+
42+
#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
43+
struct Dangling;
44+
45+
#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
46+
impl NotDrop for () {
47+
}
48+
49+
#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
50+
fn main() {
51+
#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
52+
let () = ();
53+
}

Diff for: tests/ui/attributes/may_dangle.stderr

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
2+
--> $DIR/may_dangle.rs:8:13
3+
|
4+
LL | unsafe impl<#[may_dangle] 'a, T, const N: usize> NotDrop for Implee1<'a, T, N> {}
5+
| ^^^^^^^^^^^^^
6+
7+
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
8+
--> $DIR/may_dangle.rs:11:17
9+
|
10+
LL | unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> {}
11+
| ^^^^^^^^^^^^^
12+
13+
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
14+
--> $DIR/may_dangle.rs:14:20
15+
|
16+
LL | unsafe impl<'a, T, #[may_dangle] const N: usize> Drop for Implee1<'a, T, N> {
17+
| ^^^^^^^^^^^^^
18+
19+
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
20+
--> $DIR/may_dangle.rs:42:1
21+
|
22+
LL | #[may_dangle]
23+
| ^^^^^^^^^^^^^
24+
25+
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
26+
--> $DIR/may_dangle.rs:45:1
27+
|
28+
LL | #[may_dangle]
29+
| ^^^^^^^^^^^^^
30+
31+
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
32+
--> $DIR/may_dangle.rs:49:1
33+
|
34+
LL | #[may_dangle]
35+
| ^^^^^^^^^^^^^
36+
37+
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
38+
--> $DIR/may_dangle.rs:51:5
39+
|
40+
LL | #[may_dangle]
41+
| ^^^^^^^^^^^^^
42+
43+
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
44+
--> $DIR/may_dangle.rs:36:17
45+
|
46+
LL | unsafe impl<#[may_dangle] T> Drop for Implee<T> {
47+
| ^^^^^^^^^^^^^
48+
49+
error: aborting due to 8 previous errors
50+

Diff for: tests/ui/lint/must_not_suspend/other_items.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: `must_not_suspend` attribute should be applied to a struct, enum, or trait
1+
error: `must_not_suspend` attribute should be applied to a struct, enum, union, or trait
22
--> $DIR/other_items.rs:5:1
33
|
44
LL | #[must_not_suspend]
55
| ^^^^^^^^^^^^^^^^^^^
66
LL | mod inner {}
7-
| ------------ is not a struct, enum, or trait
7+
| ------------ is not a struct, enum, union, or trait
88

99
error: aborting due to 1 previous error
1010

Diff for: tests/ui/lint/must_not_suspend/return.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
error: `must_not_suspend` attribute should be applied to a struct, enum, or trait
1+
error: `must_not_suspend` attribute should be applied to a struct, enum, union, or trait
22
--> $DIR/return.rs:5:1
33
|
44
LL | #[must_not_suspend]
55
| ^^^^^^^^^^^^^^^^^^^
66
LL | / fn foo() -> i32 {
77
LL | | 0
88
LL | | }
9-
| |_- is not a struct, enum, or trait
9+
| |_- is not a struct, enum, union, or trait
1010

1111
error: aborting due to 1 previous error
1212

0 commit comments

Comments
 (0)