mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-27 07:03:45 +00:00
Auto merge of #124482 - spastorino:unsafe-extern-blocks, r=oli-obk
Unsafe extern blocks This implements RFC 3484. Tracking issue #123743 and RFC https://github.com/rust-lang/rfcs/pull/3484 This is better reviewed commit by commit.
This commit is contained in:
commit
2d28b6384e
@ -2501,6 +2501,8 @@ pub enum IsAuto {
|
|||||||
pub enum Safety {
|
pub enum Safety {
|
||||||
/// `unsafe` an item is explicitly marked as `unsafe`.
|
/// `unsafe` an item is explicitly marked as `unsafe`.
|
||||||
Unsafe(Span),
|
Unsafe(Span),
|
||||||
|
/// `safe` an item is explicitly marked as `safe`.
|
||||||
|
Safe(Span),
|
||||||
/// Default means no value was provided, it will take a default value given the context in
|
/// Default means no value was provided, it will take a default value given the context in
|
||||||
/// which is used.
|
/// which is used.
|
||||||
Default,
|
Default,
|
||||||
@ -3162,6 +3164,7 @@ pub struct DelegationMac {
|
|||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub struct StaticItem {
|
pub struct StaticItem {
|
||||||
pub ty: P<Ty>,
|
pub ty: P<Ty>,
|
||||||
|
pub safety: Safety,
|
||||||
pub mutability: Mutability,
|
pub mutability: Mutability,
|
||||||
pub expr: Option<P<Expr>>,
|
pub expr: Option<P<Expr>>,
|
||||||
}
|
}
|
||||||
@ -3171,6 +3174,7 @@ pub struct StaticItem {
|
|||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub struct StaticForeignItem {
|
pub struct StaticForeignItem {
|
||||||
pub ty: P<Ty>,
|
pub ty: P<Ty>,
|
||||||
|
pub safety: Safety,
|
||||||
pub mutability: Mutability,
|
pub mutability: Mutability,
|
||||||
pub expr: Option<P<Expr>>,
|
pub expr: Option<P<Expr>>,
|
||||||
}
|
}
|
||||||
@ -3179,6 +3183,7 @@ impl From<StaticItem> for StaticForeignItem {
|
|||||||
fn from(static_item: StaticItem) -> StaticForeignItem {
|
fn from(static_item: StaticItem) -> StaticForeignItem {
|
||||||
StaticForeignItem {
|
StaticForeignItem {
|
||||||
ty: static_item.ty,
|
ty: static_item.ty,
|
||||||
|
safety: static_item.safety,
|
||||||
mutability: static_item.mutability,
|
mutability: static_item.mutability,
|
||||||
expr: static_item.expr,
|
expr: static_item.expr,
|
||||||
}
|
}
|
||||||
@ -3189,6 +3194,7 @@ impl From<StaticForeignItem> for StaticItem {
|
|||||||
fn from(static_item: StaticForeignItem) -> StaticItem {
|
fn from(static_item: StaticForeignItem) -> StaticItem {
|
||||||
StaticItem {
|
StaticItem {
|
||||||
ty: static_item.ty,
|
ty: static_item.ty,
|
||||||
|
safety: static_item.safety,
|
||||||
mutability: static_item.mutability,
|
mutability: static_item.mutability,
|
||||||
expr: static_item.expr,
|
expr: static_item.expr,
|
||||||
}
|
}
|
||||||
|
@ -862,6 +862,7 @@ fn visit_defaultness<T: MutVisitor>(defaultness: &mut Defaultness, vis: &mut T)
|
|||||||
fn visit_safety<T: MutVisitor>(safety: &mut Safety, vis: &mut T) {
|
fn visit_safety<T: MutVisitor>(safety: &mut Safety, vis: &mut T) {
|
||||||
match safety {
|
match safety {
|
||||||
Safety::Unsafe(span) => vis.visit_span(span),
|
Safety::Unsafe(span) => vis.visit_span(span),
|
||||||
|
Safety::Safe(span) => vis.visit_span(span),
|
||||||
Safety::Default => {}
|
Safety::Default => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1079,7 +1080,7 @@ impl NoopVisitItemKind for ItemKind {
|
|||||||
match self {
|
match self {
|
||||||
ItemKind::ExternCrate(_orig_name) => {}
|
ItemKind::ExternCrate(_orig_name) => {}
|
||||||
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
|
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
|
||||||
ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
|
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
|
||||||
vis.visit_ty(ty);
|
vis.visit_ty(ty);
|
||||||
visit_opt(expr, |expr| vis.visit_expr(expr));
|
visit_opt(expr, |expr| vis.visit_expr(expr));
|
||||||
}
|
}
|
||||||
@ -1289,7 +1290,12 @@ pub fn noop_flat_map_item<K: NoopVisitItemKind>(
|
|||||||
impl NoopVisitItemKind for ForeignItemKind {
|
impl NoopVisitItemKind for ForeignItemKind {
|
||||||
fn noop_visit(&mut self, visitor: &mut impl MutVisitor) {
|
fn noop_visit(&mut self, visitor: &mut impl MutVisitor) {
|
||||||
match self {
|
match self {
|
||||||
ForeignItemKind::Static(box StaticForeignItem { ty, mutability: _, expr }) => {
|
ForeignItemKind::Static(box StaticForeignItem {
|
||||||
|
ty,
|
||||||
|
mutability: _,
|
||||||
|
expr,
|
||||||
|
safety: _,
|
||||||
|
}) => {
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(ty);
|
||||||
visit_opt(expr, |expr| visitor.visit_expr(expr));
|
visit_opt(expr, |expr| visitor.visit_expr(expr));
|
||||||
}
|
}
|
||||||
|
@ -210,6 +210,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: IdentIsRaw) -> boo
|
|||||||
kw::Unsafe,
|
kw::Unsafe,
|
||||||
kw::While,
|
kw::While,
|
||||||
kw::Yield,
|
kw::Yield,
|
||||||
|
kw::Safe,
|
||||||
kw::Static,
|
kw::Static,
|
||||||
]
|
]
|
||||||
.contains(&name)
|
.contains(&name)
|
||||||
@ -577,6 +578,7 @@ impl Token {
|
|||||||
kw::Impl,
|
kw::Impl,
|
||||||
kw::Unsafe,
|
kw::Unsafe,
|
||||||
kw::Const,
|
kw::Const,
|
||||||
|
kw::Safe,
|
||||||
kw::Static,
|
kw::Static,
|
||||||
kw::Union,
|
kw::Union,
|
||||||
kw::Macro,
|
kw::Macro,
|
||||||
|
@ -334,7 +334,7 @@ impl WalkItemKind for ItemKind {
|
|||||||
match self {
|
match self {
|
||||||
ItemKind::ExternCrate(_) => {}
|
ItemKind::ExternCrate(_) => {}
|
||||||
ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, item.id, false)),
|
ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, item.id, false)),
|
||||||
ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
|
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
|
||||||
try_visit!(visitor.visit_ty(ty));
|
try_visit!(visitor.visit_ty(ty));
|
||||||
visit_opt!(visitor, visit_expr, expr);
|
visit_opt!(visitor, visit_expr, expr);
|
||||||
}
|
}
|
||||||
@ -658,7 +658,12 @@ impl WalkItemKind for ForeignItemKind {
|
|||||||
) -> V::Result {
|
) -> V::Result {
|
||||||
let &Item { id, span, ident, ref vis, .. } = item;
|
let &Item { id, span, ident, ref vis, .. } = item;
|
||||||
match self {
|
match self {
|
||||||
ForeignItemKind::Static(box StaticForeignItem { ty, mutability: _, expr }) => {
|
ForeignItemKind::Static(box StaticForeignItem {
|
||||||
|
ty,
|
||||||
|
mutability: _,
|
||||||
|
expr,
|
||||||
|
safety: _,
|
||||||
|
}) => {
|
||||||
try_visit!(visitor.visit_ty(ty));
|
try_visit!(visitor.visit_ty(ty));
|
||||||
visit_opt!(visitor, visit_expr, expr);
|
visit_opt!(visitor, visit_expr, expr);
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
|
|
||||||
self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
|
self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
|
||||||
}
|
}
|
||||||
ItemKind::Static(box ast::StaticItem { ty: t, mutability: m, expr: e }) => {
|
ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => {
|
||||||
let (ty, body_id) =
|
let (ty, body_id) =
|
||||||
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
|
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
|
||||||
hir::ItemKind::Static(ty, *m, body_id)
|
hir::ItemKind::Static(ty, *m, body_id)
|
||||||
@ -388,7 +388,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
|
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
|
||||||
};
|
};
|
||||||
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
|
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
|
||||||
safety: self.lower_safety(*safety),
|
safety: self.lower_safety(*safety, hir::Safety::Safe),
|
||||||
polarity,
|
polarity,
|
||||||
defaultness,
|
defaultness,
|
||||||
defaultness_span,
|
defaultness_span,
|
||||||
@ -418,7 +418,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let items = this.arena.alloc_from_iter(
|
let items = this.arena.alloc_from_iter(
|
||||||
items.iter().map(|item| this.lower_trait_item_ref(item)),
|
items.iter().map(|item| this.lower_trait_item_ref(item)),
|
||||||
);
|
);
|
||||||
let safety = this.lower_safety(*safety);
|
let safety = this.lower_safety(*safety, hir::Safety::Safe);
|
||||||
(safety, items, bounds)
|
(safety, items, bounds)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -660,13 +660,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
this.lower_fn_params_to_names(fdec),
|
this.lower_fn_params_to_names(fdec),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
let safety = self.lower_safety(sig.header.safety, hir::Safety::Unsafe);
|
||||||
|
|
||||||
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
|
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics, safety)
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(box StaticForeignItem { ty, mutability, expr: _ }) => {
|
ForeignItemKind::Static(box StaticForeignItem {
|
||||||
|
ty,
|
||||||
|
mutability,
|
||||||
|
expr: _,
|
||||||
|
safety,
|
||||||
|
}) => {
|
||||||
let ty = self
|
let ty = self
|
||||||
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
|
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
|
||||||
hir::ForeignItemKind::Static(ty, *mutability)
|
let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
|
||||||
|
|
||||||
|
hir::ForeignItemKind::Static(ty, *mutability, safety)
|
||||||
}
|
}
|
||||||
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
|
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
|
||||||
ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
|
ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
|
||||||
@ -1360,7 +1368,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
hir::IsAsync::NotAsync
|
hir::IsAsync::NotAsync
|
||||||
};
|
};
|
||||||
hir::FnHeader {
|
hir::FnHeader {
|
||||||
safety: self.lower_safety(h.safety),
|
safety: self.lower_safety(h.safety, hir::Safety::Safe),
|
||||||
asyncness: asyncness,
|
asyncness: asyncness,
|
||||||
constness: self.lower_constness(h.constness),
|
constness: self.lower_constness(h.constness),
|
||||||
abi: self.lower_extern(h.ext),
|
abi: self.lower_extern(h.ext),
|
||||||
@ -1410,10 +1418,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn lower_safety(&mut self, s: Safety) -> hir::Safety {
|
pub(super) fn lower_safety(&mut self, s: Safety, default: hir::Safety) -> hir::Safety {
|
||||||
match s {
|
match s {
|
||||||
Safety::Unsafe(_) => hir::Safety::Unsafe,
|
Safety::Unsafe(_) => hir::Safety::Unsafe,
|
||||||
Safety::Default => hir::Safety::Safe,
|
Safety::Default => default,
|
||||||
|
Safety::Safe(_) => hir::Safety::Safe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1321,7 +1321,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
|
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
|
||||||
hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
|
hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
|
||||||
generic_params,
|
generic_params,
|
||||||
safety: self.lower_safety(f.safety),
|
safety: self.lower_safety(f.safety, hir::Safety::Safe),
|
||||||
abi: self.lower_extern(f.ext),
|
abi: self.lower_extern(f.ext),
|
||||||
decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None),
|
decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None),
|
||||||
param_names: self.lower_fn_params_to_names(&f.decl),
|
param_names: self.lower_fn_params_to_names(&f.decl),
|
||||||
|
@ -67,6 +67,9 @@ ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have quali
|
|||||||
.label = in this `extern` block
|
.label = in this `extern` block
|
||||||
.suggestion = remove this qualifier
|
.suggestion = remove this qualifier
|
||||||
|
|
||||||
|
ast_passes_extern_invalid_safety = items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
|
.suggestion = add unsafe to this `extern` block
|
||||||
|
|
||||||
ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
|
ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
|
||||||
.label = in this `extern` block
|
.label = in this `extern` block
|
||||||
.note = this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
|
.note = this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
|
||||||
@ -174,6 +177,8 @@ ast_passes_match_arm_with_no_body =
|
|||||||
`match` arm with no body
|
`match` arm with no body
|
||||||
.suggestion = add a body after the pattern
|
.suggestion = add a body after the pattern
|
||||||
|
|
||||||
|
ast_passes_missing_unsafe_on_extern = extern blocks must be unsafe
|
||||||
|
|
||||||
ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
|
ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
|
||||||
.help = consider using the `#[path]` attribute to specify filesystem path
|
.help = consider using the `#[path]` attribute to specify filesystem path
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@ use rustc_data_structures::fx::FxIndexMap;
|
|||||||
use rustc_feature::Features;
|
use rustc_feature::Features;
|
||||||
use rustc_parse::validate_attr;
|
use rustc_parse::validate_attr;
|
||||||
use rustc_session::lint::builtin::{
|
use rustc_session::lint::builtin::{
|
||||||
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
|
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN,
|
||||||
|
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||||
};
|
};
|
||||||
use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
|
use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
@ -86,6 +87,9 @@ struct AstValidator<'a> {
|
|||||||
/// or `Foo::Bar<impl Trait>`
|
/// or `Foo::Bar<impl Trait>`
|
||||||
is_impl_trait_banned: bool,
|
is_impl_trait_banned: bool,
|
||||||
|
|
||||||
|
/// Used to ban explicit safety on foreign items when the extern block is not marked as unsafe.
|
||||||
|
extern_mod_safety: Option<Safety>,
|
||||||
|
|
||||||
lint_buffer: &'a mut LintBuffer,
|
lint_buffer: &'a mut LintBuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,6 +120,12 @@ impl<'a> AstValidator<'a> {
|
|||||||
self.outer_trait_or_trait_impl = old;
|
self.outer_trait_or_trait_impl = old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_in_extern_mod(&mut self, extern_mod_safety: Safety, f: impl FnOnce(&mut Self)) {
|
||||||
|
let old = mem::replace(&mut self.extern_mod_safety, Some(extern_mod_safety));
|
||||||
|
f(self);
|
||||||
|
self.extern_mod_safety = old;
|
||||||
|
}
|
||||||
|
|
||||||
fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
|
fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
|
||||||
let old = mem::replace(&mut self.is_impl_trait_banned, true);
|
let old = mem::replace(&mut self.is_impl_trait_banned, true);
|
||||||
f(self);
|
f(self);
|
||||||
@ -429,6 +439,18 @@ impl<'a> AstValidator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_foreign_item_safety(&self, item_span: Span, safety: Safety) {
|
||||||
|
if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_))
|
||||||
|
&& (self.extern_mod_safety == Some(Safety::Default)
|
||||||
|
|| !self.features.unsafe_extern_blocks)
|
||||||
|
{
|
||||||
|
self.dcx().emit_err(errors::InvalidSafetyOnExtern {
|
||||||
|
item_span,
|
||||||
|
block: self.current_extern_span(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
|
fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
|
||||||
if let Defaultness::Default(def_span) = defaultness {
|
if let Defaultness::Default(def_span) = defaultness {
|
||||||
let span = self.session.source_map().guess_head_span(span);
|
let span = self.session.source_map().guess_head_span(span);
|
||||||
@ -518,7 +540,7 @@ impl<'a> AstValidator<'a> {
|
|||||||
fn check_foreign_fn_headerless(
|
fn check_foreign_fn_headerless(
|
||||||
&self,
|
&self,
|
||||||
// Deconstruct to ensure exhaustiveness
|
// Deconstruct to ensure exhaustiveness
|
||||||
FnHeader { safety, coroutine_kind, constness, ext }: FnHeader,
|
FnHeader { safety: _, coroutine_kind, constness, ext }: FnHeader,
|
||||||
) {
|
) {
|
||||||
let report_err = |span| {
|
let report_err = |span| {
|
||||||
self.dcx().emit_err(errors::FnQualifierInExtern {
|
self.dcx().emit_err(errors::FnQualifierInExtern {
|
||||||
@ -526,10 +548,6 @@ impl<'a> AstValidator<'a> {
|
|||||||
block: self.current_extern_span(),
|
block: self.current_extern_span(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
match safety {
|
|
||||||
Safety::Unsafe(span) => report_err(span),
|
|
||||||
Safety::Default => (),
|
|
||||||
}
|
|
||||||
match coroutine_kind {
|
match coroutine_kind {
|
||||||
Some(knd) => report_err(knd.span()),
|
Some(knd) => report_err(knd.span()),
|
||||||
None => (),
|
None => (),
|
||||||
@ -1017,19 +1035,39 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
return; // Avoid visiting again.
|
return; // Avoid visiting again.
|
||||||
}
|
}
|
||||||
ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => {
|
ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => {
|
||||||
let old_item = mem::replace(&mut self.extern_mod, Some(item));
|
self.with_in_extern_mod(*safety, |this| {
|
||||||
self.visibility_not_permitted(
|
let old_item = mem::replace(&mut this.extern_mod, Some(item));
|
||||||
&item.vis,
|
this.visibility_not_permitted(
|
||||||
errors::VisibilityNotPermittedNote::IndividualForeignItems,
|
&item.vis,
|
||||||
);
|
errors::VisibilityNotPermittedNote::IndividualForeignItems,
|
||||||
if let &Safety::Unsafe(span) = safety {
|
);
|
||||||
self.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" });
|
|
||||||
}
|
if this.features.unsafe_extern_blocks {
|
||||||
if abi.is_none() {
|
if &Safety::Default == safety {
|
||||||
self.maybe_lint_missing_abi(item.span, item.id);
|
if item.span.at_least_rust_2024() {
|
||||||
}
|
this.dcx()
|
||||||
visit::walk_item(self, item);
|
.emit_err(errors::MissingUnsafeOnExtern { span: item.span });
|
||||||
self.extern_mod = old_item;
|
} else {
|
||||||
|
this.lint_buffer.buffer_lint(
|
||||||
|
MISSING_UNSAFE_ON_EXTERN,
|
||||||
|
item.id,
|
||||||
|
item.span,
|
||||||
|
BuiltinLintDiag::MissingUnsafeOnExtern {
|
||||||
|
suggestion: item.span.shrink_to_lo(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let &Safety::Unsafe(span) = safety {
|
||||||
|
this.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" });
|
||||||
|
}
|
||||||
|
|
||||||
|
if abi.is_none() {
|
||||||
|
this.maybe_lint_missing_abi(item.span, item.id);
|
||||||
|
}
|
||||||
|
visit::walk_item(this, item);
|
||||||
|
this.extern_mod = old_item;
|
||||||
|
});
|
||||||
return; // Avoid visiting again.
|
return; // Avoid visiting again.
|
||||||
}
|
}
|
||||||
ItemKind::Enum(def, _) => {
|
ItemKind::Enum(def, _) => {
|
||||||
@ -1161,6 +1199,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
||||||
match &fi.kind {
|
match &fi.kind {
|
||||||
ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
|
ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
|
||||||
|
self.check_foreign_item_safety(fi.span, sig.header.safety);
|
||||||
self.check_defaultness(fi.span, *defaultness);
|
self.check_defaultness(fi.span, *defaultness);
|
||||||
self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
|
self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
|
||||||
self.check_foreign_fn_headerless(sig.header);
|
self.check_foreign_fn_headerless(sig.header);
|
||||||
@ -1180,7 +1219,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
self.check_foreign_ty_genericless(generics, where_clauses);
|
self.check_foreign_ty_genericless(generics, where_clauses);
|
||||||
self.check_foreign_item_ascii_only(fi.ident);
|
self.check_foreign_item_ascii_only(fi.ident);
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(box StaticForeignItem { ty: _, mutability: _, expr }) => {
|
ForeignItemKind::Static(box StaticForeignItem { expr, safety, .. }) => {
|
||||||
|
self.check_foreign_item_safety(fi.span, *safety);
|
||||||
self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span));
|
self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span));
|
||||||
self.check_foreign_item_ascii_only(fi.ident);
|
self.check_foreign_item_ascii_only(fi.ident);
|
||||||
}
|
}
|
||||||
@ -1736,6 +1776,7 @@ pub fn check_crate(
|
|||||||
outer_impl_trait: None,
|
outer_impl_trait: None,
|
||||||
disallow_tilde_const: Some(DisallowTildeConstContext::Item),
|
disallow_tilde_const: Some(DisallowTildeConstContext::Item),
|
||||||
is_impl_trait_banned: false,
|
is_impl_trait_banned: false,
|
||||||
|
extern_mod_safety: None,
|
||||||
lint_buffer: lints,
|
lint_buffer: lints,
|
||||||
};
|
};
|
||||||
visit::walk_crate(&mut validator, krate);
|
visit::walk_crate(&mut validator, krate);
|
||||||
|
@ -216,6 +216,15 @@ pub enum ExternBlockSuggestion {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_passes_extern_invalid_safety)]
|
||||||
|
pub struct InvalidSafetyOnExtern {
|
||||||
|
#[primary_span]
|
||||||
|
pub item_span: Span,
|
||||||
|
#[suggestion(code = "", applicability = "maybe-incorrect")]
|
||||||
|
pub block: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_bound_in_context)]
|
#[diag(ast_passes_bound_in_context)]
|
||||||
pub struct BoundInContext<'a> {
|
pub struct BoundInContext<'a> {
|
||||||
@ -485,6 +494,13 @@ pub struct UnsafeItem {
|
|||||||
pub kind: &'static str,
|
pub kind: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_passes_missing_unsafe_on_extern)]
|
||||||
|
pub struct MissingUnsafeOnExtern {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_fieldless_union)]
|
#[diag(ast_passes_fieldless_union)]
|
||||||
pub struct FieldlessUnion {
|
pub struct FieldlessUnion {
|
||||||
|
@ -1973,6 +1973,7 @@ impl<'a> State<'a> {
|
|||||||
fn print_safety(&mut self, s: ast::Safety) {
|
fn print_safety(&mut self, s: ast::Safety) {
|
||||||
match s {
|
match s {
|
||||||
ast::Safety::Default => {}
|
ast::Safety::Default => {}
|
||||||
|
ast::Safety::Safe(_) => self.word_nbsp("safe"),
|
||||||
ast::Safety::Unsafe(_) => self.word_nbsp("unsafe"),
|
ast::Safety::Unsafe(_) => self.word_nbsp("unsafe"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,13 @@ impl<'a> State<'a> {
|
|||||||
ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
|
ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
|
||||||
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
|
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
|
||||||
}
|
}
|
||||||
ast::ForeignItemKind::Static(box ast::StaticForeignItem { ty, mutability, expr }) => {
|
ast::ForeignItemKind::Static(box ast::StaticForeignItem {
|
||||||
|
ty,
|
||||||
|
mutability,
|
||||||
|
expr,
|
||||||
|
safety,
|
||||||
|
}) => {
|
||||||
|
self.print_safety(*safety);
|
||||||
self.print_item_const(
|
self.print_item_const(
|
||||||
ident,
|
ident,
|
||||||
Some(*mutability),
|
Some(*mutability),
|
||||||
@ -165,7 +171,8 @@ impl<'a> State<'a> {
|
|||||||
self.print_use_tree(tree);
|
self.print_use_tree(tree);
|
||||||
self.word(";");
|
self.word(";");
|
||||||
}
|
}
|
||||||
ast::ItemKind::Static(box StaticItem { ty, mutability: mutbl, expr: body }) => {
|
ast::ItemKind::Static(box StaticItem { ty, safety, mutability: mutbl, expr: body }) => {
|
||||||
|
self.print_safety(*safety);
|
||||||
self.print_item_const(
|
self.print_item_const(
|
||||||
item.ident,
|
item.ident,
|
||||||
Some(*mutbl),
|
Some(*mutbl),
|
||||||
|
@ -102,7 +102,7 @@ fn intern_as_new_static<'tcx>(
|
|||||||
let feed = tcx.create_def(
|
let feed = tcx.create_def(
|
||||||
static_id,
|
static_id,
|
||||||
sym::nested,
|
sym::nested,
|
||||||
DefKind::Static { mutability: alloc.0.mutability, nested: true },
|
DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
|
||||||
);
|
);
|
||||||
tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());
|
tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());
|
||||||
|
|
||||||
|
@ -711,7 +711,9 @@ fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId)
|
|||||||
// We're not using `try_global_alloc` since dangling pointers have already been handled.
|
// We're not using `try_global_alloc` since dangling pointers have already been handled.
|
||||||
match ecx.tcx.global_alloc(alloc_id) {
|
match ecx.tcx.global_alloc(alloc_id) {
|
||||||
GlobalAlloc::Static(did) => {
|
GlobalAlloc::Static(did) => {
|
||||||
let DefKind::Static { mutability, nested } = ecx.tcx.def_kind(did) else { bug!() };
|
let DefKind::Static { safety: _, mutability, nested } = ecx.tcx.def_kind(did) else {
|
||||||
|
bug!()
|
||||||
|
};
|
||||||
if nested {
|
if nested {
|
||||||
assert!(
|
assert!(
|
||||||
ecx.memory.alloc_map.get(alloc_id).is_none(),
|
ecx.memory.alloc_map.get(alloc_id).is_none(),
|
||||||
|
@ -631,7 +631,10 @@ impl<'a> ExtCtxt<'a> {
|
|||||||
span,
|
span,
|
||||||
name,
|
name,
|
||||||
AttrVec::new(),
|
AttrVec::new(),
|
||||||
ast::ItemKind::Static(ast::StaticItem { ty, mutability, expr: Some(expr) }.into()),
|
ast::ItemKind::Static(
|
||||||
|
ast::StaticItem { ty, safety: ast::Safety::Default, mutability, expr: Some(expr) }
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,6 +620,8 @@ declare_features! (
|
|||||||
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
|
(unstable, type_changing_struct_update, "1.58.0", Some(86555)),
|
||||||
/// Allows unnamed fields of struct and union type
|
/// Allows unnamed fields of struct and union type
|
||||||
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
|
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
|
||||||
|
/// Allows unsafe on extern declarations and safety qualifiers over internal items.
|
||||||
|
(unstable, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
|
||||||
/// Allows unsized fn parameters.
|
/// Allows unsized fn parameters.
|
||||||
(unstable, unsized_fn_params, "1.49.0", Some(48055)),
|
(unstable, unsized_fn_params, "1.49.0", Some(48055)),
|
||||||
/// Allows unsized rvalues at arguments and parameters.
|
/// Allows unsized rvalues at arguments and parameters.
|
||||||
|
@ -76,6 +76,8 @@ pub enum DefKind {
|
|||||||
/// Constant generic parameter: `struct Foo<const N: usize> { ... }`
|
/// Constant generic parameter: `struct Foo<const N: usize> { ... }`
|
||||||
ConstParam,
|
ConstParam,
|
||||||
Static {
|
Static {
|
||||||
|
/// Whether it's a `unsafe static`, `safe static` (inside extern only) or just a `static`.
|
||||||
|
safety: hir::Safety,
|
||||||
/// Whether it's a `static mut` or just a `static`.
|
/// Whether it's a `static mut` or just a `static`.
|
||||||
mutability: ast::Mutability,
|
mutability: ast::Mutability,
|
||||||
/// Whether it's an anonymous static generated for nested allocations.
|
/// Whether it's an anonymous static generated for nested allocations.
|
||||||
|
@ -3475,9 +3475,9 @@ impl ForeignItem<'_> {
|
|||||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
pub enum ForeignItemKind<'hir> {
|
pub enum ForeignItemKind<'hir> {
|
||||||
/// A foreign function.
|
/// A foreign function.
|
||||||
Fn(&'hir FnDecl<'hir>, &'hir [Ident], &'hir Generics<'hir>),
|
Fn(&'hir FnDecl<'hir>, &'hir [Ident], &'hir Generics<'hir>, Safety),
|
||||||
/// A foreign static item (`static ext: u8`).
|
/// A foreign static item (`static ext: u8`).
|
||||||
Static(&'hir Ty<'hir>, Mutability),
|
Static(&'hir Ty<'hir>, Mutability, Safety),
|
||||||
/// A foreign type.
|
/// A foreign type.
|
||||||
Type,
|
Type,
|
||||||
}
|
}
|
||||||
@ -3545,7 +3545,7 @@ impl<'hir> OwnerNode<'hir> {
|
|||||||
| OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
| OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
||||||
| OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
|
| OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
|
||||||
OwnerNode::ForeignItem(ForeignItem {
|
OwnerNode::ForeignItem(ForeignItem {
|
||||||
kind: ForeignItemKind::Fn(fn_decl, _, _),
|
kind: ForeignItemKind::Fn(fn_decl, _, _, _),
|
||||||
..
|
..
|
||||||
}) => Some(fn_decl),
|
}) => Some(fn_decl),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -3728,9 +3728,9 @@ impl<'hir> Node<'hir> {
|
|||||||
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
| Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
|
||||||
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
|
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
|
||||||
Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. })
|
Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. })
|
||||||
| Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
|
| Node::ForeignItem(ForeignItem {
|
||||||
Some(fn_decl)
|
kind: ForeignItemKind::Fn(fn_decl, _, _, _), ..
|
||||||
}
|
}) => Some(fn_decl),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3813,7 +3813,7 @@ impl<'hir> Node<'hir> {
|
|||||||
pub fn generics(self) -> Option<&'hir Generics<'hir>> {
|
pub fn generics(self) -> Option<&'hir Generics<'hir>> {
|
||||||
match self {
|
match self {
|
||||||
Node::ForeignItem(ForeignItem {
|
Node::ForeignItem(ForeignItem {
|
||||||
kind: ForeignItemKind::Fn(_, _, generics), ..
|
kind: ForeignItemKind::Fn(_, _, generics, _), ..
|
||||||
})
|
})
|
||||||
| Node::TraitItem(TraitItem { generics, .. })
|
| Node::TraitItem(TraitItem { generics, .. })
|
||||||
| Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
|
| Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
|
||||||
|
@ -608,12 +608,14 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(
|
|||||||
try_visit!(visitor.visit_ident(foreign_item.ident));
|
try_visit!(visitor.visit_ident(foreign_item.ident));
|
||||||
|
|
||||||
match foreign_item.kind {
|
match foreign_item.kind {
|
||||||
ForeignItemKind::Fn(ref function_declaration, param_names, ref generics) => {
|
ForeignItemKind::Fn(ref function_declaration, param_names, ref generics, _) => {
|
||||||
try_visit!(visitor.visit_generics(generics));
|
try_visit!(visitor.visit_generics(generics));
|
||||||
try_visit!(visitor.visit_fn_decl(function_declaration));
|
try_visit!(visitor.visit_fn_decl(function_declaration));
|
||||||
walk_list!(visitor, visit_ident, param_names.iter().copied());
|
walk_list!(visitor, visit_ident, param_names.iter().copied());
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(ref typ, _) => try_visit!(visitor.visit_ty(typ)),
|
ForeignItemKind::Static(ref typ, _, _) => {
|
||||||
|
try_visit!(visitor.visit_ty(typ));
|
||||||
|
}
|
||||||
ForeignItemKind::Type => (),
|
ForeignItemKind::Type => (),
|
||||||
}
|
}
|
||||||
V::Result::output()
|
V::Result::output()
|
||||||
|
@ -801,7 +801,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||||||
|
|
||||||
let item = tcx.hir().foreign_item(item.id);
|
let item = tcx.hir().foreign_item(item.id);
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
hir::ForeignItemKind::Fn(fn_decl, _, _) => {
|
hir::ForeignItemKind::Fn(fn_decl, _, _, _) => {
|
||||||
require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
|
require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
|
||||||
}
|
}
|
||||||
hir::ForeignItemKind::Static(..) => {
|
hir::ForeignItemKind::Static(..) => {
|
||||||
|
@ -41,7 +41,8 @@ fn path_if_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> Option<String> {
|
|||||||
if let hir::ExprKind::Path(qpath) = expr.kind
|
if let hir::ExprKind::Path(qpath) = expr.kind
|
||||||
&& let hir::QPath::Resolved(_, path) = qpath
|
&& let hir::QPath::Resolved(_, path) = qpath
|
||||||
&& let hir::def::Res::Def(def_kind, _) = path.res
|
&& let hir::def::Res::Def(def_kind, _) = path.res
|
||||||
&& let hir::def::DefKind::Static { mutability: Mutability::Mut, nested: false } = def_kind
|
&& let hir::def::DefKind::Static { safety: _, mutability: Mutability::Mut, nested: false } =
|
||||||
|
def_kind
|
||||||
{
|
{
|
||||||
return Some(qpath_to_string(&tcx, &qpath));
|
return Some(qpath_to_string(&tcx, &qpath));
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ fn equate_intrinsic_type<'tcx>(
|
|||||||
let (own_counts, span) = match tcx.hir_node_by_def_id(def_id) {
|
let (own_counts, span) = match tcx.hir_node_by_def_id(def_id) {
|
||||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
|
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
|
||||||
| hir::Node::ForeignItem(hir::ForeignItem {
|
| hir::Node::ForeignItem(hir::ForeignItem {
|
||||||
kind: hir::ForeignItemKind::Fn(.., generics),
|
kind: hir::ForeignItemKind::Fn(.., generics, _),
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let own_counts = tcx.generics_of(def_id).own_counts();
|
let own_counts = tcx.generics_of(def_id).own_counts();
|
||||||
|
@ -1406,9 +1406,11 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
|
|||||||
icx.lowerer().lower_fn_ty(hir_id, header.safety, header.abi, decl, Some(generics), None)
|
icx.lowerer().lower_fn_ty(hir_id, header.safety, header.abi, decl, Some(generics), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
|
ForeignItem(&hir::ForeignItem {
|
||||||
|
kind: ForeignItemKind::Fn(fn_decl, _, _, safety), ..
|
||||||
|
}) => {
|
||||||
let abi = tcx.hir().get_foreign_abi(hir_id);
|
let abi = tcx.hir().get_foreign_abi(hir_id);
|
||||||
compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
|
compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi, safety)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
|
Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
|
||||||
@ -1780,11 +1782,12 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
|
|||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
decl: &'tcx hir::FnDecl<'tcx>,
|
decl: &'tcx hir::FnDecl<'tcx>,
|
||||||
abi: abi::Abi,
|
abi: abi::Abi,
|
||||||
|
safety: hir::Safety,
|
||||||
) -> ty::PolyFnSig<'tcx> {
|
) -> ty::PolyFnSig<'tcx> {
|
||||||
let safety = if abi == abi::Abi::RustIntrinsic {
|
let safety = if abi == abi::Abi::RustIntrinsic {
|
||||||
intrinsic_operation_unsafety(tcx, def_id)
|
intrinsic_operation_unsafety(tcx, def_id)
|
||||||
} else {
|
} else {
|
||||||
hir::Safety::Unsafe
|
safety
|
||||||
};
|
};
|
||||||
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
let hir_id = tcx.local_def_id_to_hir_id(def_id);
|
||||||
let fty =
|
let fty =
|
||||||
|
@ -603,7 +603,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||||||
|
|
||||||
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
|
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
|
||||||
match item.kind {
|
match item.kind {
|
||||||
hir::ForeignItemKind::Fn(_, _, generics) => {
|
hir::ForeignItemKind::Fn(_, _, generics, _) => {
|
||||||
self.visit_early_late(item.hir_id(), generics, |this| {
|
self.visit_early_late(item.hir_id(), generics, |this| {
|
||||||
intravisit::walk_foreign_item(this, item);
|
intravisit::walk_foreign_item(this, item);
|
||||||
})
|
})
|
||||||
|
@ -464,7 +464,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
|
|||||||
let args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
let args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
||||||
Ty::new_fn_def(tcx, def_id.to_def_id(), args)
|
Ty::new_fn_def(tcx, def_id.to_def_id(), args)
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(t, _) => icx.lower_ty(t),
|
ForeignItemKind::Static(t, _, _) => icx.lower_ty(t),
|
||||||
ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()),
|
ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ fn diagnostic_hir_wf_check<'tcx>(
|
|||||||
},
|
},
|
||||||
hir::Node::Field(field) => vec![field.ty],
|
hir::Node::Field(field) => vec![field.ty],
|
||||||
hir::Node::ForeignItem(ForeignItem {
|
hir::Node::ForeignItem(ForeignItem {
|
||||||
kind: ForeignItemKind::Static(ty, _), ..
|
kind: ForeignItemKind::Static(ty, _, _), ..
|
||||||
}) => vec![*ty],
|
}) => vec![*ty],
|
||||||
hir::Node::GenericParam(hir::GenericParam {
|
hir::Node::GenericParam(hir::GenericParam {
|
||||||
kind: hir::GenericParamKind::Type { default: Some(ty), .. },
|
kind: hir::GenericParamKind::Type { default: Some(ty), .. },
|
||||||
|
@ -345,12 +345,12 @@ impl<'a> State<'a> {
|
|||||||
self.maybe_print_comment(item.span.lo());
|
self.maybe_print_comment(item.span.lo());
|
||||||
self.print_outer_attributes(self.attrs(item.hir_id()));
|
self.print_outer_attributes(self.attrs(item.hir_id()));
|
||||||
match item.kind {
|
match item.kind {
|
||||||
hir::ForeignItemKind::Fn(decl, arg_names, generics) => {
|
hir::ForeignItemKind::Fn(decl, arg_names, generics, safety) => {
|
||||||
self.head("");
|
self.head("");
|
||||||
self.print_fn(
|
self.print_fn(
|
||||||
decl,
|
decl,
|
||||||
hir::FnHeader {
|
hir::FnHeader {
|
||||||
safety: hir::Safety::Safe,
|
safety,
|
||||||
constness: hir::Constness::NotConst,
|
constness: hir::Constness::NotConst,
|
||||||
abi: Abi::Rust,
|
abi: Abi::Rust,
|
||||||
asyncness: hir::IsAsync::NotAsync,
|
asyncness: hir::IsAsync::NotAsync,
|
||||||
@ -364,7 +364,8 @@ impl<'a> State<'a> {
|
|||||||
self.word(";");
|
self.word(";");
|
||||||
self.end() // end the outer fn box
|
self.end() // end the outer fn box
|
||||||
}
|
}
|
||||||
hir::ForeignItemKind::Static(t, m) => {
|
hir::ForeignItemKind::Static(t, m, safety) => {
|
||||||
|
self.print_safety(safety);
|
||||||
self.head("static");
|
self.head("static");
|
||||||
if m.is_mut() {
|
if m.is_mut() {
|
||||||
self.word_space("mut");
|
self.word_space("mut");
|
||||||
|
@ -462,6 +462,9 @@ lint_metavariable_wrong_operator = meta-variable repeats with different Kleene o
|
|||||||
|
|
||||||
lint_missing_fragment_specifier = missing fragment specifier
|
lint_missing_fragment_specifier = missing fragment specifier
|
||||||
|
|
||||||
|
lint_missing_unsafe_on_extern = extern blocks should be unsafe
|
||||||
|
.suggestion = needs `unsafe` before the extern keyword
|
||||||
|
|
||||||
lint_mixed_script_confusables =
|
lint_mixed_script_confusables =
|
||||||
the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
|
the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables
|
||||||
.includes_note = the usage includes {$includes}
|
.includes_note = the usage includes {$includes}
|
||||||
|
@ -202,6 +202,9 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
|
|||||||
};
|
};
|
||||||
lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag);
|
lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag);
|
||||||
}
|
}
|
||||||
|
BuiltinLintDiag::MissingUnsafeOnExtern { suggestion } => {
|
||||||
|
lints::MissingUnsafeOnExtern { suggestion }.decorate_lint(diag);
|
||||||
|
}
|
||||||
BuiltinLintDiag::SingleUseLifetime {
|
BuiltinLintDiag::SingleUseLifetime {
|
||||||
param_span,
|
param_span,
|
||||||
use_span: Some((use_span, elide)),
|
use_span: Some((use_span, elide)),
|
||||||
|
@ -2730,6 +2730,13 @@ pub enum DeprecatedWhereClauseLocationSugg {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(LintDiagnostic)]
|
||||||
|
#[diag(lint_missing_unsafe_on_extern)]
|
||||||
|
pub struct MissingUnsafeOnExtern {
|
||||||
|
#[suggestion(code = "unsafe ", applicability = "machine-applicable")]
|
||||||
|
pub suggestion: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(lint_single_use_lifetime)]
|
#[diag(lint_single_use_lifetime)]
|
||||||
pub struct SingleUseLifetime {
|
pub struct SingleUseLifetime {
|
||||||
|
@ -1741,13 +1741,13 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
|
|||||||
let abi = cx.tcx.hir().get_foreign_abi(it.hir_id());
|
let abi = cx.tcx.hir().get_foreign_abi(it.hir_id());
|
||||||
|
|
||||||
match it.kind {
|
match it.kind {
|
||||||
hir::ForeignItemKind::Fn(decl, _, _) if !vis.is_internal_abi(abi) => {
|
hir::ForeignItemKind::Fn(decl, _, _, _) if !vis.is_internal_abi(abi) => {
|
||||||
vis.check_foreign_fn(it.owner_id.def_id, decl);
|
vis.check_foreign_fn(it.owner_id.def_id, decl);
|
||||||
}
|
}
|
||||||
hir::ForeignItemKind::Static(ty, _) if !vis.is_internal_abi(abi) => {
|
hir::ForeignItemKind::Static(ty, _, _) if !vis.is_internal_abi(abi) => {
|
||||||
vis.check_foreign_static(it.owner_id, ty.span);
|
vis.check_foreign_static(it.owner_id, ty.span);
|
||||||
}
|
}
|
||||||
hir::ForeignItemKind::Fn(decl, _, _) => vis.check_fn(it.owner_id.def_id, decl),
|
hir::ForeignItemKind::Fn(decl, _, _, _) => vis.check_fn(it.owner_id.def_id, decl),
|
||||||
hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => (),
|
hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,7 @@ declare_lint_pass! {
|
|||||||
META_VARIABLE_MISUSE,
|
META_VARIABLE_MISUSE,
|
||||||
MISSING_ABI,
|
MISSING_ABI,
|
||||||
MISSING_FRAGMENT_SPECIFIER,
|
MISSING_FRAGMENT_SPECIFIER,
|
||||||
|
MISSING_UNSAFE_ON_EXTERN,
|
||||||
MUST_NOT_SUSPEND,
|
MUST_NOT_SUSPEND,
|
||||||
NAMED_ARGUMENTS_USED_POSITIONALLY,
|
NAMED_ARGUMENTS_USED_POSITIONALLY,
|
||||||
NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE,
|
NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE,
|
||||||
@ -4803,3 +4804,40 @@ declare_lint! {
|
|||||||
reference: "issue #27970 <https://github.com/rust-lang/rust/issues/27970>",
|
reference: "issue #27970 <https://github.com/rust-lang/rust/issues/27970>",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare_lint! {
|
||||||
|
/// The `missing_unsafe_on_extern` lint detects missing unsafe keyword on extern declarations.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// #![feature(unsafe_extern_blocks)]
|
||||||
|
/// #![warn(missing_unsafe_on_extern)]
|
||||||
|
/// #![allow(dead_code)]
|
||||||
|
///
|
||||||
|
/// extern "C" {
|
||||||
|
/// fn foo(_: i32);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn main() {}
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// {{produces}}
|
||||||
|
///
|
||||||
|
/// ### Explanation
|
||||||
|
///
|
||||||
|
/// Declaring extern items, even without ever using them, can cause Undefined Behavior. We
|
||||||
|
/// should consider all sources of Undefined Behavior to be unsafe.
|
||||||
|
///
|
||||||
|
/// This is a [future-incompatible] lint to transition this to a
|
||||||
|
/// hard error in the future.
|
||||||
|
///
|
||||||
|
/// [future-incompatible]: ../index.md#future-incompatible-lints
|
||||||
|
pub MISSING_UNSAFE_ON_EXTERN,
|
||||||
|
Allow,
|
||||||
|
"detects missing unsafe keyword on extern declarations",
|
||||||
|
@future_incompatible = FutureIncompatibleInfo {
|
||||||
|
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
|
||||||
|
reference: "issue #123743 <https://github.com/rust-lang/rust/issues/123743>",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -626,6 +626,9 @@ pub enum BuiltinLintDiag {
|
|||||||
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
|
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
|
||||||
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
|
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
|
||||||
DeprecatedWhereclauseLocation(Span, Option<(Span, String)>),
|
DeprecatedWhereclauseLocation(Span, Option<(Span, String)>),
|
||||||
|
MissingUnsafeOnExtern {
|
||||||
|
suggestion: Span,
|
||||||
|
},
|
||||||
SingleUseLifetime {
|
SingleUseLifetime {
|
||||||
/// Span of the parameter which declares this lifetime.
|
/// Span of the parameter which declares this lifetime.
|
||||||
param_span: Span,
|
param_span: Span,
|
||||||
|
@ -156,10 +156,14 @@ fixed_size_enum! {
|
|||||||
( Impl { of_trait: false } )
|
( Impl { of_trait: false } )
|
||||||
( Impl { of_trait: true } )
|
( Impl { of_trait: true } )
|
||||||
( Closure )
|
( Closure )
|
||||||
( Static { mutability: ast::Mutability::Not, nested: false } )
|
( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: false } )
|
||||||
( Static { mutability: ast::Mutability::Mut, nested: false } )
|
( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: false } )
|
||||||
( Static { mutability: ast::Mutability::Not, nested: true } )
|
( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Mut, nested: false } )
|
||||||
( Static { mutability: ast::Mutability::Mut, nested: true } )
|
( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Mut, nested: false } )
|
||||||
|
( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: true } )
|
||||||
|
( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: true } )
|
||||||
|
( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Mut, nested: true } )
|
||||||
|
( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Mut, nested: true } )
|
||||||
( Ctor(CtorOf::Struct, CtorKind::Fn) )
|
( Ctor(CtorOf::Struct, CtorKind::Fn) )
|
||||||
( Ctor(CtorOf::Struct, CtorKind::Const) )
|
( Ctor(CtorOf::Struct, CtorKind::Const) )
|
||||||
( Ctor(CtorOf::Variant, CtorKind::Fn) )
|
( Ctor(CtorOf::Variant, CtorKind::Fn) )
|
||||||
|
@ -305,7 +305,9 @@ impl<'hir> Map<'hir> {
|
|||||||
DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
|
DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
|
||||||
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
|
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
|
||||||
DefKind::Closure => BodyOwnerKind::Closure,
|
DefKind::Closure => BodyOwnerKind::Closure,
|
||||||
DefKind::Static { mutability, nested: false } => BodyOwnerKind::Static(mutability),
|
DefKind::Static { safety: _, mutability, nested: false } => {
|
||||||
|
BodyOwnerKind::Static(mutability)
|
||||||
|
}
|
||||||
dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
|
dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -886,7 +888,7 @@ impl<'hir> Map<'hir> {
|
|||||||
Node::Variant(variant) => named_span(variant.span, variant.ident, None),
|
Node::Variant(variant) => named_span(variant.span, variant.ident, None),
|
||||||
Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)),
|
Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)),
|
||||||
Node::ForeignItem(item) => match item.kind {
|
Node::ForeignItem(item) => match item.kind {
|
||||||
ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()),
|
ForeignItemKind::Fn(decl, _, _, _) => until_within(item.span, decl.output.span()),
|
||||||
_ => named_span(item.span, item.ident, None),
|
_ => named_span(item.span, item.ident, None),
|
||||||
},
|
},
|
||||||
Node::Ctor(_) => return self.span(self.tcx.parent_hir_id(hir_id)),
|
Node::Ctor(_) => return self.span(self.tcx.parent_hir_id(hir_id)),
|
||||||
|
@ -201,7 +201,7 @@ pub fn provide(providers: &mut Providers) {
|
|||||||
..
|
..
|
||||||
})
|
})
|
||||||
| Node::ForeignItem(&ForeignItem {
|
| Node::ForeignItem(&ForeignItem {
|
||||||
kind: ForeignItemKind::Fn(_, idents, _),
|
kind: ForeignItemKind::Fn(_, idents, _, _),
|
||||||
..
|
..
|
||||||
}) = tcx.hir_node(tcx.local_def_id_to_hir_id(def_id))
|
}) = tcx.hir_node(tcx.local_def_id_to_hir_id(def_id))
|
||||||
{
|
{
|
||||||
|
@ -559,10 +559,10 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
|
|||||||
match (kind, body.source.promoted) {
|
match (kind, body.source.promoted) {
|
||||||
(_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts
|
(_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts
|
||||||
(DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?,
|
(DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?,
|
||||||
(DefKind::Static { mutability: hir::Mutability::Not, nested: false }, _) => {
|
(DefKind::Static { safety: _, mutability: hir::Mutability::Not, nested: false }, _) => {
|
||||||
write!(w, "static ")?
|
write!(w, "static ")?
|
||||||
}
|
}
|
||||||
(DefKind::Static { mutability: hir::Mutability::Mut, nested: false }, _) => {
|
(DefKind::Static { safety: _, mutability: hir::Mutability::Mut, nested: false }, _) => {
|
||||||
write!(w, "static mut ")?
|
write!(w, "static mut ")?
|
||||||
}
|
}
|
||||||
(_, _) if is_function => write!(w, "fn ")?,
|
(_, _) if is_function => write!(w, "fn ")?,
|
||||||
|
@ -2,6 +2,7 @@ use crate::build::ExprCategory;
|
|||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
|
|
||||||
use rustc_errors::DiagArgValue;
|
use rustc_errors::DiagArgValue;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
|
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
|
||||||
use rustc_middle::mir::BorrowKind;
|
use rustc_middle::mir::BorrowKind;
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
@ -469,7 +470,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||||||
if self.tcx.is_mutable_static(def_id) {
|
if self.tcx.is_mutable_static(def_id) {
|
||||||
self.requires_unsafe(expr.span, UseOfMutableStatic);
|
self.requires_unsafe(expr.span, UseOfMutableStatic);
|
||||||
} else if self.tcx.is_foreign_item(def_id) {
|
} else if self.tcx.is_foreign_item(def_id) {
|
||||||
self.requires_unsafe(expr.span, UseOfExternStatic);
|
match self.tcx.def_kind(def_id) {
|
||||||
|
DefKind::Static { safety: hir::Safety::Safe, .. } => {}
|
||||||
|
_ => self.requires_unsafe(expr.span, UseOfExternStatic),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if self.thir[arg].ty.is_unsafe_ptr() {
|
} else if self.thir[arg].ty.is_unsafe_ptr() {
|
||||||
self.requires_unsafe(expr.span, DerefOfRawPointer);
|
self.requires_unsafe(expr.span, DerefOfRawPointer);
|
||||||
|
@ -226,10 +226,11 @@ impl<'a> Parser<'a> {
|
|||||||
self.expect_keyword(kw::Extern)?;
|
self.expect_keyword(kw::Extern)?;
|
||||||
self.parse_item_foreign_mod(attrs, safety)?
|
self.parse_item_foreign_mod(attrs, safety)?
|
||||||
} else if self.is_static_global() {
|
} else if self.is_static_global() {
|
||||||
|
let safety = self.parse_safety(Case::Sensitive);
|
||||||
// STATIC ITEM
|
// STATIC ITEM
|
||||||
self.bump(); // `static`
|
self.bump(); // `static`
|
||||||
let mutability = self.parse_mutability();
|
let mutability = self.parse_mutability();
|
||||||
let (ident, item) = self.parse_static_item(mutability)?;
|
let (ident, item) = self.parse_static_item(safety, mutability)?;
|
||||||
(ident, ItemKind::Static(Box::new(item)))
|
(ident, ItemKind::Static(Box::new(item)))
|
||||||
} else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) {
|
} else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) {
|
||||||
// CONST ITEM
|
// CONST ITEM
|
||||||
@ -952,7 +953,7 @@ impl<'a> Parser<'a> {
|
|||||||
let kind = match AssocItemKind::try_from(kind) {
|
let kind = match AssocItemKind::try_from(kind) {
|
||||||
Ok(kind) => kind,
|
Ok(kind) => kind,
|
||||||
Err(kind) => match kind {
|
Err(kind) => match kind {
|
||||||
ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
|
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
|
||||||
self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
|
self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
|
||||||
AssocItemKind::Const(Box::new(ConstItem {
|
AssocItemKind::Const(Box::new(ConstItem {
|
||||||
defaultness: Defaultness::Final,
|
defaultness: Defaultness::Final,
|
||||||
@ -1221,6 +1222,7 @@ impl<'a> Parser<'a> {
|
|||||||
ty,
|
ty,
|
||||||
mutability: Mutability::Not,
|
mutability: Mutability::Not,
|
||||||
expr,
|
expr,
|
||||||
|
safety: Safety::Default,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
_ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
|
_ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
|
||||||
@ -1258,7 +1260,10 @@ impl<'a> Parser<'a> {
|
|||||||
matches!(token.kind, token::BinOp(token::Or) | token::OrOr)
|
matches!(token.kind, token::BinOp(token::Or) | token::OrOr)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
false
|
let quals: &[Symbol] = &[kw::Unsafe, kw::Safe];
|
||||||
|
// `$qual static`
|
||||||
|
quals.iter().any(|&kw| self.check_keyword(kw))
|
||||||
|
&& self.look_ahead(1, |t| t.is_keyword(kw::Static))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1319,7 +1324,11 @@ impl<'a> Parser<'a> {
|
|||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ;
|
/// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ;
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_static_item(&mut self, mutability: Mutability) -> PResult<'a, (Ident, StaticItem)> {
|
fn parse_static_item(
|
||||||
|
&mut self,
|
||||||
|
safety: Safety,
|
||||||
|
mutability: Mutability,
|
||||||
|
) -> PResult<'a, (Ident, StaticItem)> {
|
||||||
let ident = self.parse_ident()?;
|
let ident = self.parse_ident()?;
|
||||||
|
|
||||||
if self.token.kind == TokenKind::Lt && self.may_recover() {
|
if self.token.kind == TokenKind::Lt && self.may_recover() {
|
||||||
@ -1340,7 +1349,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
self.expect_semi()?;
|
self.expect_semi()?;
|
||||||
|
|
||||||
Ok((ident, StaticItem { ty, mutability, expr }))
|
Ok((ident, StaticItem { ty, safety, mutability, expr }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a constant item with the prefix `"const"` already parsed.
|
/// Parse a constant item with the prefix `"const"` already parsed.
|
||||||
@ -2400,9 +2409,9 @@ impl<'a> Parser<'a> {
|
|||||||
// `pub` is added in case users got confused with the ordering like `async pub fn`,
|
// `pub` is added in case users got confused with the ordering like `async pub fn`,
|
||||||
// only if it wasn't preceded by `default` as `default pub` is invalid.
|
// only if it wasn't preceded by `default` as `default pub` is invalid.
|
||||||
let quals: &[Symbol] = if check_pub {
|
let quals: &[Symbol] = if check_pub {
|
||||||
&[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Extern]
|
&[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
|
||||||
} else {
|
} else {
|
||||||
&[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Extern]
|
&[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
|
||||||
};
|
};
|
||||||
self.check_keyword_case(kw::Fn, case) // Definitely an `fn`.
|
self.check_keyword_case(kw::Fn, case) // Definitely an `fn`.
|
||||||
// `$qual fn` or `$qual $qual`:
|
// `$qual fn` or `$qual $qual`:
|
||||||
@ -2537,11 +2546,27 @@ impl<'a> Parser<'a> {
|
|||||||
} else if self.check_keyword(kw::Unsafe) {
|
} else if self.check_keyword(kw::Unsafe) {
|
||||||
match safety {
|
match safety {
|
||||||
Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
|
Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)),
|
||||||
|
Safety::Safe(sp) => {
|
||||||
|
recover_safety = Safety::Unsafe(self.token.span);
|
||||||
|
Some(WrongKw::Misplaced(sp))
|
||||||
|
}
|
||||||
Safety::Default => {
|
Safety::Default => {
|
||||||
recover_safety = Safety::Unsafe(self.token.span);
|
recover_safety = Safety::Unsafe(self.token.span);
|
||||||
Some(WrongKw::Misplaced(ext_start_sp))
|
Some(WrongKw::Misplaced(ext_start_sp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if self.check_keyword(kw::Safe) {
|
||||||
|
match safety {
|
||||||
|
Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)),
|
||||||
|
Safety::Unsafe(sp) => {
|
||||||
|
recover_safety = Safety::Safe(self.token.span);
|
||||||
|
Some(WrongKw::Misplaced(sp))
|
||||||
|
}
|
||||||
|
Safety::Default => {
|
||||||
|
recover_safety = Safety::Safe(self.token.span);
|
||||||
|
Some(WrongKw::Misplaced(ext_start_sp))
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -1221,6 +1221,8 @@ impl<'a> Parser<'a> {
|
|||||||
fn parse_safety(&mut self, case: Case) -> Safety {
|
fn parse_safety(&mut self, case: Case) -> Safety {
|
||||||
if self.eat_keyword_case(kw::Unsafe, case) {
|
if self.eat_keyword_case(kw::Unsafe, case) {
|
||||||
Safety::Unsafe(self.prev_token.uninterpolated_span())
|
Safety::Unsafe(self.prev_token.uninterpolated_span())
|
||||||
|
} else if self.eat_keyword_case(kw::Safe, case) {
|
||||||
|
Safety::Safe(self.prev_token.uninterpolated_span())
|
||||||
} else {
|
} else {
|
||||||
Safety::Default
|
Safety::Default
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ use crate::{ImplTraitContext, Resolver};
|
|||||||
use rustc_ast::visit::FnKind;
|
use rustc_ast::visit::FnKind;
|
||||||
use rustc_ast::*;
|
use rustc_ast::*;
|
||||||
use rustc_expand::expand::AstFragment;
|
use rustc_expand::expand::AstFragment;
|
||||||
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
|
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_span::hygiene::LocalExpnId;
|
use rustc_span::hygiene::LocalExpnId;
|
||||||
@ -128,7 +129,11 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
|||||||
ItemKind::Union(..) => DefKind::Union,
|
ItemKind::Union(..) => DefKind::Union,
|
||||||
ItemKind::ExternCrate(..) => DefKind::ExternCrate,
|
ItemKind::ExternCrate(..) => DefKind::ExternCrate,
|
||||||
ItemKind::TyAlias(..) => DefKind::TyAlias,
|
ItemKind::TyAlias(..) => DefKind::TyAlias,
|
||||||
ItemKind::Static(s) => DefKind::Static { mutability: s.mutability, nested: false },
|
ItemKind::Static(s) => DefKind::Static {
|
||||||
|
safety: hir::Safety::Safe,
|
||||||
|
mutability: s.mutability,
|
||||||
|
nested: false,
|
||||||
|
},
|
||||||
ItemKind::Const(..) => DefKind::Const,
|
ItemKind::Const(..) => DefKind::Const,
|
||||||
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
|
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
|
||||||
ItemKind::MacroDef(..) => {
|
ItemKind::MacroDef(..) => {
|
||||||
@ -211,8 +216,18 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
|||||||
|
|
||||||
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
||||||
let def_kind = match fi.kind {
|
let def_kind = match fi.kind {
|
||||||
ForeignItemKind::Static(box StaticForeignItem { ty: _, mutability, expr: _ }) => {
|
ForeignItemKind::Static(box StaticForeignItem {
|
||||||
DefKind::Static { mutability, nested: false }
|
ty: _,
|
||||||
|
mutability,
|
||||||
|
expr: _,
|
||||||
|
safety,
|
||||||
|
}) => {
|
||||||
|
let safety = match safety {
|
||||||
|
ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe,
|
||||||
|
ast::Safety::Safe(_) => hir::Safety::Safe,
|
||||||
|
};
|
||||||
|
|
||||||
|
DefKind::Static { safety, mutability, nested: false }
|
||||||
}
|
}
|
||||||
ForeignItemKind::Fn(_) => DefKind::Fn,
|
ForeignItemKind::Fn(_) => DefKind::Fn,
|
||||||
ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
|
ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
|
||||||
|
@ -103,6 +103,7 @@ symbols! {
|
|||||||
MacroRules: "macro_rules",
|
MacroRules: "macro_rules",
|
||||||
Raw: "raw",
|
Raw: "raw",
|
||||||
Reuse: "reuse",
|
Reuse: "reuse",
|
||||||
|
Safe: "safe",
|
||||||
Union: "union",
|
Union: "union",
|
||||||
Yeet: "yeet",
|
Yeet: "yeet",
|
||||||
}
|
}
|
||||||
@ -1964,6 +1965,7 @@ symbols! {
|
|||||||
unsafe_block_in_unsafe_fn,
|
unsafe_block_in_unsafe_fn,
|
||||||
unsafe_cell,
|
unsafe_cell,
|
||||||
unsafe_cell_raw_get,
|
unsafe_cell_raw_get,
|
||||||
|
unsafe_extern_blocks,
|
||||||
unsafe_no_drop_flag,
|
unsafe_no_drop_flag,
|
||||||
unsafe_pin_internals,
|
unsafe_pin_internals,
|
||||||
unsize,
|
unsize,
|
||||||
|
@ -3075,7 +3075,9 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
|
|||||||
let def_id = item.owner_id.to_def_id();
|
let def_id = item.owner_id.to_def_id();
|
||||||
cx.with_param_env(def_id, |cx| {
|
cx.with_param_env(def_id, |cx| {
|
||||||
let kind = match item.kind {
|
let kind = match item.kind {
|
||||||
hir::ForeignItemKind::Fn(decl, names, generics) => {
|
// FIXME(missing_unsafe_on_extern) handle safety of foreign fns.
|
||||||
|
// Safety was added as part of the implementation of unsafe extern blocks PR #124482
|
||||||
|
hir::ForeignItemKind::Fn(decl, names, generics, _) => {
|
||||||
let (generics, decl) = enter_impl_trait(cx, |cx| {
|
let (generics, decl) = enter_impl_trait(cx, |cx| {
|
||||||
// NOTE: generics must be cleaned before args
|
// NOTE: generics must be cleaned before args
|
||||||
let generics = clean_generics(generics, cx);
|
let generics = clean_generics(generics, cx);
|
||||||
@ -3085,7 +3087,9 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
|
|||||||
});
|
});
|
||||||
ForeignFunctionItem(Box::new(Function { decl, generics }))
|
ForeignFunctionItem(Box::new(Function { decl, generics }))
|
||||||
}
|
}
|
||||||
hir::ForeignItemKind::Static(ty, mutability) => {
|
// FIXME(missing_unsafe_on_extern) handle safety of foreign statics.
|
||||||
|
// Safety was added as part of the implementation of unsafe extern blocks PR #124482
|
||||||
|
hir::ForeignItemKind::Static(ty, mutability, _) => {
|
||||||
ForeignStaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: None })
|
ForeignStaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: None })
|
||||||
}
|
}
|
||||||
hir::ForeignItemKind::Type => ForeignTypeItem,
|
hir::ForeignItemKind::Type => ForeignTypeItem,
|
||||||
|
@ -12,7 +12,7 @@ use rustc_errors::{Applicability, Diag, DiagMessage};
|
|||||||
use rustc_hir::def::Namespace::*;
|
use rustc_hir::def::Namespace::*;
|
||||||
use rustc_hir::def::{DefKind, Namespace, PerNS};
|
use rustc_hir::def::{DefKind, Namespace, PerNS};
|
||||||
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
|
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
|
||||||
use rustc_hir::Mutability;
|
use rustc_hir::{Mutability, Safety};
|
||||||
use rustc_middle::ty::{Ty, TyCtxt};
|
use rustc_middle::ty::{Ty, TyCtxt};
|
||||||
use rustc_middle::{bug, span_bug, ty};
|
use rustc_middle::{bug, span_bug, ty};
|
||||||
use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
|
use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
|
||||||
@ -1517,7 +1517,11 @@ impl Disambiguator {
|
|||||||
"union" => Kind(DefKind::Union),
|
"union" => Kind(DefKind::Union),
|
||||||
"module" | "mod" => Kind(DefKind::Mod),
|
"module" | "mod" => Kind(DefKind::Mod),
|
||||||
"const" | "constant" => Kind(DefKind::Const),
|
"const" | "constant" => Kind(DefKind::Const),
|
||||||
"static" => Kind(DefKind::Static { mutability: Mutability::Not, nested: false }),
|
"static" => Kind(DefKind::Static {
|
||||||
|
mutability: Mutability::Not,
|
||||||
|
nested: false,
|
||||||
|
safety: Safety::Safe,
|
||||||
|
}),
|
||||||
"function" | "fn" | "method" => Kind(DefKind::Fn),
|
"function" | "fn" | "method" => Kind(DefKind::Fn),
|
||||||
"derive" => Kind(DefKind::Macro(MacroKind::Derive)),
|
"derive" => Kind(DefKind::Macro(MacroKind::Derive)),
|
||||||
"type" => NS(Namespace::TypeNS),
|
"type" => NS(Namespace::TypeNS),
|
||||||
|
@ -308,13 +308,15 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||||||
ty: lt,
|
ty: lt,
|
||||||
mutability: lm,
|
mutability: lm,
|
||||||
expr: le,
|
expr: le,
|
||||||
|
safety: ls,
|
||||||
}),
|
}),
|
||||||
Static(box StaticItem {
|
Static(box StaticItem {
|
||||||
ty: rt,
|
ty: rt,
|
||||||
mutability: rm,
|
mutability: rm,
|
||||||
expr: re,
|
expr: re,
|
||||||
|
safety: rs,
|
||||||
}),
|
}),
|
||||||
) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
|
) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le, re),
|
||||||
(
|
(
|
||||||
Const(box ConstItem {
|
Const(box ConstItem {
|
||||||
defaultness: ld,
|
defaultness: ld,
|
||||||
@ -451,13 +453,15 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
|
|||||||
ty: lt,
|
ty: lt,
|
||||||
mutability: lm,
|
mutability: lm,
|
||||||
expr: le,
|
expr: le,
|
||||||
|
safety: ls,
|
||||||
}),
|
}),
|
||||||
Static(box StaticForeignItem {
|
Static(box StaticForeignItem {
|
||||||
ty: rt,
|
ty: rt,
|
||||||
mutability: rm,
|
mutability: rm,
|
||||||
expr: re,
|
expr: re,
|
||||||
|
safety: rs,
|
||||||
}),
|
}),
|
||||||
) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
|
) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re) && ls == rs,
|
||||||
(
|
(
|
||||||
Fn(box ast::Fn {
|
Fn(box ast::Fn {
|
||||||
defaultness: ld,
|
defaultness: ld,
|
||||||
|
@ -111,6 +111,7 @@ pub(crate) fn format_defaultness(defaultness: ast::Defaultness) -> &'static str
|
|||||||
pub(crate) fn format_safety(unsafety: ast::Safety) -> &'static str {
|
pub(crate) fn format_safety(unsafety: ast::Safety) -> &'static str {
|
||||||
match unsafety {
|
match unsafety {
|
||||||
ast::Safety::Unsafe(..) => "unsafe ",
|
ast::Safety::Unsafe(..) => "unsafe ",
|
||||||
|
ast::Safety::Safe(..) => "safe ",
|
||||||
ast::Safety::Default => "",
|
ast::Safety::Default => "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ use ::std::prelude::rust_2015::*;
|
|||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn foo(x: i32, va1: ...);
|
unsafe fn foo(x: i32, va1: ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { va2.arg::<usize>() }
|
unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { va2.arg::<usize>() }
|
||||||
|
@ -2,5 +2,5 @@
|
|||||||
//@ compile-flags: --crate-type lib
|
//@ compile-flags: --crate-type lib
|
||||||
|
|
||||||
pub async const fn x() {}
|
pub async const fn x() {}
|
||||||
//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
|
//~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const`
|
||||||
//~| ERROR functions cannot be both `const` and `async`
|
//~| ERROR functions cannot be both `const` and `async`
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
|
error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const`
|
||||||
--> $DIR/no-async-const.rs:4:11
|
--> $DIR/no-async-const.rs:4:11
|
||||||
|
|
|
|
||||||
LL | pub async const fn x() {}
|
LL | pub async const fn x() {}
|
||||||
| ------^^^^^
|
| ------^^^^^
|
||||||
| | |
|
| | |
|
||||||
| | expected one of `extern`, `fn`, or `unsafe`
|
| | expected one of `extern`, `fn`, `safe`, or `unsafe`
|
||||||
| help: `const` must come before `async`: `const async`
|
| help: `const` must come before `async`: `const async`
|
||||||
|
|
|
|
||||||
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
|
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
|
||||||
|
@ -7,11 +7,11 @@ LL | async gen fn foo() {}
|
|||||||
= help: pass `--edition 2021` to `rustc`
|
= help: pass `--edition 2021` to `rustc`
|
||||||
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
|
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
|
||||||
|
|
||||||
error: expected one of `extern`, `fn`, or `unsafe`, found `gen`
|
error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found `gen`
|
||||||
--> $DIR/async_gen_fn.rs:4:7
|
--> $DIR/async_gen_fn.rs:4:7
|
||||||
|
|
|
|
||||||
LL | async gen fn foo() {}
|
LL | async gen fn foo() {}
|
||||||
| ^^^ expected one of `extern`, `fn`, or `unsafe`
|
| ^^^ expected one of `extern`, `fn`, `safe`, or `unsafe`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
async gen fn foo() {}
|
async gen fn foo() {}
|
||||||
//[none]~^ ERROR: `async fn` is not permitted in Rust 2015
|
//[none]~^ ERROR: `async fn` is not permitted in Rust 2015
|
||||||
//[none]~| ERROR: expected one of `extern`, `fn`, or `unsafe`, found `gen`
|
//[none]~| ERROR: expected one of `extern`, `fn`, `safe`, or `unsafe`, found `gen`
|
||||||
//[e2024]~^^^ ERROR: gen blocks are experimental
|
//[e2024]~^^^ ERROR: gen blocks are experimental
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen`
|
error: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `safe`, `unsafe`, or `use`, found `gen`
|
||||||
--> $DIR/gen_fn.rs:4:1
|
--> $DIR/gen_fn.rs:4:1
|
||||||
|
|
|
|
||||||
LL | gen fn foo() {}
|
LL | gen fn foo() {}
|
||||||
| ^^^ expected one of 9 possible tokens
|
| ^^^ expected one of 10 possible tokens
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
//@[e2024] compile-flags: --edition 2024 -Zunstable-options
|
//@[e2024] compile-flags: --edition 2024 -Zunstable-options
|
||||||
|
|
||||||
gen fn foo() {}
|
gen fn foo() {}
|
||||||
//[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen`
|
//[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `safe`, `unsafe`, or `use`, found `gen`
|
||||||
//[e2024]~^^ ERROR: gen blocks are experimental
|
//[e2024]~^^ ERROR: gen blocks are experimental
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
unsafe extern "C" {
|
||||||
|
//~^ ERROR extern block cannot be declared unsafe
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,8 @@
|
|||||||
|
error: extern block cannot be declared unsafe
|
||||||
|
--> $DIR/feature-gate-unsafe-extern-blocks.rs:1:1
|
||||||
|
|
|
||||||
|
LL | unsafe extern "C" {
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
@ -2,8 +2,8 @@ fn main() {}
|
|||||||
|
|
||||||
extern "C" { //~ NOTE while parsing this item list starting here
|
extern "C" { //~ NOTE while parsing this item list starting here
|
||||||
pub pub fn foo();
|
pub pub fn foo();
|
||||||
//~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub`
|
//~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `safe`, `unsafe`, or `use`, found keyword `pub`
|
||||||
//~| NOTE expected one of 8 possible tokens
|
//~| NOTE expected one of 9 possible tokens
|
||||||
//~| HELP there is already a visibility modifier, remove one
|
//~| HELP there is already a visibility modifier, remove one
|
||||||
//~| NOTE explicit visibility first seen here
|
//~| NOTE explicit visibility first seen here
|
||||||
} //~ NOTE the item list ends here
|
} //~ NOTE the item list ends here
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub`
|
error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `safe`, `unsafe`, or `use`, found keyword `pub`
|
||||||
--> $DIR/duplicate-visibility.rs:4:9
|
--> $DIR/duplicate-visibility.rs:4:9
|
||||||
|
|
|
|
||||||
LL | extern "C" {
|
LL | extern "C" {
|
||||||
@ -6,7 +6,7 @@ LL | extern "C" {
|
|||||||
LL | pub pub fn foo();
|
LL | pub pub fn foo();
|
||||||
| ^^^
|
| ^^^
|
||||||
| |
|
| |
|
||||||
| expected one of 8 possible tokens
|
| expected one of 9 possible tokens
|
||||||
| help: there is already a visibility modifier, remove one
|
| help: there is already a visibility modifier, remove one
|
||||||
...
|
...
|
||||||
LL | }
|
LL | }
|
||||||
|
@ -44,13 +44,14 @@ fn main() {
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
async fn fe1(); //~ ERROR functions in `extern` blocks cannot have qualifiers
|
async fn fe1(); //~ ERROR functions in `extern` blocks cannot have qualifiers
|
||||||
unsafe fn fe2(); //~ ERROR functions in `extern` blocks cannot have qualifiers
|
unsafe fn fe2(); //~ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers
|
const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers
|
||||||
extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot have qualifiers
|
extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot have qualifiers
|
||||||
const async unsafe extern "C" fn fe5(); //~ ERROR functions in `extern` blocks
|
const async unsafe extern "C" fn fe5();
|
||||||
//~| ERROR functions in `extern` blocks
|
//~^ ERROR functions in `extern` blocks
|
||||||
//~| ERROR functions in `extern` blocks
|
//~| ERROR functions in `extern` blocks
|
||||||
//~| ERROR functions in `extern` blocks
|
//~| ERROR functions in `extern` blocks
|
||||||
//~| ERROR functions cannot be both `const` and `async`
|
//~| ERROR functions cannot be both `const` and `async`
|
||||||
|
//~| ERROR items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,14 +78,14 @@ LL | extern "C" {
|
|||||||
LL | async fn fe1();
|
LL | async fn fe1();
|
||||||
| ^^^^^ help: remove this qualifier
|
| ^^^^^ help: remove this qualifier
|
||||||
|
|
||||||
error: functions in `extern` blocks cannot have qualifiers
|
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
--> $DIR/fn-header-semantic-fail.rs:47:9
|
--> $DIR/fn-header-semantic-fail.rs:47:9
|
||||||
|
|
|
|
||||||
LL | extern "C" {
|
LL | extern "C" {
|
||||||
| ---------- in this `extern` block
|
| ---------- help: add unsafe to this `extern` block
|
||||||
LL | async fn fe1();
|
LL | async fn fe1();
|
||||||
LL | unsafe fn fe2();
|
LL | unsafe fn fe2();
|
||||||
| ^^^^^^ help: remove this qualifier
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: functions in `extern` blocks cannot have qualifiers
|
error: functions in `extern` blocks cannot have qualifiers
|
||||||
--> $DIR/fn-header-semantic-fail.rs:48:9
|
--> $DIR/fn-header-semantic-fail.rs:48:9
|
||||||
@ -105,14 +105,14 @@ LL | extern "C" {
|
|||||||
LL | extern "C" fn fe4();
|
LL | extern "C" fn fe4();
|
||||||
| ^^^^^^^^^^ help: remove this qualifier
|
| ^^^^^^^^^^ help: remove this qualifier
|
||||||
|
|
||||||
error: functions in `extern` blocks cannot have qualifiers
|
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
--> $DIR/fn-header-semantic-fail.rs:50:21
|
--> $DIR/fn-header-semantic-fail.rs:50:9
|
||||||
|
|
|
|
||||||
LL | extern "C" {
|
LL | extern "C" {
|
||||||
| ---------- in this `extern` block
|
| ---------- help: add unsafe to this `extern` block
|
||||||
...
|
...
|
||||||
LL | const async unsafe extern "C" fn fe5();
|
LL | const async unsafe extern "C" fn fe5();
|
||||||
| ^^^^^^ help: remove this qualifier
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: functions in `extern` blocks cannot have qualifiers
|
error: functions in `extern` blocks cannot have qualifiers
|
||||||
--> $DIR/fn-header-semantic-fail.rs:50:15
|
--> $DIR/fn-header-semantic-fail.rs:50:15
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
mod t {
|
mod t {
|
||||||
async pub fn t() {}
|
async pub fn t() {}
|
||||||
//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
|
//~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
|
||||||
//~| HELP visibility `pub` must come before `async`
|
//~| HELP visibility `pub` must come before `async`
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
error: expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
|
error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
|
||||||
--> $DIR/issue-76437-async.rs:4:11
|
--> $DIR/issue-76437-async.rs:4:11
|
||||||
|
|
|
|
||||||
LL | async pub fn t() {}
|
LL | async pub fn t() {}
|
||||||
| ------^^^
|
| ------^^^
|
||||||
| | |
|
| | |
|
||||||
| | expected one of `extern`, `fn`, or `unsafe`
|
| | expected one of `extern`, `fn`, `safe`, or `unsafe`
|
||||||
| help: visibility `pub` must come before `async`: `pub async`
|
| help: visibility `pub` must come before `async`: `pub async`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
mod t {
|
mod t {
|
||||||
const async pub fn t() {}
|
const async pub fn t() {}
|
||||||
//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
|
//~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
|
||||||
//~| HELP visibility `pub` must come before `const async`
|
//~| HELP visibility `pub` must come before `const async`
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
error: expected one of `extern`, `fn`, or `unsafe`, found keyword `pub`
|
error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
|
||||||
--> $DIR/issue-76437-const-async.rs:4:17
|
--> $DIR/issue-76437-const-async.rs:4:17
|
||||||
|
|
|
|
||||||
LL | const async pub fn t() {}
|
LL | const async pub fn t() {}
|
||||||
| ------------^^^
|
| ------------^^^
|
||||||
| | |
|
| | |
|
||||||
| | expected one of `extern`, `fn`, or `unsafe`
|
| | expected one of `extern`, `fn`, `safe`, or `unsafe`
|
||||||
| help: visibility `pub` must come before `const async`: `pub const async`
|
| help: visibility `pub` must come before `const async`: `pub const async`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
mod t {
|
mod t {
|
||||||
const pub fn t() {}
|
const pub fn t() {}
|
||||||
//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
|
//~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
|
||||||
//~| HELP visibility `pub` must come before `const`
|
//~| HELP visibility `pub` must come before `const`
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
|
error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
|
||||||
--> $DIR/issue-76437-const.rs:4:11
|
--> $DIR/issue-76437-const.rs:4:11
|
||||||
|
|
|
|
||||||
LL | const pub fn t() {}
|
LL | const pub fn t() {}
|
||||||
| ------^^^
|
| ------^^^
|
||||||
| | |
|
| | |
|
||||||
| | expected one of `async`, `extern`, `fn`, or `unsafe`
|
| | expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
|
||||||
| help: visibility `pub` must come before `const`: `pub const`
|
| help: visibility `pub` must come before `const`: `pub const`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
const pub () {}
|
const pub () {}
|
||||||
//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`
|
//~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
|
||||||
pub fn main() {}
|
pub fn main() {}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
|
error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
|
||||||
--> $DIR/issue-86895.rs:1:7
|
--> $DIR/issue-86895.rs:1:7
|
||||||
|
|
|
|
||||||
LL | const pub () {}
|
LL | const pub () {}
|
||||||
| ^^^ expected one of `async`, `extern`, `fn`, or `unsafe`
|
| ^^^ expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
// Test that even when `const` is already present, the proposed fix is to remove the second `const`
|
// Test that even when `const` is already present, the proposed fix is to remove the second `const`
|
||||||
|
|
||||||
const async const fn test() {}
|
const async const fn test() {}
|
||||||
//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
|
//~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const`
|
||||||
//~| NOTE expected one of `extern`, `fn`, or `unsafe`
|
//~| NOTE expected one of `extern`, `fn`, `safe`, or `unsafe`
|
||||||
//~| HELP `const` already used earlier, remove this one
|
//~| HELP `const` already used earlier, remove this one
|
||||||
//~| NOTE `const` first seen here
|
//~| NOTE `const` first seen here
|
||||||
//~| ERROR functions cannot be both `const` and `async`
|
//~| ERROR functions cannot be both `const` and `async`
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
|
error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const`
|
||||||
--> $DIR/const-async-const.rs:5:13
|
--> $DIR/const-async-const.rs:5:13
|
||||||
|
|
|
|
||||||
LL | const async const fn test() {}
|
LL | const async const fn test() {}
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
| |
|
| |
|
||||||
| expected one of `extern`, `fn`, or `unsafe`
|
| expected one of `extern`, `fn`, `safe`, or `unsafe`
|
||||||
| help: `const` already used earlier, remove this one
|
| help: `const` already used earlier, remove this one
|
||||||
|
|
|
|
||||||
note: `const` first seen here
|
note: `const` first seen here
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
pub const pub fn test() {}
|
pub const pub fn test() {}
|
||||||
//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
|
//~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
|
||||||
//~| NOTE expected one of `async`, `extern`, `fn`, or `unsafe`
|
//~| NOTE expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
|
||||||
//~| HELP there is already a visibility modifier, remove one
|
//~| HELP there is already a visibility modifier, remove one
|
||||||
//~| NOTE explicit visibility first seen here
|
//~| NOTE explicit visibility first seen here
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
|
error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
|
||||||
--> $DIR/issue-87694-duplicated-pub.rs:1:11
|
--> $DIR/issue-87694-duplicated-pub.rs:1:11
|
||||||
|
|
|
|
||||||
LL | pub const pub fn test() {}
|
LL | pub const pub fn test() {}
|
||||||
| ^^^
|
| ^^^
|
||||||
| |
|
| |
|
||||||
| expected one of `async`, `extern`, `fn`, or `unsafe`
|
| expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
|
||||||
| help: there is already a visibility modifier, remove one
|
| help: there is already a visibility modifier, remove one
|
||||||
|
|
|
|
||||||
note: explicit visibility first seen here
|
note: explicit visibility first seen here
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const pub fn test() {}
|
const pub fn test() {}
|
||||||
//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
|
//~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
|
||||||
//~| NOTE expected one of `async`, `extern`, `fn`, or `unsafe`
|
//~| NOTE expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
|
||||||
//~| HELP visibility `pub` must come before `const`
|
//~| HELP visibility `pub` must come before `const`
|
||||||
//~| SUGGESTION pub const
|
//~| SUGGESTION pub const
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub`
|
error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub`
|
||||||
--> $DIR/issue-87694-misplaced-pub.rs:1:7
|
--> $DIR/issue-87694-misplaced-pub.rs:1:7
|
||||||
|
|
|
|
||||||
LL | const pub fn test() {}
|
LL | const pub fn test() {}
|
||||||
| ------^^^
|
| ------^^^
|
||||||
| | |
|
| | |
|
||||||
| | expected one of `async`, `extern`, `fn`, or `unsafe`
|
| | expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`
|
||||||
| help: visibility `pub` must come before `const`: `pub const`
|
| help: visibility `pub` must come before `const`: `pub const`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
@ -3,7 +3,7 @@ extern "C" {
|
|||||||
//~^ ERROR functions in `extern` blocks cannot have qualifiers
|
//~^ ERROR functions in `extern` blocks cannot have qualifiers
|
||||||
const unsafe fn bar();
|
const unsafe fn bar();
|
||||||
//~^ ERROR functions in `extern` blocks cannot have qualifiers
|
//~^ ERROR functions in `extern` blocks cannot have qualifiers
|
||||||
//~| ERROR functions in `extern` blocks cannot have qualifiers
|
//~| ERROR items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -6,14 +6,14 @@ LL | extern "C" {
|
|||||||
LL | const fn foo();
|
LL | const fn foo();
|
||||||
| ^^^^^ help: remove this qualifier
|
| ^^^^^ help: remove this qualifier
|
||||||
|
|
||||||
error: functions in `extern` blocks cannot have qualifiers
|
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
--> $DIR/no-const-fn-in-extern-block.rs:4:11
|
--> $DIR/no-const-fn-in-extern-block.rs:4:5
|
||||||
|
|
|
|
||||||
LL | extern "C" {
|
LL | extern "C" {
|
||||||
| ---------- in this `extern` block
|
| ---------- help: add unsafe to this `extern` block
|
||||||
...
|
...
|
||||||
LL | const unsafe fn bar();
|
LL | const unsafe fn bar();
|
||||||
| ^^^^^^ help: remove this qualifier
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: functions in `extern` blocks cannot have qualifiers
|
error: functions in `extern` blocks cannot have qualifiers
|
||||||
--> $DIR/no-const-fn-in-extern-block.rs:4:5
|
--> $DIR/no-const-fn-in-extern-block.rs:4:5
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
extern "C" unsafe {
|
extern "C" unsafe {
|
||||||
//~^ ERROR expected `{`, found keyword `unsafe`
|
//~^ ERROR expected `{`, found keyword `unsafe`
|
||||||
//~| ERROR extern block cannot be declared unsafe
|
//~| ERROR extern block cannot be declared unsafe
|
||||||
unsafe fn foo();
|
unsafe fn foo();
|
||||||
//~^ ERROR functions in `extern` blocks cannot have qualifiers
|
//~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -10,14 +10,14 @@ error: extern block cannot be declared unsafe
|
|||||||
LL | extern "C" unsafe {
|
LL | extern "C" unsafe {
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: functions in `extern` blocks cannot have qualifiers
|
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
--> $DIR/unsafe-foreign-mod-2.rs:4:5
|
--> $DIR/unsafe-foreign-mod-2.rs:4:5
|
||||||
|
|
|
|
||||||
LL | extern "C" unsafe {
|
LL | extern "C" unsafe {
|
||||||
| ----------------- in this `extern` block
|
| ----------------- help: add unsafe to this `extern` block
|
||||||
...
|
...
|
||||||
LL | unsafe fn foo();
|
LL | unsafe fn foo();
|
||||||
| ^^^^^^ help: remove this qualifier
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/extern-items-unsafe.rs:14:5
|
||||||
|
|
|
||||||
|
LL | test1(TEST1);
|
||||||
|
| ^^^^^^^^^^^^ call to unsafe function
|
||||||
|
|
|
||||||
|
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||||
|
|
||||||
|
error[E0133]: use of extern static is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/extern-items-unsafe.rs:14:11
|
||||||
|
|
|
||||||
|
LL | test1(TEST1);
|
||||||
|
| ^^^^^ use of extern static
|
||||||
|
|
|
||||||
|
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0133`.
|
@ -0,0 +1,19 @@
|
|||||||
|
error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block
|
||||||
|
--> $DIR/extern-items-unsafe.rs:14:5
|
||||||
|
|
|
||||||
|
LL | test1(TEST1);
|
||||||
|
| ^^^^^^^^^^^^ call to unsafe function
|
||||||
|
|
|
||||||
|
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||||
|
|
||||||
|
error[E0133]: use of extern static is unsafe and requires unsafe block
|
||||||
|
--> $DIR/extern-items-unsafe.rs:14:11
|
||||||
|
|
|
||||||
|
LL | test1(TEST1);
|
||||||
|
| ^^^^^ use of extern static
|
||||||
|
|
|
||||||
|
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0133`.
|
@ -0,0 +1,25 @@
|
|||||||
|
//@ revisions: edition2021 edition2024
|
||||||
|
//@[edition2021] edition:2021
|
||||||
|
//@[edition2024] edition:2024
|
||||||
|
//@[edition2024] compile-flags: -Zunstable-options
|
||||||
|
|
||||||
|
#![feature(unsafe_extern_blocks)]
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
static TEST1: i32;
|
||||||
|
fn test1(i: i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test2() {
|
||||||
|
test1(TEST1);
|
||||||
|
//~^ ERROR: call to unsafe function `test1` is unsafe
|
||||||
|
//~| ERROR: use of extern static is unsafe
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test3() {
|
||||||
|
unsafe {
|
||||||
|
test1(TEST1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,12 @@
|
|||||||
|
error: extern blocks must be unsafe
|
||||||
|
--> $DIR/extern-items.rs:9:1
|
||||||
|
|
|
||||||
|
LL | / extern "C" {
|
||||||
|
LL | |
|
||||||
|
LL | | static TEST1: i32;
|
||||||
|
LL | | fn test1(i: i32);
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
20
tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
Normal file
20
tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//@ revisions: edition2021 edition2024
|
||||||
|
//@[edition2021] edition:2021
|
||||||
|
//@[edition2021] check-pass
|
||||||
|
//@[edition2024] edition:2024
|
||||||
|
//@[edition2024] compile-flags: -Zunstable-options
|
||||||
|
|
||||||
|
#![feature(unsafe_extern_blocks)]
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
//[edition2024]~^ ERROR extern blocks must be unsafe
|
||||||
|
static TEST1: i32;
|
||||||
|
fn test1(i: i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
static TEST2: i32;
|
||||||
|
fn test2(i: i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
18
tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
Normal file
18
tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//@ revisions: edition2021 edition2024
|
||||||
|
//@[edition2021] edition:2021
|
||||||
|
//@[edition2024] edition:2024
|
||||||
|
//@[edition2024] compile-flags: -Zunstable-options
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![feature(unsafe_extern_blocks)]
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
safe static TEST1: i32;
|
||||||
|
safe fn test1(i: i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test2() {
|
||||||
|
test1(TEST1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,20 @@
|
|||||||
|
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
|
--> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
|
||||||
|
|
|
||||||
|
LL | extern "C" {
|
||||||
|
| ---------- help: add unsafe to this `extern` block
|
||||||
|
LL |
|
||||||
|
LL | safe static TEST1: i32;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
|
--> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
|
||||||
|
|
|
||||||
|
LL | extern "C" {
|
||||||
|
| ---------- help: add unsafe to this `extern` block
|
||||||
|
...
|
||||||
|
LL | safe fn test1(i: i32);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
error: extern blocks must be unsafe
|
||||||
|
--> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:1
|
||||||
|
|
|
||||||
|
LL | / extern "C" {
|
||||||
|
LL | |
|
||||||
|
LL | | safe static TEST1: i32;
|
||||||
|
LL | |
|
||||||
|
LL | | safe fn test1(i: i32);
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
||||||
|
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
|
--> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
|
||||||
|
|
|
||||||
|
LL | extern "C" {
|
||||||
|
| ---------- help: add unsafe to this `extern` block
|
||||||
|
LL |
|
||||||
|
LL | safe static TEST1: i32;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
|
--> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
|
||||||
|
|
|
||||||
|
LL | extern "C" {
|
||||||
|
| ---------- help: add unsafe to this `extern` block
|
||||||
|
...
|
||||||
|
LL | safe fn test1(i: i32);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
@ -0,0 +1,20 @@
|
|||||||
|
//@ revisions: edition2021 edition2024
|
||||||
|
//@[edition2021] edition:2021
|
||||||
|
//@[edition2024] edition:2024
|
||||||
|
//@[edition2024] compile-flags: -Zunstable-options
|
||||||
|
|
||||||
|
#![feature(unsafe_extern_blocks)]
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
//[edition2024]~^ ERROR extern blocks must be unsafe
|
||||||
|
safe static TEST1: i32;
|
||||||
|
//~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
|
safe fn test1(i: i32);
|
||||||
|
//~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test2() {
|
||||||
|
test1(TEST1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,19 @@
|
|||||||
|
//@ run-rustfix
|
||||||
|
|
||||||
|
#![feature(unsafe_extern_blocks)]
|
||||||
|
#![deny(missing_unsafe_on_extern)]
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
//~^ ERROR extern blocks should be unsafe [missing_unsafe_on_extern]
|
||||||
|
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
|
||||||
|
static TEST1: i32;
|
||||||
|
fn test1(i: i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
static TEST2: i32;
|
||||||
|
fn test2(i: i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,19 @@
|
|||||||
|
//@ run-rustfix
|
||||||
|
|
||||||
|
#![feature(unsafe_extern_blocks)]
|
||||||
|
#![deny(missing_unsafe_on_extern)]
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
//~^ ERROR extern blocks should be unsafe [missing_unsafe_on_extern]
|
||||||
|
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
|
||||||
|
static TEST1: i32;
|
||||||
|
fn test1(i: i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
static TEST2: i32;
|
||||||
|
fn test2(i: i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,25 @@
|
|||||||
|
error: extern blocks should be unsafe
|
||||||
|
--> $DIR/unsafe-extern-suggestion.rs:7:1
|
||||||
|
|
|
||||||
|
LL | extern "C" {
|
||||||
|
| ^
|
||||||
|
| |
|
||||||
|
| _help: needs `unsafe` before the extern keyword: `unsafe`
|
||||||
|
| |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | | static TEST1: i32;
|
||||||
|
LL | | fn test1(i: i32);
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
|
||||||
|
= note: for more information, see issue #123743 <https://github.com/rust-lang/rust/issues/123743>
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/unsafe-extern-suggestion.rs:4:9
|
||||||
|
|
|
||||||
|
LL | #![deny(missing_unsafe_on_extern)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
@ -0,0 +1,19 @@
|
|||||||
|
error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/unsafe-items.rs:20:5
|
||||||
|
|
|
||||||
|
LL | test1(TEST1);
|
||||||
|
| ^^^^^^^^^^^^ call to unsafe function
|
||||||
|
|
|
||||||
|
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||||
|
|
||||||
|
error[E0133]: use of extern static is unsafe and requires unsafe function or block
|
||||||
|
--> $DIR/unsafe-items.rs:20:11
|
||||||
|
|
|
||||||
|
LL | test1(TEST1);
|
||||||
|
| ^^^^^ use of extern static
|
||||||
|
|
|
||||||
|
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0133`.
|
@ -0,0 +1,19 @@
|
|||||||
|
error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block
|
||||||
|
--> $DIR/unsafe-items.rs:20:5
|
||||||
|
|
|
||||||
|
LL | test1(TEST1);
|
||||||
|
| ^^^^^^^^^^^^ call to unsafe function
|
||||||
|
|
|
||||||
|
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||||
|
|
||||||
|
error[E0133]: use of extern static is unsafe and requires unsafe block
|
||||||
|
--> $DIR/unsafe-items.rs:20:11
|
||||||
|
|
|
||||||
|
LL | test1(TEST1);
|
||||||
|
| ^^^^^ use of extern static
|
||||||
|
|
|
||||||
|
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0133`.
|
25
tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
Normal file
25
tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//@ revisions: edition2021 edition2024
|
||||||
|
//@[edition2021] edition:2021
|
||||||
|
//@[edition2024] edition:2024
|
||||||
|
//@[edition2024] compile-flags: -Zunstable-options
|
||||||
|
|
||||||
|
#![feature(unsafe_extern_blocks)]
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
unsafe static TEST1: i32;
|
||||||
|
unsafe fn test1(i: i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test2() {
|
||||||
|
unsafe {
|
||||||
|
test1(TEST1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test3() {
|
||||||
|
test1(TEST1);
|
||||||
|
//~^ ERROR: call to unsafe function `test1` is unsafe
|
||||||
|
//~| ERROR: use of extern static is unsafe
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -25,6 +25,7 @@
|
|||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
#![feature(unnamed_fields)]
|
#![feature(unnamed_fields)]
|
||||||
|
#![feature(unsafe_extern_blocks)]
|
||||||
#![feature(yeet_expr)]
|
#![feature(yeet_expr)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
@ -473,8 +474,8 @@ mod items {
|
|||||||
|
|
||||||
/// ItemKind::ForeignMod
|
/// ItemKind::ForeignMod
|
||||||
mod item_foreign_mod {
|
mod item_foreign_mod {
|
||||||
extern "C++" {}
|
unsafe extern "C++" {}
|
||||||
extern {}
|
unsafe extern {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ItemKind::GlobalAsm
|
/// ItemKind::GlobalAsm
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
#![feature(unnamed_fields)]
|
#![feature(unnamed_fields)]
|
||||||
|
#![feature(unsafe_extern_blocks)]
|
||||||
#![feature(yeet_expr)]
|
#![feature(yeet_expr)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#[prelude_import]
|
#[prelude_import]
|
||||||
@ -451,8 +452,8 @@ mod items {
|
|||||||
mod item_mod { }
|
mod item_mod { }
|
||||||
/// ItemKind::ForeignMod
|
/// ItemKind::ForeignMod
|
||||||
mod item_foreign_mod {
|
mod item_foreign_mod {
|
||||||
extern "C++" {}
|
unsafe extern "C++" {}
|
||||||
extern {}
|
unsafe extern {}
|
||||||
}
|
}
|
||||||
/// ItemKind::GlobalAsm
|
/// ItemKind::GlobalAsm
|
||||||
mod item_global_asm {
|
mod item_global_asm {
|
||||||
|
Loading…
Reference in New Issue
Block a user