Add a diagnostic attribute for special casing const bound errors for non-const impls
This commit is contained in:
parent
1223f5c168
commit
9218298caa
24 changed files with 319 additions and 27 deletions
|
|
@ -1576,9 +1576,10 @@ pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>>
|
|||
map
|
||||
});
|
||||
|
||||
pub fn is_stable_diagnostic_attribute(sym: Symbol, _features: &Features) -> bool {
|
||||
pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool {
|
||||
match sym {
|
||||
sym::on_unimplemented | sym::do_not_recommend => true,
|
||||
sym::on_const => features.diagnostic_on_const(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -485,6 +485,8 @@ declare_features! (
|
|||
(incomplete, deref_patterns, "1.79.0", Some(87121)),
|
||||
/// Allows deriving the From trait on single-field structs.
|
||||
(unstable, derive_from, "1.91.0", Some(144889)),
|
||||
/// Allows giving non-const impls custom diagnostic messages if attempted to be used as const
|
||||
(unstable, diagnostic_on_const, "CURRENT_RUSTC_VERSION", Some(143874)),
|
||||
/// Allows `#[doc(cfg(...))]`.
|
||||
(unstable, doc_cfg, "1.21.0", Some(43781)),
|
||||
/// Allows `#[doc(masked)]`.
|
||||
|
|
|
|||
|
|
@ -802,6 +802,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
|
|||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
tcx.ensure_ok().associated_items(def_id);
|
||||
check_diagnostic_attrs(tcx, def_id);
|
||||
if of_trait {
|
||||
let impl_trait_header = tcx.impl_trait_header(def_id);
|
||||
res = res.and(
|
||||
|
|
@ -824,7 +825,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
|
|||
tcx.ensure_ok().predicates_of(def_id);
|
||||
tcx.ensure_ok().associated_items(def_id);
|
||||
let assoc_items = tcx.associated_items(def_id);
|
||||
check_on_unimplemented(tcx, def_id);
|
||||
check_diagnostic_attrs(tcx, def_id);
|
||||
|
||||
for &assoc_item in assoc_items.in_definition_order() {
|
||||
match assoc_item.kind {
|
||||
|
|
@ -1112,7 +1113,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
|
|||
})
|
||||
}
|
||||
|
||||
pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
pub(super) fn check_diagnostic_attrs(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
// an error would be reported if this fails.
|
||||
let _ = OnUnimplementedDirective::of_item(tcx, def_id.to_def_id());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,9 @@ passes_deprecated_annotation_has_no_effect =
|
|||
passes_deprecated_attribute =
|
||||
deprecated attribute must be paired with either stable or unstable attribute
|
||||
|
||||
passes_diagnostic_diagnostic_on_const_only_for_trait_impls =
|
||||
`#[diagnostic::on_const]` can only be applied to trait impls
|
||||
|
||||
passes_diagnostic_diagnostic_on_unimplemented_only_for_traits =
|
||||
`#[diagnostic::on_unimplemented]` can only be applied to trait definitions
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ use rustc_hir::def::DefKind;
|
|||
use rustc_hir::def_id::LocalModDefId;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{
|
||||
self as hir, Attribute, CRATE_HIR_ID, CRATE_OWNER_ID, FnSig, ForeignItem, HirId, Item,
|
||||
ItemKind, MethodKind, PartialConstStability, Safety, Stability, StabilityLevel, Target,
|
||||
self as hir, Attribute, CRATE_HIR_ID, CRATE_OWNER_ID, Constness, FnSig, ForeignItem, HirId,
|
||||
Item, ItemKind, MethodKind, PartialConstStability, Safety, Stability, StabilityLevel, Target,
|
||||
TraitItem, find_attr,
|
||||
};
|
||||
use rustc_macros::LintDiagnostic;
|
||||
|
|
@ -55,6 +55,10 @@ use crate::{errors, fluent_generated as fluent};
|
|||
#[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)]
|
||||
struct DiagnosticOnUnimplementedOnlyForTraits;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes_diagnostic_diagnostic_on_const_only_for_trait_impls)]
|
||||
struct DiagnosticOnConstOnlyForTraitImpls;
|
||||
|
||||
fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target {
|
||||
match impl_item.kind {
|
||||
hir::ImplItemKind::Const(..) => Target::AssocConst,
|
||||
|
|
@ -293,6 +297,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
[sym::diagnostic, sym::on_unimplemented, ..] => {
|
||||
self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target)
|
||||
}
|
||||
[sym::diagnostic, sym::on_const, ..] => {
|
||||
self.check_diagnostic_on_const(attr.span(), hir_id, target, item)
|
||||
}
|
||||
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
|
||||
[sym::doc, ..] => self.check_doc_attrs(
|
||||
attr,
|
||||
|
|
@ -516,6 +523,31 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Checks if `#[diagnostic::on_const]` is applied to a trait impl
|
||||
fn check_diagnostic_on_const(
|
||||
&self,
|
||||
attr_span: Span,
|
||||
hir_id: HirId,
|
||||
target: Target,
|
||||
item: Option<ItemLike<'_>>,
|
||||
) {
|
||||
if matches!(target, Target::Impl { of_trait: true }) {
|
||||
match item.unwrap() {
|
||||
ItemLike::Item(it) => match it.expect_impl().constness {
|
||||
Constness::Const => {}
|
||||
Constness::NotConst => return,
|
||||
},
|
||||
ItemLike::ForeignItem => {}
|
||||
}
|
||||
}
|
||||
self.tcx.emit_node_span_lint(
|
||||
MISPLACED_DIAGNOSTIC_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr_span,
|
||||
DiagnosticOnConstOnlyForTraitImpls,
|
||||
);
|
||||
}
|
||||
|
||||
/// Checks if an `#[inline]` is applied to a function or a closure.
|
||||
fn check_inline(&self, hir_id: HirId, attr_span: Span, kind: &InlineAttr, target: Target) {
|
||||
match target {
|
||||
|
|
|
|||
|
|
@ -690,10 +690,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
|
||||
&& let [namespace, attribute, ..] = &*path.segments
|
||||
&& namespace.ident.name == sym::diagnostic
|
||||
&& ![sym::on_unimplemented, sym::do_not_recommend].contains(&attribute.ident.name)
|
||||
&& ![sym::on_unimplemented, sym::do_not_recommend, sym::on_const]
|
||||
.contains(&attribute.ident.name)
|
||||
{
|
||||
let typo_name = find_best_match_for_name(
|
||||
&[sym::on_unimplemented, sym::do_not_recommend],
|
||||
&[sym::on_unimplemented, sym::do_not_recommend, sym::on_const],
|
||||
attribute.ident.name,
|
||||
Some(5),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -878,6 +878,7 @@ symbols! {
|
|||
destructuring_assignment,
|
||||
diagnostic,
|
||||
diagnostic_namespace,
|
||||
diagnostic_on_const,
|
||||
dialect,
|
||||
direct,
|
||||
discriminant_kind,
|
||||
|
|
@ -1593,6 +1594,7 @@ symbols! {
|
|||
old_name,
|
||||
omit_gdb_pretty_printer_section,
|
||||
on,
|
||||
on_const,
|
||||
on_unimplemented,
|
||||
opaque,
|
||||
opaque_module_name_placeholder: "<opaque>",
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ use super::{
|
|||
};
|
||||
use crate::error_reporting::TypeErrCtxt;
|
||||
use crate::error_reporting::infer::TyCategory;
|
||||
use crate::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
|
||||
use crate::error_reporting::traits::report_dyn_incompatibility;
|
||||
use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, CoroClosureNotFn};
|
||||
use crate::infer::{self, InferCtxt, InferCtxtExt as _};
|
||||
|
|
@ -586,7 +587,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
|
||||
self.report_host_effect_error(bound_predicate.rebind(predicate), obligation.param_env, span)
|
||||
self.report_host_effect_error(bound_predicate.rebind(predicate), &obligation, span)
|
||||
}
|
||||
|
||||
ty::PredicateKind::Subtype(predicate) => {
|
||||
|
|
@ -807,20 +808,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
fn report_host_effect_error(
|
||||
&self,
|
||||
predicate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
main_obligation: &PredicateObligation<'tcx>,
|
||||
span: Span,
|
||||
) -> Diag<'a> {
|
||||
// FIXME(const_trait_impl): We should recompute the predicate with `[const]`
|
||||
// if it's `const`, and if it holds, explain that this bound only
|
||||
// *conditionally* holds. If that fails, we should also do selection
|
||||
// to drill this down to an impl or built-in source, so we can
|
||||
// point at it and explain that while the trait *is* implemented,
|
||||
// that implementation is not const.
|
||||
// *conditionally* holds.
|
||||
let trait_ref = predicate.map_bound(|predicate| ty::TraitPredicate {
|
||||
trait_ref: predicate.trait_ref,
|
||||
polarity: ty::PredicatePolarity::Positive,
|
||||
});
|
||||
let mut file = None;
|
||||
|
||||
let err_msg = self.get_standard_error_message(
|
||||
trait_ref,
|
||||
None,
|
||||
|
|
@ -834,7 +833,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
let obligation = Obligation::new(
|
||||
self.tcx,
|
||||
ObligationCause::dummy(),
|
||||
param_env,
|
||||
main_obligation.param_env,
|
||||
trait_ref,
|
||||
);
|
||||
if !self.predicate_may_hold(&obligation) {
|
||||
|
|
@ -867,6 +866,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
impl_span,
|
||||
format!("trait `{trait_name}` is implemented but not `const`"),
|
||||
);
|
||||
|
||||
let (condition_options, format_args) = self.on_unimplemented_components(
|
||||
trait_ref,
|
||||
main_obligation,
|
||||
diag.long_ty_path(),
|
||||
);
|
||||
|
||||
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, impl_did)
|
||||
{
|
||||
let note = command.evaluate(
|
||||
self.tcx,
|
||||
predicate.skip_binder().trait_ref,
|
||||
&condition_options,
|
||||
&format_args,
|
||||
);
|
||||
let OnUnimplementedNote {
|
||||
message,
|
||||
label,
|
||||
notes,
|
||||
parent_label,
|
||||
append_const_msg: _,
|
||||
} = note;
|
||||
|
||||
if let Some(message) = message {
|
||||
diag.primary_message(message);
|
||||
}
|
||||
if let Some(label) = label {
|
||||
diag.span_label(impl_span, label);
|
||||
}
|
||||
for note in notes {
|
||||
diag.note(note);
|
||||
}
|
||||
if let Some(parent_label) = parent_label {
|
||||
diag.span_label(impl_span, parent_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit};
|
|||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::{AttrArgs, Attribute};
|
||||
use rustc_macros::LintDiagnostic;
|
||||
|
|
@ -103,7 +104,27 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
if trait_pred.polarity() != ty::PredicatePolarity::Positive {
|
||||
return OnUnimplementedNote::default();
|
||||
}
|
||||
let (condition_options, format_args) =
|
||||
self.on_unimplemented_components(trait_pred, obligation, long_ty_path);
|
||||
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, trait_pred.def_id())
|
||||
{
|
||||
command.evaluate(
|
||||
self.tcx,
|
||||
trait_pred.skip_binder().trait_ref,
|
||||
&condition_options,
|
||||
&format_args,
|
||||
)
|
||||
} else {
|
||||
OnUnimplementedNote::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn on_unimplemented_components(
|
||||
&self,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
long_ty_path: &mut Option<PathBuf>,
|
||||
) -> (ConditionOptions, FormatArgs<'tcx>) {
|
||||
let (def_id, args) = self
|
||||
.impl_similar_to(trait_pred, obligation)
|
||||
.unwrap_or_else(|| (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args));
|
||||
|
|
@ -293,12 +314,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
.collect();
|
||||
|
||||
let format_args = FormatArgs { this, trait_sugared, generic_args, item_context };
|
||||
|
||||
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) {
|
||||
command.evaluate(self.tcx, trait_pred.trait_ref, &condition_options, &format_args)
|
||||
} else {
|
||||
OnUnimplementedNote::default()
|
||||
}
|
||||
(condition_options, format_args)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -325,7 +341,7 @@ pub struct OnUnimplementedDirective {
|
|||
}
|
||||
|
||||
/// For the `#[rustc_on_unimplemented]` attribute
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct OnUnimplementedNote {
|
||||
pub message: Option<String>,
|
||||
pub label: Option<String>,
|
||||
|
|
@ -562,17 +578,21 @@ impl<'tcx> OnUnimplementedDirective {
|
|||
}
|
||||
|
||||
pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<Option<Self>, ErrorGuaranteed> {
|
||||
if !tcx.is_trait(item_def_id) {
|
||||
let attr = if tcx.is_trait(item_def_id) {
|
||||
sym::on_unimplemented
|
||||
} else if let DefKind::Impl { of_trait: true } = tcx.def_kind(item_def_id) {
|
||||
sym::on_const
|
||||
} else {
|
||||
// It could be a trait_alias (`trait MyTrait = SomeOtherTrait`)
|
||||
// or an implementation (`impl MyTrait for Foo {}`)
|
||||
//
|
||||
// We don't support those.
|
||||
return Ok(None);
|
||||
}
|
||||
};
|
||||
if let Some(attr) = tcx.get_attr(item_def_id, sym::rustc_on_unimplemented) {
|
||||
return Self::parse_attribute(attr, false, tcx, item_def_id);
|
||||
} else {
|
||||
tcx.get_attrs_by_path(item_def_id, &[sym::diagnostic, sym::on_unimplemented])
|
||||
tcx.get_attrs_by_path(item_def_id, &[sym::diagnostic, attr])
|
||||
.filter_map(|attr| Self::parse_attribute(attr, true, tcx, item_def_id).transpose())
|
||||
.try_fold(None, |aggr: Option<Self>, directive| {
|
||||
let directive = directive?;
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@
|
|||
#![feature(decl_macro)]
|
||||
#![feature(deprecated_suggestion)]
|
||||
#![feature(derive_const)]
|
||||
#![feature(diagnostic_on_const)]
|
||||
#![feature(doc_cfg)]
|
||||
#![feature(doc_notable_trait)]
|
||||
#![feature(extern_types)]
|
||||
|
|
|
|||
|
|
@ -1567,6 +1567,10 @@ impl<T, const N: usize> *const [T; N] {
|
|||
|
||||
/// Pointer equality is by address, as produced by the [`<*const T>::addr`](pointer::addr) method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<T: PointeeSized> PartialEq for *const T {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
|
|
@ -1577,10 +1581,18 @@ impl<T: PointeeSized> PartialEq for *const T {
|
|||
|
||||
/// Pointer equality is an equivalence relation.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<T: PointeeSized> Eq for *const T {}
|
||||
|
||||
/// Pointer comparison is by address, as produced by the `[`<*const T>::addr`](pointer::addr)` method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<T: PointeeSized> Ord for *const T {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
|
|
@ -1597,6 +1609,10 @@ impl<T: PointeeSized> Ord for *const T {
|
|||
|
||||
/// Pointer comparison is by address, as produced by the `[`<*const T>::addr`](pointer::addr)` method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<T: PointeeSized> PartialOrd for *const T {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
|
|
|
|||
|
|
@ -2520,6 +2520,10 @@ pub fn hash<T: PointeeSized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
|
|||
}
|
||||
|
||||
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<F: FnPtr> PartialEq for F {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
|
|
@ -2527,9 +2531,17 @@ impl<F: FnPtr> PartialEq for F {
|
|||
}
|
||||
}
|
||||
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<F: FnPtr> Eq for F {}
|
||||
|
||||
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<F: FnPtr> PartialOrd for F {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
|
|
@ -2537,6 +2549,10 @@ impl<F: FnPtr> PartialOrd for F {
|
|||
}
|
||||
}
|
||||
#[stable(feature = "fnptr_impls", since = "1.4.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<F: FnPtr> Ord for F {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
|
|
|
|||
|
|
@ -2000,6 +2000,10 @@ impl<T, const N: usize> *mut [T; N] {
|
|||
|
||||
/// Pointer equality is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<T: PointeeSized> PartialEq for *mut T {
|
||||
#[inline(always)]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
|
|
@ -2010,10 +2014,18 @@ impl<T: PointeeSized> PartialEq for *mut T {
|
|||
|
||||
/// Pointer equality is an equivalence relation.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<T: PointeeSized> Eq for *mut T {}
|
||||
|
||||
/// Pointer comparison is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<T: PointeeSized> Ord for *mut T {
|
||||
#[inline]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
|
|
@ -2030,6 +2042,10 @@ impl<T: PointeeSized> Ord for *mut T {
|
|||
|
||||
/// Pointer comparison is by address, as produced by the [`<*mut T>::addr`](pointer::addr) method.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[diagnostic::on_const(
|
||||
message = "pointers cannot be reliably compared during const eval",
|
||||
note = "see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information"
|
||||
)]
|
||||
impl<T: PointeeSized> PartialOrd for *mut T {
|
||||
#[inline(always)]
|
||||
#[allow(ambiguous_wide_pointer_comparisons)]
|
||||
|
|
|
|||
23
tests/ui/consts/const-eval/const_raw_ptr_ops.gated.stderr
Normal file
23
tests/ui/consts/const-eval/const_raw_ptr_ops.gated.stderr
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
error[E0277]: pointers cannot be reliably compared during const eval
|
||||
--> $DIR/const_raw_ptr_ops.rs:7:26
|
||||
|
|
||||
LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: trait `PartialEq` is implemented but not `const`
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
||||
|
||||
error[E0277]: pointers cannot be reliably compared during const eval
|
||||
--> $DIR/const_raw_ptr_ops.rs:9:27
|
||||
|
|
||||
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: trait `PartialEq` is implemented but not `const`
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
//@revisions: stable gated
|
||||
#![cfg_attr(gated, feature(const_trait_impl))]
|
||||
|
||||
fn main() {}
|
||||
|
||||
// unconst and bad, will thus error in miri
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: pointers cannot be reliably compared during const eval
|
||||
--> $DIR/const_raw_ptr_ops.rs:4:26
|
||||
--> $DIR/const_raw_ptr_ops.rs:7:26
|
||||
|
|
||||
LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -7,7 +7,7 @@ LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
|
|||
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
||||
|
||||
error: pointers cannot be reliably compared during const eval
|
||||
--> $DIR/const_raw_ptr_ops.rs:6:27
|
||||
--> $DIR/const_raw_ptr_ops.rs:9:27
|
||||
|
|
||||
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
error[E0277]: pointers cannot be reliably compared during const eval
|
||||
--> $DIR/different-fn-ptr-binders-during-ctfe.rs:5:5
|
||||
|
|
||||
LL | x == y
|
||||
| ^^^^^^
|
||||
|
|
||||
note: trait `PartialEq` is implemented but not `const`
|
||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
//@revisions: stable gated
|
||||
#![cfg_attr(gated, feature(const_trait_impl))]
|
||||
|
||||
const fn cmp(x: fn(&'static ()), y: for<'a> fn(&'a ())) -> bool {
|
||||
x == y
|
||||
//~^ ERROR pointers cannot be reliably compared during const eval
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: pointers cannot be reliably compared during const eval
|
||||
--> $DIR/different-fn-ptr-binders-during-ctfe.rs:2:5
|
||||
--> $DIR/different-fn-ptr-binders-during-ctfe.rs:5:5
|
||||
|
|
||||
LL | x == y
|
||||
| ^^^^^^
|
||||
32
tests/ui/diagnostic_namespace/on_const/misplaced_attr.rs
Normal file
32
tests/ui/diagnostic_namespace/on_const/misplaced_attr.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#![feature(const_trait_impl, const_cmp)]
|
||||
#![deny(misplaced_diagnostic_attributes)]
|
||||
|
||||
#[diagnostic::on_const(message = "tadaa", note = "boing")]
|
||||
//~^ ERROR: `#[diagnostic::on_const]` can only be applied to trait impls
|
||||
pub struct Foo;
|
||||
|
||||
#[diagnostic::on_const(message = "tadaa", note = "boing")]
|
||||
//~^ ERROR: `#[diagnostic::on_const]` can only be applied to trait impls
|
||||
impl const PartialEq for Foo {
|
||||
fn eq(&self, _other: &Foo) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[diagnostic::on_const(message = "tadaa", note = "boing")]
|
||||
//~^ ERROR: `#[diagnostic::on_const]` can only be applied to trait impls
|
||||
impl Foo {
|
||||
fn eq(&self, _other: &Foo) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Foo {
|
||||
#[diagnostic::on_const(message = "tadaa", note = "boing")]
|
||||
//~^ ERROR: `#[diagnostic::on_const]` can only be applied to trait impls
|
||||
fn partial_cmp(&self, other: &Foo) -> Option<std::cmp::Ordering> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
32
tests/ui/diagnostic_namespace/on_const/misplaced_attr.stderr
Normal file
32
tests/ui/diagnostic_namespace/on_const/misplaced_attr.stderr
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
error: `#[diagnostic::on_const]` can only be applied to trait impls
|
||||
--> $DIR/misplaced_attr.rs:4:1
|
||||
|
|
||||
LL | #[diagnostic::on_const(message = "tadaa", note = "boing")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/misplaced_attr.rs:2:9
|
||||
|
|
||||
LL | #![deny(misplaced_diagnostic_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[diagnostic::on_const]` can only be applied to trait impls
|
||||
--> $DIR/misplaced_attr.rs:8:1
|
||||
|
|
||||
LL | #[diagnostic::on_const(message = "tadaa", note = "boing")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[diagnostic::on_const]` can only be applied to trait impls
|
||||
--> $DIR/misplaced_attr.rs:16:1
|
||||
|
|
||||
LL | #[diagnostic::on_const(message = "tadaa", note = "boing")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[diagnostic::on_const]` can only be applied to trait impls
|
||||
--> $DIR/misplaced_attr.rs:25:5
|
||||
|
|
||||
LL | #[diagnostic::on_const(message = "tadaa", note = "boing")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
8
tests/ui/feature-gates/auxiliary/diagnostic-on-const.rs
Normal file
8
tests/ui/feature-gates/auxiliary/diagnostic-on-const.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
pub struct Foo;
|
||||
|
||||
#[diagnostic::on_const(message = "tadaa", note = "boing")]
|
||||
impl PartialEq for Foo {
|
||||
fn eq(&self, _other: &Foo) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
16
tests/ui/feature-gates/feature-gate-diagnostic-on-const.rs
Normal file
16
tests/ui/feature-gates/feature-gate-diagnostic-on-const.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//! This is an unusual feature gate test, as it doesn't test the feature
|
||||
//! gate, but the fact that not adding the feature gate to
|
||||
//! the aux crate will cause the diagnostic to not emit the
|
||||
//! custom diagnostic message
|
||||
|
||||
//@ aux-build: diagnostic-on-const.rs
|
||||
|
||||
extern crate diagnostic_on_const;
|
||||
use diagnostic_on_const::Foo;
|
||||
|
||||
const fn foo() {
|
||||
Foo == Foo;
|
||||
//~^ ERROR: cannot call non-const operator in constant functions
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
error[E0015]: cannot call non-const operator in constant functions
|
||||
--> $DIR/feature-gate-diagnostic-on-const.rs:12:5
|
||||
|
|
||||
LL | Foo == Foo;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: impl defined here, but it is not `const`
|
||||
--> $DIR/auxiliary/diagnostic-on-const.rs:4:1
|
||||
|
|
||||
LL | impl PartialEq for Foo {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0015`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue