Check that #[may_dangle]
is properly applied
It's only valid when applied to a type or lifetime parameter in `Drop` trait implementation.
This commit is contained in:
parent
7521bdaf5b
commit
3a9bf45513
@ -444,6 +444,9 @@ passes_macro_export_on_decl_macro =
|
|||||||
passes_macro_use =
|
passes_macro_use =
|
||||||
`#[{$name}]` only has an effect on `extern crate` and modules
|
`#[{$name}]` only has an effect on `extern crate` and modules
|
||||||
|
|
||||||
|
passes_may_dangle =
|
||||||
|
`#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
|
||||||
passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
|
passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
|
||||||
passes_missing_const_err =
|
passes_missing_const_err =
|
||||||
attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
||||||
|
@ -189,6 +189,7 @@ fn check_attributes(
|
|||||||
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
|
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
|
||||||
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
|
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
|
||||||
[sym::must_use, ..] => self.check_must_use(hir_id, attr, target),
|
[sym::must_use, ..] => self.check_must_use(hir_id, attr, target),
|
||||||
|
[sym::may_dangle, ..] => self.check_may_dangle(hir_id, attr),
|
||||||
[sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target),
|
[sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target),
|
||||||
[sym::rustc_allow_incoherent_impl, ..] => {
|
[sym::rustc_allow_incoherent_impl, ..] => {
|
||||||
self.check_allow_incoherent_impl(attr, span, target)
|
self.check_allow_incoherent_impl(attr, span, target)
|
||||||
@ -255,7 +256,6 @@ fn check_attributes(
|
|||||||
| sym::cfg_attr
|
| sym::cfg_attr
|
||||||
// need to be fixed
|
// need to be fixed
|
||||||
| sym::cfi_encoding // FIXME(cfi_encoding)
|
| sym::cfi_encoding // FIXME(cfi_encoding)
|
||||||
| sym::may_dangle // FIXME(dropck_eyepatch)
|
|
||||||
| sym::pointee // FIXME(derive_smart_pointer)
|
| sym::pointee // FIXME(derive_smart_pointer)
|
||||||
| sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
|
| sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
|
||||||
| sym::used // handled elsewhere to restrict to static items
|
| sym::used // handled elsewhere to restrict to static items
|
||||||
@ -1373,6 +1373,27 @@ fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl.
|
||||||
|
fn check_may_dangle(&self, hir_id: HirId, attr: &Attribute) {
|
||||||
|
if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id)
|
||||||
|
&& matches!(
|
||||||
|
param.kind,
|
||||||
|
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. }
|
||||||
|
)
|
||||||
|
&& matches!(param.source, hir::GenericParamSource::Generics)
|
||||||
|
&& let parent_hir_id = self.tcx.parent_hir_id(hir_id)
|
||||||
|
&& let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id)
|
||||||
|
&& let hir::ItemKind::Impl(impl_) = item.kind
|
||||||
|
&& let Some(trait_) = impl_.of_trait
|
||||||
|
&& let Some(def_id) = trait_.trait_def_id()
|
||||||
|
&& self.tcx.is_lang_item(def_id, hir::LangItem::Drop)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.dcx().emit_err(errors::InvalidMayDangle { attr_span: attr.span });
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks if `#[cold]` is applied to a non-function.
|
/// Checks if `#[cold]` is applied to a non-function.
|
||||||
fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
|
fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
|
||||||
match target {
|
match target {
|
||||||
|
@ -737,6 +737,13 @@ pub struct NonExportedMacroInvalidAttrs {
|
|||||||
pub attr_span: Span,
|
pub attr_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(passes_may_dangle)]
|
||||||
|
pub struct InvalidMayDangle {
|
||||||
|
#[primary_span]
|
||||||
|
pub attr_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(passes_unused_duplicate)]
|
#[diag(passes_unused_duplicate)]
|
||||||
pub struct UnusedDuplicate {
|
pub struct UnusedDuplicate {
|
||||||
|
53
tests/ui/attributes/may_dangle.rs
Normal file
53
tests/ui/attributes/may_dangle.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#![feature(dropck_eyepatch)]
|
||||||
|
|
||||||
|
struct Implee1<'a, T, const N: usize>(&'a T);
|
||||||
|
struct Implee2<'a, T, const N: usize>(&'a T);
|
||||||
|
struct Implee3<'a, T, const N: usize>(&'a T);
|
||||||
|
trait NotDrop {}
|
||||||
|
|
||||||
|
unsafe impl<#[may_dangle] 'a, T, const N: usize> NotDrop for Implee1<'a, T, N> {}
|
||||||
|
//~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
|
||||||
|
unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> {}
|
||||||
|
//~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
|
||||||
|
unsafe impl<'a, T, #[may_dangle] const N: usize> Drop for Implee1<'a, T, N> {
|
||||||
|
//~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
fn drop(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ok, lifetime param in a `Drop` impl.
|
||||||
|
unsafe impl<#[may_dangle] 'a, T, const N: usize> Drop for Implee2<'a, T, N> {
|
||||||
|
fn drop(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ok, type param in a `Drop` impl.
|
||||||
|
unsafe impl<'a, #[may_dangle] T, const N: usize> Drop for Implee3<'a, T, N> {
|
||||||
|
fn drop(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that this check is not textual.
|
||||||
|
mod fake {
|
||||||
|
trait Drop {
|
||||||
|
fn drop(&mut self);
|
||||||
|
}
|
||||||
|
struct Implee<T>(T);
|
||||||
|
|
||||||
|
unsafe impl<#[may_dangle] T> Drop for Implee<T> {
|
||||||
|
//~^ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
fn drop(&mut self) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
struct Dangling;
|
||||||
|
|
||||||
|
#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
impl NotDrop for () {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
fn main() {
|
||||||
|
#[may_dangle] //~ ERROR must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
let () = ();
|
||||||
|
}
|
50
tests/ui/attributes/may_dangle.stderr
Normal file
50
tests/ui/attributes/may_dangle.stderr
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
--> $DIR/may_dangle.rs:8:13
|
||||||
|
|
|
||||||
|
LL | unsafe impl<#[may_dangle] 'a, T, const N: usize> NotDrop for Implee1<'a, T, N> {}
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
--> $DIR/may_dangle.rs:11:17
|
||||||
|
|
|
||||||
|
LL | unsafe impl<'a, #[may_dangle] T, const N: usize> NotDrop for Implee2<'a, T, N> {}
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
--> $DIR/may_dangle.rs:14:20
|
||||||
|
|
|
||||||
|
LL | unsafe impl<'a, T, #[may_dangle] const N: usize> Drop for Implee1<'a, T, N> {
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
--> $DIR/may_dangle.rs:42:1
|
||||||
|
|
|
||||||
|
LL | #[may_dangle]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
--> $DIR/may_dangle.rs:45:1
|
||||||
|
|
|
||||||
|
LL | #[may_dangle]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
--> $DIR/may_dangle.rs:49:1
|
||||||
|
|
|
||||||
|
LL | #[may_dangle]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
--> $DIR/may_dangle.rs:51:5
|
||||||
|
|
|
||||||
|
LL | #[may_dangle]
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
--> $DIR/may_dangle.rs:36:17
|
||||||
|
|
|
||||||
|
LL | unsafe impl<#[may_dangle] T> Drop for Implee<T> {
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 8 previous errors
|
||||||
|
|
Loading…
Reference in New Issue
Block a user