Only inherit const stability for methods of impl const Trait
blocks
This commit is contained in:
parent
949bdd8b79
commit
5bac1c9229
5 changed files with 74 additions and 16 deletions
|
@ -929,7 +929,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
|
||||||
if callee_is_unstable_unmarked {
|
if callee_is_unstable_unmarked {
|
||||||
trace!("callee_is_unstable_unmarked");
|
trace!("callee_is_unstable_unmarked");
|
||||||
// We do not use `const` modifiers for intrinsic "functions", as intrinsics are
|
// We do not use `const` modifiers for intrinsic "functions", as intrinsics are
|
||||||
// `extern` funtions, and these have way to get marked `const`. So instead we
|
// `extern` funtions, and these have no way to get marked `const`. So instead we
|
||||||
// use `rustc_const_(un)stable` attributes to mean that the intrinsic is `const`
|
// use `rustc_const_(un)stable` attributes to mean that the intrinsic is `const`
|
||||||
if self.ccx.is_const_stable_const_fn() || is_intrinsic {
|
if self.ccx.is_const_stable_const_fn() || is_intrinsic {
|
||||||
self.check_op(ops::FnCallUnstable(callee, None));
|
self.check_op(ops::FnCallUnstable(callee, None));
|
||||||
|
|
|
@ -55,6 +55,21 @@ impl InheritDeprecation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether to inherit const stability flags for nested items. In most cases, we do not want to
|
||||||
|
/// inherit const stability: just because an enclosing `fn` is const-stable does not mean
|
||||||
|
/// all `extern` imports declared in it should be const-stable! However, trait methods
|
||||||
|
/// inherit const stability attributes from their parent and do not have their own.
|
||||||
|
enum InheritConstStability {
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InheritConstStability {
|
||||||
|
fn yes(&self) -> bool {
|
||||||
|
matches!(self, InheritConstStability::Yes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// A private tree-walker for producing an Index.
|
// A private tree-walker for producing an Index.
|
||||||
struct Annotator<'a, 'tcx> {
|
struct Annotator<'a, 'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
@ -75,6 +90,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||||
item_sp: Span,
|
item_sp: Span,
|
||||||
kind: AnnotationKind,
|
kind: AnnotationKind,
|
||||||
inherit_deprecation: InheritDeprecation,
|
inherit_deprecation: InheritDeprecation,
|
||||||
|
inherit_const_stability: InheritConstStability,
|
||||||
visit_children: F,
|
visit_children: F,
|
||||||
) where
|
) where
|
||||||
F: FnOnce(&mut Self),
|
F: FnOnce(&mut Self),
|
||||||
|
@ -140,6 +156,8 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||||
const_stab
|
const_stab
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// `impl const Trait for Type` items forward their const stability to their
|
||||||
|
// immediate children.
|
||||||
if const_stab.is_none() {
|
if const_stab.is_none() {
|
||||||
debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab);
|
debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab);
|
||||||
if let Some(parent) = self.parent_const_stab {
|
if let Some(parent) = self.parent_const_stab {
|
||||||
|
@ -228,7 +246,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||||
self.recurse_with_stability_attrs(
|
self.recurse_with_stability_attrs(
|
||||||
depr.map(|(d, _)| DeprecationEntry::local(d, hir_id)),
|
depr.map(|(d, _)| DeprecationEntry::local(d, hir_id)),
|
||||||
stab,
|
stab,
|
||||||
const_stab,
|
if inherit_const_stability.yes() { const_stab } else { None },
|
||||||
visit_children,
|
visit_children,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -325,6 +343,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
|
fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
|
||||||
let orig_in_trait_impl = self.in_trait_impl;
|
let orig_in_trait_impl = self.in_trait_impl;
|
||||||
let mut kind = AnnotationKind::Required;
|
let mut kind = AnnotationKind::Required;
|
||||||
|
let mut const_stab_inherit = InheritConstStability::No;
|
||||||
match i.kind {
|
match i.kind {
|
||||||
// Inherent impls and foreign modules serve only as containers for other items,
|
// Inherent impls and foreign modules serve only as containers for other items,
|
||||||
// they don't have their own stability. They still can be annotated as unstable
|
// they don't have their own stability. They still can be annotated as unstable
|
||||||
|
@ -338,6 +357,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => {
|
hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => {
|
||||||
self.in_trait_impl = true;
|
self.in_trait_impl = true;
|
||||||
kind = AnnotationKind::DeprecationProhibited;
|
kind = AnnotationKind::DeprecationProhibited;
|
||||||
|
const_stab_inherit = InheritConstStability::Yes;
|
||||||
}
|
}
|
||||||
hir::ItemKind::Struct(ref sd, _) => {
|
hir::ItemKind::Struct(ref sd, _) => {
|
||||||
if let Some(ctor_hir_id) = sd.ctor_hir_id() {
|
if let Some(ctor_hir_id) = sd.ctor_hir_id() {
|
||||||
|
@ -347,6 +367,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
i.span,
|
i.span,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
|
InheritConstStability::No,
|
||||||
|_| {},
|
|_| {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -354,9 +375,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.annotate(i.hir_id, &i.attrs, i.span, kind, InheritDeprecation::Yes, |v| {
|
self.annotate(
|
||||||
intravisit::walk_item(v, i)
|
i.hir_id,
|
||||||
});
|
&i.attrs,
|
||||||
|
i.span,
|
||||||
|
kind,
|
||||||
|
InheritDeprecation::Yes,
|
||||||
|
const_stab_inherit,
|
||||||
|
|v| intravisit::walk_item(v, i),
|
||||||
|
);
|
||||||
self.in_trait_impl = orig_in_trait_impl;
|
self.in_trait_impl = orig_in_trait_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,6 +394,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
ti.span,
|
ti.span,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
|
InheritConstStability::No,
|
||||||
|v| {
|
|v| {
|
||||||
intravisit::walk_trait_item(v, ti);
|
intravisit::walk_trait_item(v, ti);
|
||||||
},
|
},
|
||||||
|
@ -376,9 +404,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
|
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
|
||||||
let kind =
|
let kind =
|
||||||
if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required };
|
if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required };
|
||||||
self.annotate(ii.hir_id, &ii.attrs, ii.span, kind, InheritDeprecation::Yes, |v| {
|
self.annotate(
|
||||||
|
ii.hir_id,
|
||||||
|
&ii.attrs,
|
||||||
|
ii.span,
|
||||||
|
kind,
|
||||||
|
InheritDeprecation::Yes,
|
||||||
|
InheritConstStability::No,
|
||||||
|
|v| {
|
||||||
intravisit::walk_impl_item(v, ii);
|
intravisit::walk_impl_item(v, ii);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics<'tcx>, item_id: HirId) {
|
fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics<'tcx>, item_id: HirId) {
|
||||||
|
@ -388,6 +424,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
var.span,
|
var.span,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
|
InheritConstStability::No,
|
||||||
|v| {
|
|v| {
|
||||||
if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
|
if let Some(ctor_hir_id) = var.data.ctor_hir_id() {
|
||||||
v.annotate(
|
v.annotate(
|
||||||
|
@ -396,6 +433,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
var.span,
|
var.span,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
|
InheritConstStability::No,
|
||||||
|_| {},
|
|_| {},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -412,6 +450,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
s.span,
|
s.span,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
|
InheritConstStability::No,
|
||||||
|v| {
|
|v| {
|
||||||
intravisit::walk_struct_field(v, s);
|
intravisit::walk_struct_field(v, s);
|
||||||
},
|
},
|
||||||
|
@ -425,6 +464,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
i.span,
|
i.span,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
|
InheritConstStability::No,
|
||||||
|v| {
|
|v| {
|
||||||
intravisit::walk_foreign_item(v, i);
|
intravisit::walk_foreign_item(v, i);
|
||||||
},
|
},
|
||||||
|
@ -438,6 +478,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
md.span,
|
md.span,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
|
InheritConstStability::No,
|
||||||
|_| {},
|
|_| {},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -451,9 +492,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
||||||
_ => AnnotationKind::Prohibited,
|
_ => AnnotationKind::Prohibited,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.annotate(p.hir_id, &p.attrs, p.span, kind, InheritDeprecation::No, |v| {
|
self.annotate(
|
||||||
|
p.hir_id,
|
||||||
|
&p.attrs,
|
||||||
|
p.span,
|
||||||
|
kind,
|
||||||
|
InheritDeprecation::No,
|
||||||
|
InheritConstStability::No,
|
||||||
|
|v| {
|
||||||
intravisit::walk_generic_param(v, p);
|
intravisit::walk_generic_param(v, p);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,6 +667,7 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
|
||||||
krate.item.span,
|
krate.item.span,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
|
InheritConstStability::No,
|
||||||
|v| intravisit::walk_crate(v, krate),
|
|v| intravisit::walk_crate(v, krate),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1842,6 +1842,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
|
pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||||
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1926,6 +1927,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||||
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// check-pass
|
|
||||||
|
|
||||||
#![feature(intrinsics, staged_api, const_intrinsic_copy)]
|
#![feature(intrinsics, staged_api, const_intrinsic_copy)]
|
||||||
#![stable(feature = "core", since = "1.6.0")]
|
#![stable(feature = "core", since = "1.6.0")]
|
||||||
|
|
||||||
|
@ -7,14 +5,13 @@
|
||||||
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
||||||
|
// Const stability attributes are not inherited from parent items.
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Even though the `copy` intrinsic lacks stability attributes, this works, because it
|
|
||||||
// inherits its stability attributes from its parent. That includes `rustc_const_(un)stable`
|
|
||||||
// attributes.
|
|
||||||
unsafe { copy(src, dst, count) }
|
unsafe { copy(src, dst, count) }
|
||||||
|
//~^ ERROR calls in constant functions are limited to constant functions
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
9
src/test/ui/consts/intrinsic_without_const_stab.stderr
Normal file
9
src/test/ui/consts/intrinsic_without_const_stab.stderr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
|
--> $DIR/intrinsic_without_const_stab.rs:13:14
|
||||||
|
|
|
||||||
|
LL | unsafe { copy(src, dst, count) }
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0015`.
|
Loading…
Add table
Add a link
Reference in a new issue