Skip to content

Commit a417515

Browse files
committed
Auto merge of #149368 - Zalathar:rollup-dakpdsl, r=Zalathar
Rollup of 12 pull requests Successful merges: - #147115 (More robust stack protector testing) - #148048 (Stabilize `maybe_uninit_write_slice`) - #148641 (Add a diagnostic attribute for special casing const bound errors for non-const impls) - #149074 (Add Command::get_env_clear) - #149097 (num: Implement `uint_gather_scatter_bits` feature for unsigned integers) - #149131 (optimize `slice::Iter::next_chunk`) - #149190 (Forbid `CHECK: br` and `CHECK-NOT: br` in codegen tests (suggest `br {{.*}}` instead)) - #149239 (clarify float min/max behavios for NaNs and signed zeros) - #149243 (Fix typo and clarify bootstrap change tracker entry) - #149301 (Motor OS: make decode_error_kind more comprehensive) - #149306 (bootstrap: Miri now handles jemalloc like everything else) - #149325 (rustdoc: add regression test for #140968) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 1be6b13 + 8d6e349 commit a417515

File tree

70 files changed

+2185
-155
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2185
-155
lines changed

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,21 @@ enum MulAddType {
3636

3737
#[derive(Copy, Clone)]
3838
pub(crate) enum MinMax {
39-
/// The IEEE `Minimum` operation - see `f32::minimum` etc
39+
/// The IEEE-2019 `minimum` operation - see `f32::minimum` etc.
4040
/// In particular, `-0.0` is considered smaller than `+0.0` and
4141
/// if either input is NaN, the result is NaN.
4242
Minimum,
43-
/// The IEEE `MinNum` operation - see `f32::min` etc
43+
/// The IEEE-2008 `minNum` operation - see `f32::min` etc.
4444
/// In particular, if the inputs are `-0.0` and `+0.0`, the result is non-deterministic,
45-
/// and is one argument is NaN, the other one is returned.
45+
/// and if one argument is NaN, the other one is returned.
4646
MinNum,
47-
/// The IEEE `Maximum` operation - see `f32::maximum` etc
47+
/// The IEEE-2019 `maximum` operation - see `f32::maximum` etc.
4848
/// In particular, `-0.0` is considered smaller than `+0.0` and
4949
/// if either input is NaN, the result is NaN.
5050
Maximum,
51-
/// The IEEE `MaxNum` operation - see `f32::max` etc
51+
/// The IEEE-2008 `maxNum` operation - see `f32::max` etc.
5252
/// In particular, if the inputs are `-0.0` and `+0.0`, the result is non-deterministic,
53-
/// and is one argument is NaN, the other one is returned.
53+
/// and if one argument is NaN, the other one is returned.
5454
MaxNum,
5555
}
5656

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1586,9 +1586,10 @@ pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>>
15861586
map
15871587
});
15881588

1589-
pub fn is_stable_diagnostic_attribute(sym: Symbol, _features: &Features) -> bool {
1589+
pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool {
15901590
match sym {
15911591
sym::on_unimplemented | sym::do_not_recommend => true,
1592+
sym::on_const => features.diagnostic_on_const(),
15921593
_ => false,
15931594
}
15941595
}

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,8 @@ declare_features! (
483483
(incomplete, deref_patterns, "1.79.0", Some(87121)),
484484
/// Allows deriving the From trait on single-field structs.
485485
(unstable, derive_from, "1.91.0", Some(144889)),
486+
/// Allows giving non-const impls custom diagnostic messages if attempted to be used as const
487+
(unstable, diagnostic_on_const, "CURRENT_RUSTC_VERSION", Some(143874)),
486488
/// Allows `#[doc(cfg(...))]`.
487489
(unstable, doc_cfg, "1.21.0", Some(43781)),
488490
/// Allows `#[doc(masked)]`.

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
802802
tcx.ensure_ok().type_of(def_id);
803803
tcx.ensure_ok().predicates_of(def_id);
804804
tcx.ensure_ok().associated_items(def_id);
805+
check_diagnostic_attrs(tcx, def_id);
805806
if of_trait {
806807
let impl_trait_header = tcx.impl_trait_header(def_id);
807808
res = res.and(
@@ -824,7 +825,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
824825
tcx.ensure_ok().predicates_of(def_id);
825826
tcx.ensure_ok().associated_items(def_id);
826827
let assoc_items = tcx.associated_items(def_id);
827-
check_on_unimplemented(tcx, def_id);
828+
check_diagnostic_attrs(tcx, def_id);
828829

829830
for &assoc_item in assoc_items.in_definition_order() {
830831
match assoc_item.kind {
@@ -1112,7 +1113,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
11121113
})
11131114
}
11141115

1115-
pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, def_id: LocalDefId) {
1116+
pub(super) fn check_diagnostic_attrs(tcx: TyCtxt<'_>, def_id: LocalDefId) {
11161117
// an error would be reported if this fails.
11171118
let _ = OnUnimplementedDirective::of_item(tcx, def_id.to_def_id());
11181119
}

compiler/rustc_passes/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ passes_deprecated_annotation_has_no_effect =
9696
passes_deprecated_attribute =
9797
deprecated attribute must be paired with either stable or unstable attribute
9898
99+
passes_diagnostic_diagnostic_on_const_only_for_trait_impls =
100+
`#[diagnostic::on_const]` can only be applied to trait impls
101+
99102
passes_diagnostic_diagnostic_on_unimplemented_only_for_traits =
100103
`#[diagnostic::on_unimplemented]` can only be applied to trait definitions
101104

compiler/rustc_passes/src/check_attr.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ use rustc_hir::def::DefKind;
2323
use rustc_hir::def_id::LocalModDefId;
2424
use rustc_hir::intravisit::{self, Visitor};
2525
use rustc_hir::{
26-
self as hir, Attribute, CRATE_HIR_ID, CRATE_OWNER_ID, FnSig, ForeignItem, HirId, Item,
27-
ItemKind, MethodKind, PartialConstStability, Safety, Stability, StabilityLevel, Target,
26+
self as hir, Attribute, CRATE_HIR_ID, CRATE_OWNER_ID, Constness, FnSig, ForeignItem, HirId,
27+
Item, ItemKind, MethodKind, PartialConstStability, Safety, Stability, StabilityLevel, Target,
2828
TraitItem, find_attr,
2929
};
3030
use rustc_macros::LintDiagnostic;
@@ -55,6 +55,10 @@ use crate::{errors, fluent_generated as fluent};
5555
#[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)]
5656
struct DiagnosticOnUnimplementedOnlyForTraits;
5757

58+
#[derive(LintDiagnostic)]
59+
#[diag(passes_diagnostic_diagnostic_on_const_only_for_trait_impls)]
60+
struct DiagnosticOnConstOnlyForTraitImpls;
61+
5862
fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target {
5963
match impl_item.kind {
6064
hir::ImplItemKind::Const(..) => Target::AssocConst,
@@ -294,6 +298,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
294298
[sym::diagnostic, sym::on_unimplemented, ..] => {
295299
self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target)
296300
}
301+
[sym::diagnostic, sym::on_const, ..] => {
302+
self.check_diagnostic_on_const(attr.span(), hir_id, target, item)
303+
}
297304
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
298305
[sym::doc, ..] => self.check_doc_attrs(
299306
attr,
@@ -517,6 +524,31 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
517524
}
518525
}
519526

527+
/// Checks if `#[diagnostic::on_const]` is applied to a trait impl
528+
fn check_diagnostic_on_const(
529+
&self,
530+
attr_span: Span,
531+
hir_id: HirId,
532+
target: Target,
533+
item: Option<ItemLike<'_>>,
534+
) {
535+
if matches!(target, Target::Impl { of_trait: true }) {
536+
match item.unwrap() {
537+
ItemLike::Item(it) => match it.expect_impl().constness {
538+
Constness::Const => {}
539+
Constness::NotConst => return,
540+
},
541+
ItemLike::ForeignItem => {}
542+
}
543+
}
544+
self.tcx.emit_node_span_lint(
545+
MISPLACED_DIAGNOSTIC_ATTRIBUTES,
546+
hir_id,
547+
attr_span,
548+
DiagnosticOnConstOnlyForTraitImpls,
549+
);
550+
}
551+
520552
/// Checks if an `#[inline]` is applied to a function or a closure.
521553
fn check_inline(&self, hir_id: HirId, attr_span: Span, kind: &InlineAttr, target: Target) {
522554
match target {

compiler/rustc_resolve/src/macros.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -690,10 +690,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
690690
if res == Res::NonMacroAttr(NonMacroAttrKind::Tool)
691691
&& let [namespace, attribute, ..] = &*path.segments
692692
&& namespace.ident.name == sym::diagnostic
693-
&& ![sym::on_unimplemented, sym::do_not_recommend].contains(&attribute.ident.name)
693+
&& ![sym::on_unimplemented, sym::do_not_recommend, sym::on_const]
694+
.contains(&attribute.ident.name)
694695
{
695696
let typo_name = find_best_match_for_name(
696-
&[sym::on_unimplemented, sym::do_not_recommend],
697+
&[sym::on_unimplemented, sym::do_not_recommend, sym::on_const],
697698
attribute.ident.name,
698699
Some(5),
699700
);

compiler/rustc_span/src/symbol.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,7 @@ symbols! {
878878
destructuring_assignment,
879879
diagnostic,
880880
diagnostic_namespace,
881+
diagnostic_on_const,
881882
dialect,
882883
direct,
883884
discriminant_kind,
@@ -1594,6 +1595,7 @@ symbols! {
15941595
old_name,
15951596
omit_gdb_pretty_printer_section,
15961597
on,
1598+
on_const,
15971599
on_unimplemented,
15981600
opaque,
15991601
opaque_module_name_placeholder: "<opaque>",

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ use super::{
4343
};
4444
use crate::error_reporting::TypeErrCtxt;
4545
use crate::error_reporting::infer::TyCategory;
46+
use crate::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
4647
use crate::error_reporting::traits::report_dyn_incompatibility;
4748
use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, CoroClosureNotFn};
4849
use crate::infer::{self, InferCtxt, InferCtxtExt as _};
@@ -587,7 +588,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
587588
}
588589

589590
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
590-
self.report_host_effect_error(bound_predicate.rebind(predicate), obligation.param_env, span)
591+
self.report_host_effect_error(bound_predicate.rebind(predicate), &obligation, span)
591592
}
592593

593594
ty::PredicateKind::Subtype(predicate) => {
@@ -808,20 +809,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
808809
fn report_host_effect_error(
809810
&self,
810811
predicate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
811-
param_env: ty::ParamEnv<'tcx>,
812+
main_obligation: &PredicateObligation<'tcx>,
812813
span: Span,
813814
) -> Diag<'a> {
814815
// FIXME(const_trait_impl): We should recompute the predicate with `[const]`
815816
// if it's `const`, and if it holds, explain that this bound only
816-
// *conditionally* holds. If that fails, we should also do selection
817-
// to drill this down to an impl or built-in source, so we can
818-
// point at it and explain that while the trait *is* implemented,
819-
// that implementation is not const.
817+
// *conditionally* holds.
820818
let trait_ref = predicate.map_bound(|predicate| ty::TraitPredicate {
821819
trait_ref: predicate.trait_ref,
822820
polarity: ty::PredicatePolarity::Positive,
823821
});
824822
let mut file = None;
823+
825824
let err_msg = self.get_standard_error_message(
826825
trait_ref,
827826
None,
@@ -832,18 +831,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
832831
);
833832
let mut diag = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
834833
*diag.long_ty_path() = file;
835-
if !self.predicate_may_hold(&Obligation::new(
834+
let obligation = Obligation::new(
836835
self.tcx,
837836
ObligationCause::dummy(),
838-
param_env,
837+
main_obligation.param_env,
839838
trait_ref,
840-
)) {
839+
);
840+
if !self.predicate_may_hold(&obligation) {
841841
diag.downgrade_to_delayed_bug();
842842
}
843-
for candidate in self.find_similar_impl_candidates(trait_ref) {
844-
let CandidateSimilarity::Exact { .. } = candidate.similarity else { continue };
845-
let impl_did = candidate.impl_def_id;
846-
let trait_did = candidate.trait_ref.def_id;
843+
844+
if let Ok(Some(ImplSource::UserDefined(impl_data))) =
845+
SelectionContext::new(self).select(&obligation.with(self.tcx, trait_ref.skip_binder()))
846+
{
847+
let impl_did = impl_data.impl_def_id;
848+
let trait_did = trait_ref.def_id();
847849
let impl_span = self.tcx.def_span(impl_did);
848850
let trait_name = self.tcx.item_name(trait_did);
849851

@@ -865,6 +867,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
865867
impl_span,
866868
format!("trait `{trait_name}` is implemented but not `const`"),
867869
);
870+
871+
let (condition_options, format_args) = self.on_unimplemented_components(
872+
trait_ref,
873+
main_obligation,
874+
diag.long_ty_path(),
875+
);
876+
877+
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, impl_did)
878+
{
879+
let note = command.evaluate(
880+
self.tcx,
881+
predicate.skip_binder().trait_ref,
882+
&condition_options,
883+
&format_args,
884+
);
885+
let OnUnimplementedNote {
886+
message,
887+
label,
888+
notes,
889+
parent_label,
890+
append_const_msg: _,
891+
} = note;
892+
893+
if let Some(message) = message {
894+
diag.primary_message(message);
895+
}
896+
if let Some(label) = label {
897+
diag.span_label(impl_span, label);
898+
}
899+
for note in notes {
900+
diag.note(note);
901+
}
902+
if let Some(parent_label) = parent_label {
903+
diag.span_label(impl_span, parent_label);
904+
}
905+
}
868906
}
869907
}
870908
}

compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit};
55
use rustc_errors::codes::*;
66
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
77
use rustc_hir as hir;
8+
use rustc_hir::def::DefKind;
89
use rustc_hir::def_id::{DefId, LocalDefId};
910
use rustc_hir::{AttrArgs, Attribute};
1011
use rustc_macros::LintDiagnostic;
@@ -103,7 +104,27 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
103104
if trait_pred.polarity() != ty::PredicatePolarity::Positive {
104105
return OnUnimplementedNote::default();
105106
}
107+
let (condition_options, format_args) =
108+
self.on_unimplemented_components(trait_pred, obligation, long_ty_path);
109+
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, trait_pred.def_id())
110+
{
111+
command.evaluate(
112+
self.tcx,
113+
trait_pred.skip_binder().trait_ref,
114+
&condition_options,
115+
&format_args,
116+
)
117+
} else {
118+
OnUnimplementedNote::default()
119+
}
120+
}
106121

122+
pub(crate) fn on_unimplemented_components(
123+
&self,
124+
trait_pred: ty::PolyTraitPredicate<'tcx>,
125+
obligation: &PredicateObligation<'tcx>,
126+
long_ty_path: &mut Option<PathBuf>,
127+
) -> (ConditionOptions, FormatArgs<'tcx>) {
107128
let (def_id, args) = self
108129
.impl_similar_to(trait_pred, obligation)
109130
.unwrap_or_else(|| (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args));
@@ -293,12 +314,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
293314
.collect();
294315

295316
let format_args = FormatArgs { this, trait_sugared, generic_args, item_context };
296-
297-
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) {
298-
command.evaluate(self.tcx, trait_pred.trait_ref, &condition_options, &format_args)
299-
} else {
300-
OnUnimplementedNote::default()
301-
}
317+
(condition_options, format_args)
302318
}
303319
}
304320

@@ -325,7 +341,7 @@ pub struct OnUnimplementedDirective {
325341
}
326342

327343
/// For the `#[rustc_on_unimplemented]` attribute
328-
#[derive(Default)]
344+
#[derive(Default, Debug)]
329345
pub struct OnUnimplementedNote {
330346
pub message: Option<String>,
331347
pub label: Option<String>,
@@ -562,17 +578,21 @@ impl<'tcx> OnUnimplementedDirective {
562578
}
563579

564580
pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<Option<Self>, ErrorGuaranteed> {
565-
if !tcx.is_trait(item_def_id) {
581+
let attr = if tcx.is_trait(item_def_id) {
582+
sym::on_unimplemented
583+
} else if let DefKind::Impl { of_trait: true } = tcx.def_kind(item_def_id) {
584+
sym::on_const
585+
} else {
566586
// It could be a trait_alias (`trait MyTrait = SomeOtherTrait`)
567587
// or an implementation (`impl MyTrait for Foo {}`)
568588
//
569589
// We don't support those.
570590
return Ok(None);
571-
}
591+
};
572592
if let Some(attr) = tcx.get_attr(item_def_id, sym::rustc_on_unimplemented) {
573593
return Self::parse_attribute(attr, false, tcx, item_def_id);
574594
} else {
575-
tcx.get_attrs_by_path(item_def_id, &[sym::diagnostic, sym::on_unimplemented])
595+
tcx.get_attrs_by_path(item_def_id, &[sym::diagnostic, attr])
576596
.filter_map(|attr| Self::parse_attribute(attr, true, tcx, item_def_id).transpose())
577597
.try_fold(None, |aggr: Option<Self>, directive| {
578598
let directive = directive?;

0 commit comments

Comments
 (0)