authorbors <bors@rust-lang.org> 2025-11-09 16:44:31 UTC
committerbors <bors@rust-lang.org> 2025-11-09 16:44:31 UTC
log86b95ebc24092acac75e205d95e84e6d4539601f
tree7e1edc325286496710bca9507eff67b5aa977649
parentab67c37c6dbea849aa3425146bfe99fb1f1d117a
parenta2c4f03ea79e2e7807d403efb6da5dacc97ddd6a

Auto merge of #148753 - matthiaskrgr:rollup-48jzbqw, r=matthiaskrgr

Rollup of 10 pull requests Successful merges: - rust-lang/rust#148683 (Remove `#[const_trait]`) - rust-lang/rust#148687 (std: use a non-poisoning `RwLock` for the panic hook) - rust-lang/rust#148709 (fix: disable self-contained linker when bootstrap-override-lld is set) - rust-lang/rust#148716 (mgca: Finish implementation of `#[type_const]`) - rust-lang/rust#148722 (Add Crystal Durham to .mailmap) - rust-lang/rust#148723 (bootstrap: Render doctest timing reports as text, not JSON) - rust-lang/rust#148724 (tidy: Don't bypass stderr output capture in unit tests) - rust-lang/rust#148734 (miri subtree update) - rust-lang/rust#148736 (Fix typo in unstable-book link) - rust-lang/rust#148744 (Add myself(chenyukang) to the review rotation) r? `@ghost` `@rustbot` modify labels: rollup

306 files changed, 2362 insertions(+), 1968 deletions(-)

.mailmap+1-1
......@@ -139,7 +139,6 @@ Christian Poveda <git@pvdrz.com> <31802960+christianpoveda@users.noreply.github.
139139Christian Poveda <git@pvdrz.com> <christianpoveda@uhura.edef.eu>
140140Christian Vallentin <vallentinsource@gmail.com>
141141Christoffer Buchholz <chris@chrisbuchholz.me>
142Christopher Durham <cad97@cad97.com>
143142Clark Gaebel <cg.wowus.cg@gmail.com> <cgaebel@mozilla.com>
144143Clement Miao <clementmiao@gmail.com>
145144Clément Renault <renault.cle@gmail.com>
......@@ -148,6 +147,7 @@ Clinton Ryan <clint.ryan3@gmail.com>
148147Taylor Cramer <cramertaylorj@gmail.com> <cramertj@google.com>
149148ember arlynx <ember@lunar.town> <corey@octayn.net>
150149Crazycolorz5 <Crazycolorz5@gmail.com>
150Crystal Durham <cad97@cad97.com>
151151csmoe <35686186+csmoe@users.noreply.github.com>
152152Cyryl Płotnicki <cyplo@cyplo.net>
153153Damien Schoof <damien.schoof@gmail.com>
compiler/rustc_ast_passes/messages.ftl+1-1
......@@ -290,7 +290,7 @@ ast_passes_trait_fn_const =
290290 *[false] {""}
291291 }
292292 .make_impl_const_sugg = ... and declare the impl to be const instead
293 .make_trait_const_sugg = ... and declare the trait to be a `#[const_trait]` instead
293 .make_trait_const_sugg = ... and declare the trait to be const instead
294294
295295ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
296296
compiler/rustc_ast_passes/src/ast_validation.rs+9-14
......@@ -48,7 +48,7 @@ enum SelfSemantic {
4848}
4949
5050enum TraitOrTraitImpl {
51 Trait { span: Span, constness: Const },
51 Trait { vis: Span, constness: Const },
5252 TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span },
5353}
5454
......@@ -109,10 +109,10 @@ impl<'a> AstValidator<'a> {
109109 self.outer_trait_or_trait_impl = old;
110110 }
111111
112 fn with_in_trait(&mut self, span: Span, constness: Const, f: impl FnOnce(&mut Self)) {
112 fn with_in_trait(&mut self, vis: Span, constness: Const, f: impl FnOnce(&mut Self)) {
113113 let old = mem::replace(
114114 &mut self.outer_trait_or_trait_impl,
115 Some(TraitOrTraitImpl::Trait { span, constness }),
115 Some(TraitOrTraitImpl::Trait { vis, constness }),
116116 );
117117 f(self);
118118 self.outer_trait_or_trait_impl = old;
......@@ -265,10 +265,12 @@ impl<'a> AstValidator<'a> {
265265 None
266266 };
267267
268 let map = self.sess.source_map();
269
268270 let make_trait_const_sugg = if const_trait_impl
269 && let TraitOrTraitImpl::Trait { span, constness: ast::Const::No } = parent
271 && let &TraitOrTraitImpl::Trait { vis, constness: ast::Const::No } = parent
270272 {
271 Some(span.shrink_to_lo())
273 Some(map.span_extend_while_whitespace(vis).shrink_to_hi())
272274 } else {
273275 None
274276 };
......@@ -279,7 +281,7 @@ impl<'a> AstValidator<'a> {
279281 in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }),
280282 const_context_label: parent_constness,
281283 remove_const_sugg: (
282 self.sess.source_map().span_extend_while_whitespace(span),
284 map.span_extend_while_whitespace(span),
283285 match parent_constness {
284286 Some(_) => rustc_errors::Applicability::MachineApplicable,
285287 None => rustc_errors::Applicability::MaybeIncorrect,
......@@ -1165,13 +1167,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11651167 ..
11661168 }) => {
11671169 self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
1168 // FIXME(const_trait_impl) remove this
1169 let alt_const_trait_span =
1170 attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
1171 let constness = match (*constness, alt_const_trait_span) {
1172 (Const::Yes(span), _) | (Const::No, Some(span)) => Const::Yes(span),
1173 (Const::No, None) => Const::No,
1174 };
11751170 if *is_auto == IsAuto::Yes {
11761171 // Auto traits cannot have generics, super traits nor contain items.
11771172 self.deny_generic_params(generics, ident.span);
......@@ -1188,7 +1183,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11881183 this.visit_generics(generics);
11891184 walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
11901185 });
1191 self.with_in_trait(item.span, constness, |this| {
1186 self.with_in_trait(item.vis.span, *constness, |this| {
11921187 walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
11931188 });
11941189 }
compiler/rustc_ast_passes/src/errors.rs+1-1
......@@ -56,7 +56,7 @@ pub(crate) struct TraitFnConst {
5656 pub make_impl_const_sugg: Option<Span>,
5757 #[suggestion(
5858 ast_passes_make_trait_const_sugg,
59 code = "#[const_trait]\n",
59 code = "const ",
6060 applicability = "maybe-incorrect"
6161 )]
6262 pub make_trait_const_sugg: Option<Span>,
compiler/rustc_attr_parsing/src/attributes/traits.rs+2-12
......@@ -66,7 +66,8 @@ pub(crate) struct TypeConstParser;
6666impl<S: Stage> NoArgsAttributeParser<S> for TypeConstParser {
6767 const PATH: &[Symbol] = &[sym::type_const];
6868 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
69 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocConst)]);
69 const ALLOWED_TARGETS: AllowedTargets =
70 AllowedTargets::AllowList(&[Allow(Target::Const), Allow(Target::AssocConst)]);
7071 const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst;
7172}
7273
......@@ -101,17 +102,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser {
101102 const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject;
102103}
103104
104// FIXME(const_trait_impl): remove this
105// Const traits
106
107pub(crate) struct ConstTraitParser;
108impl<S: Stage> NoArgsAttributeParser<S> for ConstTraitParser {
109 const PATH: &[Symbol] = &[sym::const_trait];
110 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
111 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
112 const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstTrait;
113}
114
115105// Specialization
116106
117107pub(crate) struct SpecializationTraitParser;
compiler/rustc_attr_parsing/src/context.rs+1-2
......@@ -64,7 +64,7 @@ use crate::attributes::stability::{
6464};
6565use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser};
6666use crate::attributes::traits::{
67 AllowIncoherentImplParser, CoinductiveParser, ConstTraitParser, DenyExplicitImplParser,
67 AllowIncoherentImplParser, CoinductiveParser, DenyExplicitImplParser,
6868 DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, ParenSugarParser,
6969 PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
7070 UnsafeSpecializationMarkerParser,
......@@ -218,7 +218,6 @@ attribute_parsers!(
218218 Single<WithoutArgs<ColdParser>>,
219219 Single<WithoutArgs<ConstContinueParser>>,
220220 Single<WithoutArgs<ConstStabilityIndirectParser>>,
221 Single<WithoutArgs<ConstTraitParser>>,
222221 Single<WithoutArgs<CoroutineParser>>,
223222 Single<WithoutArgs<DenyExplicitImplParser>>,
224223 Single<WithoutArgs<DoNotImplementViaObjectParser>>,
compiler/rustc_const_eval/src/check_consts/ops.rs+8-10
......@@ -381,23 +381,21 @@ fn build_error_for_const_call<'tcx>(
381381 `{trait_name}` is not const",
382382 ),
383383 );
384 if parent.is_local() && ccx.tcx.sess.is_nightly_build() {
384 if let Some(parent) = parent.as_local()
385 && ccx.tcx.sess.is_nightly_build()
386 {
385387 if !ccx.tcx.features().const_trait_impl() {
386388 err.help(
387389 "add `#![feature(const_trait_impl)]` to the crate attributes to \
388 enable `#[const_trait]`",
390 enable const traits",
389391 );
390392 }
391 let indentation = ccx
392 .tcx
393 .sess
394 .source_map()
395 .indentation_before(trait_span)
396 .unwrap_or_default();
393 let span = ccx.tcx.hir_expect_item(parent).vis_span;
394 let span = ccx.tcx.sess.source_map().span_extend_while_whitespace(span);
397395 err.span_suggestion_verbose(
398 trait_span.shrink_to_lo(),
396 span.shrink_to_hi(),
399397 format!("consider making trait `{trait_name}` const"),
400 format!("#[const_trait]\n{indentation}"),
398 "const ".to_owned(),
401399 Applicability::MaybeIncorrect,
402400 );
403401 } else if !ccx.tcx.sess.is_nightly_build() {
compiler/rustc_feature/src/builtin_attrs.rs-8
......@@ -846,14 +846,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
846846 EncodeCrossCrate::No, experimental!(register_tool),
847847 ),
848848
849 // RFC 2632
850 // FIXME(const_trait_impl) remove this
851 gated!(
852 const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl,
853 "`const_trait` is a temporary placeholder for marking a trait that is suitable for `const` \
854 `impls` and all default bodies as `const`, which may be removed or renamed in the \
855 future."
856 ),
857849 // lang-team MCP 147
858850 gated!(
859851 deprecated_safe, Normal, template!(List: &[r#"since = "version", note = "...""#]), ErrorFollowing,
compiler/rustc_hir/src/attrs/data_structures.rs-3
......@@ -499,9 +499,6 @@ pub enum AttributeKind {
499499 /// Represents `#[rustc_const_stable_indirect]`.
500500 ConstStabilityIndirect,
501501
502 /// Represents `#[const_trait]`.
503 ConstTrait(Span),
504
505502 /// Represents `#[coroutine]`.
506503 Coroutine(Span),
507504
compiler/rustc_hir/src/attrs/encode_cross_crate.rs-1
......@@ -32,7 +32,6 @@ impl AttributeKind {
3232 ConstContinue(..) => No,
3333 ConstStability { .. } => Yes,
3434 ConstStabilityIndirect => No,
35 ConstTrait(..) => No,
3635 Coroutine(..) => No,
3736 Coverage(..) => No,
3837 CrateName { .. } => No,
compiler/rustc_hir/src/hir.rs+7-2
......@@ -3065,7 +3065,7 @@ macro_rules! expect_methods_self_kind {
30653065 $(
30663066 #[track_caller]
30673067 pub fn $name(&self) -> $ret_ty {
3068 let $pat = &self.kind else { expect_failed(stringify!($ident), self) };
3068 let $pat = &self.kind else { expect_failed(stringify!($name), self) };
30693069 $ret_val
30703070 }
30713071 )*
......@@ -3077,7 +3077,7 @@ macro_rules! expect_methods_self {
30773077 $(
30783078 #[track_caller]
30793079 pub fn $name(&self) -> $ret_ty {
3080 let $pat = self else { expect_failed(stringify!($ident), self) };
3080 let $pat = self else { expect_failed(stringify!($name), self) };
30813081 $ret_val
30823082 }
30833083 )*
......@@ -4790,6 +4790,11 @@ impl<'hir> Node<'hir> {
47904790 ForeignItemKind::Static(ty, ..) => Some(ty),
47914791 _ => None,
47924792 },
4793 Node::GenericParam(param) => match param.kind {
4794 GenericParamKind::Lifetime { .. } => None,
4795 GenericParamKind::Type { default, .. } => default,
4796 GenericParamKind::Const { ty, .. } => Some(ty),
4797 },
47934798 _ => None,
47944799 }
47954800 }
compiler/rustc_hir_analysis/src/check/check.rs+47-13
......@@ -757,22 +757,18 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
757757 }
758758
759759 match tcx.def_kind(def_id) {
760 def_kind @ (DefKind::Static { .. } | DefKind::Const) => {
760 DefKind::Static { .. } => {
761761 tcx.ensure_ok().generics_of(def_id);
762762 tcx.ensure_ok().type_of(def_id);
763763 tcx.ensure_ok().predicates_of(def_id);
764 match def_kind {
765 DefKind::Static { .. } => {
766 check_static_inhabited(tcx, def_id);
767 check_static_linkage(tcx, def_id);
768 let ty = tcx.type_of(def_id).instantiate_identity();
769 res = res.and(wfcheck::check_static_item(
770 tcx, def_id, ty, /* should_check_for_sync */ true,
771 ));
772 }
773 DefKind::Const => res = res.and(wfcheck::check_const_item(tcx, def_id)),
774 _ => unreachable!(),
775 }
764
765 check_static_inhabited(tcx, def_id);
766 check_static_linkage(tcx, def_id);
767 let ty = tcx.type_of(def_id).instantiate_identity();
768 res = res.and(wfcheck::check_static_item(
769 tcx, def_id, ty, /* should_check_for_sync */ true,
770 ));
771
776772 // Only `Node::Item` and `Node::ForeignItem` still have HIR based
777773 // checks. Returning early here does not miss any checks and
778774 // avoids this query from having a direct dependency edge on the HIR
......@@ -900,6 +896,39 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
900896 // avoids this query from having a direct dependency edge on the HIR
901897 return res;
902898 }
899 DefKind::Const => {
900 tcx.ensure_ok().generics_of(def_id);
901 tcx.ensure_ok().type_of(def_id);
902 tcx.ensure_ok().predicates_of(def_id);
903
904 res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
905 let ty = tcx.type_of(def_id).instantiate_identity();
906 let ty_span = tcx.ty_span(def_id);
907 let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty);
908 wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into());
909 wfcx.register_bound(
910 traits::ObligationCause::new(
911 ty_span,
912 def_id,
913 ObligationCauseCode::SizedConstOrStatic,
914 ),
915 tcx.param_env(def_id),
916 ty,
917 tcx.require_lang_item(LangItem::Sized, ty_span),
918 );
919 check_where_clauses(wfcx, def_id);
920
921 if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) {
922 wfcheck::check_type_const(wfcx, def_id, ty, true)?;
923 }
924 Ok(())
925 }));
926
927 // Only `Node::Item` and `Node::ForeignItem` still have HIR based
928 // checks. Returning early here does not miss any checks and
929 // avoids this query from having a direct dependency edge on the HIR
930 return res;
931 }
903932 DefKind::TyAlias => {
904933 tcx.ensure_ok().generics_of(def_id);
905934 tcx.ensure_ok().type_of(def_id);
......@@ -920,6 +949,11 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
920949 }));
921950 check_variances_for_type_defn(tcx, def_id);
922951 }
952
953 // Only `Node::Item` and `Node::ForeignItem` still have HIR based
954 // checks. Returning early here does not miss any checks and
955 // avoids this query from having a direct dependency edge on the HIR
956 return res;
923957 }
924958 DefKind::ForeignMod => {
925959 let it = tcx.hir_expect_item(def_id);
compiler/rustc_hir_analysis/src/check/compare_impl_item.rs+36-1
......@@ -6,9 +6,10 @@ use hir::def_id::{DefId, DefIdMap, LocalDefId};
66use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
77use rustc_errors::codes::*;
88use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err};
9use rustc_hir::attrs::AttributeKind;
910use rustc_hir::def::{DefKind, Res};
1011use rustc_hir::intravisit::VisitorExt;
11use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};
12use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, find_attr, intravisit};
1213use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt};
1314use rustc_infer::traits::util;
1415use rustc_middle::ty::error::{ExpectedFound, TypeError};
......@@ -1984,12 +1985,46 @@ fn compare_impl_const<'tcx>(
19841985 trait_const_item: ty::AssocItem,
19851986 impl_trait_ref: ty::TraitRef<'tcx>,
19861987) -> Result<(), ErrorGuaranteed> {
1988 compare_type_const(tcx, impl_const_item, trait_const_item)?;
19871989 compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
19881990 compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
19891991 check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
19901992 compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
19911993}
19921994
1995fn compare_type_const<'tcx>(
1996 tcx: TyCtxt<'tcx>,
1997 impl_const_item: ty::AssocItem,
1998 trait_const_item: ty::AssocItem,
1999) -> Result<(), ErrorGuaranteed> {
2000 let impl_is_type_const =
2001 find_attr!(tcx.get_all_attrs(impl_const_item.def_id), AttributeKind::TypeConst(_));
2002 let trait_type_const_span = find_attr!(
2003 tcx.get_all_attrs(trait_const_item.def_id),
2004 AttributeKind::TypeConst(sp) => *sp
2005 );
2006
2007 if let Some(trait_type_const_span) = trait_type_const_span
2008 && !impl_is_type_const
2009 {
2010 return Err(tcx
2011 .dcx()
2012 .struct_span_err(
2013 tcx.def_span(impl_const_item.def_id),
2014 "implementation of `#[type_const]` const must be marked with `#[type_const]`",
2015 )
2016 .with_span_note(
2017 MultiSpan::from_spans(vec![
2018 tcx.def_span(trait_const_item.def_id),
2019 trait_type_const_span,
2020 ]),
2021 "trait declaration of const is marked with `#[type_const]`",
2022 )
2023 .emit());
2024 }
2025 Ok(())
2026}
2027
19932028/// The equivalent of [compare_method_predicate_entailment], but for associated constants
19942029/// instead of associated functions.
19952030// FIXME(generic_const_items): If possible extract the common parts of `compare_{type,const}_predicate_entailment`.
compiler/rustc_hir_analysis/src/check/wfcheck.rs+63-62
......@@ -6,10 +6,11 @@ use rustc_abi::ExternAbi;
66use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
77use rustc_errors::codes::*;
88use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
9use rustc_hir::attrs::AttributeKind;
910use rustc_hir::def::{DefKind, Res};
1011use rustc_hir::def_id::{DefId, LocalDefId};
1112use rustc_hir::lang_items::LangItem;
12use rustc_hir::{AmbigArg, ItemKind};
13use rustc_hir::{AmbigArg, ItemKind, find_attr};
1314use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1415use rustc_infer::infer::{self, InferCtxt, SubregionOrigin, TyCtxtInferExt};
1516use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION;
......@@ -925,11 +926,11 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
925926#[instrument(level = "debug", skip(tcx))]
926927pub(crate) fn check_associated_item(
927928 tcx: TyCtxt<'_>,
928 item_id: LocalDefId,
929 def_id: LocalDefId,
929930) -> Result<(), ErrorGuaranteed> {
930 let loc = Some(WellFormedLoc::Ty(item_id));
931 enter_wf_checking_ctxt(tcx, item_id, |wfcx| {
932 let item = tcx.associated_item(item_id);
931 let loc = Some(WellFormedLoc::Ty(def_id));
932 enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
933 let item = tcx.associated_item(def_id);
933934
934935 // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
935936 // other `Foo` impls are incoherent.
......@@ -942,27 +943,36 @@ pub(crate) fn check_associated_item(
942943 }
943944 };
944945
945 let span = tcx.def_span(item_id);
946 let span = tcx.def_span(def_id);
946947
947948 match item.kind {
948949 ty::AssocKind::Const { .. } => {
949 let ty = tcx.type_of(item.def_id).instantiate_identity();
950 let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
950 let ty = tcx.type_of(def_id).instantiate_identity();
951 let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);
951952 wfcx.register_wf_obligation(span, loc, ty.into());
952 check_sized_if_body(
953 wfcx,
954 item.def_id.expect_local(),
955 ty,
956 Some(span),
957 ObligationCauseCode::SizedConstOrStatic,
958 );
953
954 let has_value = item.defaultness(tcx).has_value();
955 if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) {
956 check_type_const(wfcx, def_id, ty, has_value)?;
957 }
958
959 if has_value {
960 let code = ObligationCauseCode::SizedConstOrStatic;
961 wfcx.register_bound(
962 ObligationCause::new(span, def_id, code),
963 wfcx.param_env,
964 ty,
965 tcx.require_lang_item(LangItem::Sized, span),
966 );
967 }
968
959969 Ok(())
960970 }
961971 ty::AssocKind::Fn { .. } => {
962 let sig = tcx.fn_sig(item.def_id).instantiate_identity();
972 let sig = tcx.fn_sig(def_id).instantiate_identity();
963973 let hir_sig =
964 tcx.hir_node_by_def_id(item_id).fn_sig().expect("bad signature for method");
965 check_fn_or_method(wfcx, sig, hir_sig.decl, item_id);
974 tcx.hir_node_by_def_id(def_id).fn_sig().expect("bad signature for method");
975 check_fn_or_method(wfcx, sig, hir_sig.decl, def_id);
966976 check_method_receiver(wfcx, hir_sig, item, self_ty)
967977 }
968978 ty::AssocKind::Type { .. } => {
......@@ -970,8 +980,8 @@ pub(crate) fn check_associated_item(
970980 check_associated_type_bounds(wfcx, item, span)
971981 }
972982 if item.defaultness(tcx).has_value() {
973 let ty = tcx.type_of(item.def_id).instantiate_identity();
974 let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
983 let ty = tcx.type_of(def_id).instantiate_identity();
984 let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);
975985 wfcx.register_wf_obligation(span, loc, ty.into());
976986 }
977987 Ok(())
......@@ -1222,28 +1232,36 @@ pub(crate) fn check_static_item<'tcx>(
12221232 })
12231233}
12241234
1225pub(crate) fn check_const_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
1226 enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
1227 let ty = tcx.type_of(def_id).instantiate_identity();
1228 let ty_span = tcx.ty_span(def_id);
1229 let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty);
1235#[instrument(level = "debug", skip(wfcx))]
1236pub(super) fn check_type_const<'tcx>(
1237 wfcx: &WfCheckingCtxt<'_, 'tcx>,
1238 def_id: LocalDefId,
1239 item_ty: Ty<'tcx>,
1240 has_value: bool,
1241) -> Result<(), ErrorGuaranteed> {
1242 let tcx = wfcx.tcx();
1243 let span = tcx.def_span(def_id);
12301244
1231 wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into());
1232 wfcx.register_bound(
1233 traits::ObligationCause::new(
1234 ty_span,
1235 wfcx.body_def_id,
1236 ObligationCauseCode::SizedConstOrStatic,
1237 ),
1238 wfcx.param_env,
1239 ty,
1240 tcx.require_lang_item(LangItem::Sized, ty_span),
1241 );
1245 wfcx.register_bound(
1246 ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)),
1247 wfcx.param_env,
1248 item_ty,
1249 tcx.require_lang_item(LangItem::ConstParamTy, span),
1250 );
12421251
1243 check_where_clauses(wfcx, def_id);
1252 if has_value {
1253 let raw_ct = tcx.const_of_item(def_id).instantiate_identity();
1254 let norm_ct = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), raw_ct);
1255 wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(def_id)), norm_ct.into());
12441256
1245 Ok(())
1246 })
1257 wfcx.register_obligation(Obligation::new(
1258 tcx,
1259 ObligationCause::new(span, def_id, ObligationCauseCode::WellFormed(None)),
1260 wfcx.param_env,
1261 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(norm_ct, item_ty)),
1262 ));
1263 }
1264 Ok(())
12471265}
12481266
12491267#[instrument(level = "debug", skip(tcx, impl_))]
......@@ -1583,33 +1601,16 @@ fn check_fn_or_method<'tcx>(
15831601 }
15841602
15851603 // If the function has a body, additionally require that the return type is sized.
1586 check_sized_if_body(
1587 wfcx,
1588 def_id,
1589 sig.output(),
1590 match hir_decl.output {
1591 hir::FnRetTy::Return(ty) => Some(ty.span),
1592 hir::FnRetTy::DefaultReturn(_) => None,
1593 },
1594 ObligationCauseCode::SizedReturnType,
1595 );
1596}
1597
1598fn check_sized_if_body<'tcx>(
1599 wfcx: &WfCheckingCtxt<'_, 'tcx>,
1600 def_id: LocalDefId,
1601 ty: Ty<'tcx>,
1602 maybe_span: Option<Span>,
1603 code: ObligationCauseCode<'tcx>,
1604) {
1605 let tcx = wfcx.tcx();
16061604 if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) {
1607 let span = maybe_span.unwrap_or(body.value.span);
1605 let span = match hir_decl.output {
1606 hir::FnRetTy::Return(ty) => ty.span,
1607 hir::FnRetTy::DefaultReturn(_) => body.value.span,
1608 };
16081609
16091610 wfcx.register_bound(
1610 ObligationCause::new(span, def_id, code),
1611 ObligationCause::new(span, def_id, ObligationCauseCode::SizedReturnType),
16111612 wfcx.param_env,
1612 ty,
1613 sig.output(),
16131614 tcx.require_lang_item(LangItem::Sized, span),
16141615 );
16151616 }
compiler/rustc_hir_analysis/src/collect.rs+19-19
......@@ -891,15 +891,6 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
891891 };
892892
893893 let attrs = tcx.get_all_attrs(def_id);
894 // Only regular traits can be const.
895 // FIXME(const_trait_impl): remove this
896 let constness = if constness == hir::Constness::Const
897 || !is_alias && find_attr!(attrs, AttributeKind::ConstTrait(_))
898 {
899 hir::Constness::Const
900 } else {
901 hir::Constness::NotConst
902 };
903894
904895 let paren_sugar = find_attr!(attrs, AttributeKind::ParenSugar(_));
905896 if paren_sugar && !tcx.features().unboxed_closures() {
......@@ -1382,22 +1373,27 @@ fn check_impl_constness(
13821373 }
13831374
13841375 let trait_name = tcx.item_name(trait_def_id).to_string();
1385 let (local_trait_span, suggestion_pre) =
1386 match (trait_def_id.is_local(), tcx.sess.is_nightly_build()) {
1387 (true, true) => (
1388 Some(tcx.def_span(trait_def_id).shrink_to_lo()),
1376 let (suggestion, suggestion_pre) = match (trait_def_id.as_local(), tcx.sess.is_nightly_build())
1377 {
1378 (Some(trait_def_id), true) => {
1379 let span = tcx.hir_expect_item(trait_def_id).vis_span;
1380 let span = tcx.sess.source_map().span_extend_while_whitespace(span);
1381
1382 (
1383 Some(span.shrink_to_hi()),
13891384 if tcx.features().const_trait_impl() {
13901385 ""
13911386 } else {
13921387 "enable `#![feature(const_trait_impl)]` in your crate and "
13931388 },
1394 ),
1395 (false, _) | (_, false) => (None, ""),
1396 };
1389 )
1390 }
1391 (None, _) | (_, false) => (None, ""),
1392 };
13971393 tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
13981394 trait_ref_span: hir_trait_ref.path.span,
13991395 trait_name,
1400 local_trait_span,
1396 suggestion,
14011397 suggestion_pre,
14021398 marking: (),
14031399 adding: (),
......@@ -1615,8 +1611,12 @@ fn const_of_item<'tcx>(
16151611 };
16161612 let ct_arg = match ct_rhs {
16171613 hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg,
1618 hir::ConstItemRhs::Body(body_id) => {
1619 bug!("cannot call const_of_item on a non-type_const {body_id:?}")
1614 hir::ConstItemRhs::Body(_) => {
1615 let e = tcx.dcx().span_delayed_bug(
1616 tcx.def_span(def_id),
1617 "cannot call const_of_item on a non-type_const",
1618 );
1619 return ty::EarlyBinder::bind(Const::new_error(tcx, e));
16201620 }
16211621 };
16221622 let icx = ItemCtxt::new(tcx, def_id);
compiler/rustc_hir_analysis/src/errors.rs+4-14
......@@ -500,13 +500,8 @@ pub(crate) struct ConstImplForNonConstTrait {
500500 #[label]
501501 pub trait_ref_span: Span,
502502 pub trait_name: String,
503 #[suggestion(
504 applicability = "machine-applicable",
505 // FIXME(const_trait_impl) fix this suggestion
506 code = "#[const_trait] ",
507 style = "verbose"
508 )]
509 pub local_trait_span: Option<Span>,
503 #[suggestion(applicability = "machine-applicable", code = "const ", style = "verbose")]
504 pub suggestion: Option<Span>,
510505 pub suggestion_pre: &'static str,
511506 #[note]
512507 pub marking: (),
......@@ -523,14 +518,9 @@ pub(crate) struct ConstBoundForNonConstTrait {
523518 pub modifier: &'static str,
524519 #[note]
525520 pub def_span: Option<Span>,
526 pub suggestion_pre: &'static str,
527 #[suggestion(
528 applicability = "machine-applicable",
529 // FIXME(const_trait_impl) fix this suggestion
530 code = "#[const_trait] ",
531 style = "verbose"
532 )]
521 #[suggestion(applicability = "machine-applicable", code = "const ", style = "verbose")]
533522 pub suggestion: Option<Span>,
523 pub suggestion_pre: &'static str,
534524 pub trait_name: String,
535525}
536526
compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs+19-14
......@@ -881,28 +881,33 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
881881 }
882882
883883 if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness
884 && !self.tcx().is_const_trait(trait_def_id)
884 && !tcx.is_const_trait(trait_def_id)
885885 {
886886 let (def_span, suggestion, suggestion_pre) =
887 match (trait_def_id.is_local(), self.tcx().sess.is_nightly_build()) {
888 (true, true) => (
889 None,
890 Some(tcx.def_span(trait_def_id).shrink_to_lo()),
891 if self.tcx().features().const_trait_impl() {
892 ""
893 } else {
894 "enable `#![feature(const_trait_impl)]` in your crate and "
895 },
896 ),
897 (false, _) | (_, false) => (Some(tcx.def_span(trait_def_id)), None, ""),
887 match (trait_def_id.as_local(), tcx.sess.is_nightly_build()) {
888 (Some(trait_def_id), true) => {
889 let span = tcx.hir_expect_item(trait_def_id).vis_span;
890 let span = tcx.sess.source_map().span_extend_while_whitespace(span);
891
892 (
893 None,
894 Some(span.shrink_to_hi()),
895 if self.tcx().features().const_trait_impl() {
896 ""
897 } else {
898 "enable `#![feature(const_trait_impl)]` in your crate and "
899 },
900 )
901 }
902 (None, _) | (_, false) => (Some(tcx.def_span(trait_def_id)), None, ""),
898903 };
899904 self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
900905 span,
901906 modifier: constness.as_str(),
902907 def_span,
903 trait_name: self.tcx().def_path_str(trait_def_id),
904 suggestion_pre,
908 trait_name: tcx.def_path_str(trait_def_id),
905909 suggestion,
910 suggestion_pre,
906911 });
907912 } else {
908913 match predicate_filter {
compiler/rustc_passes/src/check_attr.rs+1-14
......@@ -150,9 +150,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
150150 Attribute::Parsed(AttributeKind::ProcMacroDerive { .. }) => {
151151 self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
152152 }
153 &Attribute::Parsed(AttributeKind::TypeConst(attr_span)) => {
154 self.check_type_const(hir_id, attr_span, target)
155 }
156153 Attribute::Parsed(
157154 AttributeKind::Stability {
158155 span: attr_span,
......@@ -235,7 +232,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
235232 | AttributeKind::Marker(..)
236233 | AttributeKind::SkipDuringMethodDispatch { .. }
237234 | AttributeKind::Coinductive(..)
238 | AttributeKind::ConstTrait(..)
239235 | AttributeKind::DenyExplicitImpl(..)
240236 | AttributeKind::DoNotImplementViaObject(..)
241237 | AttributeKind::SpecializationTrait(..)
......@@ -243,6 +239,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
243239 | AttributeKind::ParenSugar(..)
244240 | AttributeKind::AllowIncoherentImpl(..)
245241 | AttributeKind::Confusables { .. }
242 | AttributeKind::TypeConst{..}
246243 // `#[doc]` is actually a lot more than just doc comments, so is checked below
247244 | AttributeKind::DocComment {..}
248245 // handled below this loop and elsewhere
......@@ -2115,16 +2112,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
21152112 }
21162113 }
21172114
2118 fn check_type_const(&self, _hir_id: HirId, attr_span: Span, target: Target) {
2119 if matches!(target, Target::AssocConst | Target::Const) {
2120 return;
2121 } else {
2122 self.dcx()
2123 .struct_span_err(attr_span, "`#[type_const]` must only be applied to const items")
2124 .emit();
2125 }
2126 }
2127
21282115 fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) {
21292116 if !find_attr!(attrs, AttributeKind::Repr { reprs, .. } => reprs.iter().any(|(r, _)| r == &ReprAttr::ReprTransparent))
21302117 .unwrap_or(false)
compiler/rustc_span/src/symbol.rs-1
......@@ -750,7 +750,6 @@ symbols! {
750750 const_raw_ptr_to_usize_cast,
751751 const_refs_to_cell,
752752 const_refs_to_static,
753 const_trait,
754753 const_trait_bound_opt_out,
755754 const_trait_impl,
756755 const_try,
compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs+2-6
......@@ -1286,12 +1286,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
12861286 ty: Ty<'tcx>,
12871287 obligation: &PredicateObligation<'tcx>,
12881288 ) -> Diag<'a> {
1289 let param = obligation.cause.body_id;
1290 let hir::GenericParamKind::Const { ty: &hir::Ty { span, .. }, .. } =
1291 self.tcx.hir_node_by_def_id(param).expect_generic_param().kind
1292 else {
1293 bug!()
1294 };
1289 let def_id = obligation.cause.body_id;
1290 let span = self.tcx.ty_span(def_id);
12951291
12961292 let mut file = None;
12971293 let ty_str = self.tcx.short_string(ty, &mut file);
library/core/src/array/equality.rs+1-2
......@@ -132,9 +132,8 @@ where
132132#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
133133impl<T: [const] Eq, const N: usize> const Eq for [T; N] {}
134134
135#[const_trait]
136135#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
137trait SpecArrayEq<Other, const N: usize>: Sized {
136const trait SpecArrayEq<Other, const N: usize>: Sized {
138137 fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool;
139138 fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool;
140139}
library/core/src/cmp/bytewise.rs+1-2
......@@ -17,8 +17,7 @@ use crate::num::NonZero;
1717/// - Neither `Self` nor `Rhs` have provenance, so integer comparisons are correct.
1818/// - `<Self as PartialEq<Rhs>>::{eq,ne}` are equivalent to comparing the bytes.
1919#[rustc_specialization_trait]
20#[const_trait] // FIXME(const_trait_impl): Migrate to `const unsafe trait` once #146122 is fixed.
21pub(crate) unsafe trait BytewiseEq<Rhs = Self>:
20pub(crate) const unsafe trait BytewiseEq<Rhs = Self>:
2221 [const] PartialEq<Rhs> + Sized
2322{
2423}
library/core/src/ops/range.rs+3-6
......@@ -816,9 +816,8 @@ impl<T: Clone> Bound<&T> {
816816/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
817817#[stable(feature = "collections_range", since = "1.28.0")]
818818#[rustc_diagnostic_item = "RangeBounds"]
819#[const_trait]
820819#[rustc_const_unstable(feature = "const_range", issue = "none")]
821pub trait RangeBounds<T: ?Sized> {
820pub const trait RangeBounds<T: ?Sized> {
822821 /// Start index bound.
823822 ///
824823 /// Returns the start value as a `Bound`.
......@@ -954,9 +953,8 @@ pub trait RangeBounds<T: ?Sized> {
954953/// `IntoBounds` is implemented by Rust’s built-in range types, produced
955954/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
956955#[unstable(feature = "range_into_bounds", issue = "136903")]
957#[const_trait]
958956#[rustc_const_unstable(feature = "const_range", issue = "none")]
959pub trait IntoBounds<T>: [const] RangeBounds<T> {
957pub const trait IntoBounds<T>: [const] RangeBounds<T> {
960958 /// Convert this range into the start and end bounds.
961959 /// Returns `(start_bound, end_bound)`.
962960 ///
......@@ -1319,9 +1317,8 @@ pub enum OneSidedRangeBound {
13191317/// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded`
13201318/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`.
13211319#[unstable(feature = "one_sided_range", issue = "69780")]
1322#[const_trait]
13231320#[rustc_const_unstable(feature = "const_range", issue = "none")]
1324pub trait OneSidedRange<T>: RangeBounds<T> {
1321pub const trait OneSidedRange<T>: RangeBounds<T> {
13251322 /// An internal-only helper function for `split_off` and
13261323 /// `split_off_mut` that returns the bound of the one-sided range.
13271324 fn bound(self) -> (OneSidedRangeBound, T);
library/core/src/slice/cmp.rs+5-10
......@@ -155,18 +155,16 @@ where
155155}
156156
157157#[doc(hidden)]
158#[const_trait]
159158#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
160159// intermediate trait for specialization of slice's PartialOrd
161trait SlicePartialOrd: Sized {
160const trait SlicePartialOrd: Sized {
162161 fn partial_compare(left: &[Self], right: &[Self]) -> Option<Ordering>;
163162}
164163
165164#[doc(hidden)]
166#[const_trait]
167165#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
168166// intermediate trait for specialization of slice's PartialOrd chaining methods
169trait SliceChain: Sized {
167const trait SliceChain: Sized {
170168 fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
171169 fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
172170 fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool>;
......@@ -244,9 +242,8 @@ impl<A: [const] AlwaysApplicableOrd> const SlicePartialOrd for A {
244242}
245243
246244#[rustc_specialization_trait]
247#[const_trait]
248245#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
249trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {}
246const trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {}
250247
251248macro_rules! always_applicable_ord {
252249 ($([$($p:tt)*] $t:ty,)*) => {
......@@ -265,10 +262,9 @@ always_applicable_ord! {
265262}
266263
267264#[doc(hidden)]
268#[const_trait]
269265#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
270266// intermediate trait for specialization of slice's Ord
271trait SliceOrd: Sized {
267const trait SliceOrd: Sized {
272268 fn compare(left: &[Self], right: &[Self]) -> Ordering;
273269}
274270
......@@ -292,8 +288,7 @@ impl<A: Ord> SliceOrd for A {
292288/// * For every `x` and `y` of this type, `Ord(x, y)` must return the same
293289/// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`.
294290#[rustc_specialization_trait]
295#[const_trait]
296unsafe trait UnsignedBytewiseOrd: [const] Ord {}
291const unsafe trait UnsignedBytewiseOrd: [const] Ord {}
297292
298293#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
299294unsafe impl const UnsignedBytewiseOrd for bool {}
library/core/src/slice/index.rs+1-2
......@@ -159,9 +159,8 @@ mod private_slice_index {
159159 message = "the type `{T}` cannot be indexed by `{Self}`",
160160 label = "slice indices are of type `usize` or ranges of `usize`"
161161)]
162#[const_trait] // FIXME(const_trait_impl): Migrate to `const unsafe trait` once #146122 is fixed.
163162#[rustc_const_unstable(feature = "const_index", issue = "143775")]
164pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
163pub const unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
165164 /// The output type returned by methods.
166165 #[stable(feature = "slice_get_slice", since = "1.28.0")]
167166 type Output: ?Sized;
library/std/src/panicking.rs+7-15
......@@ -22,7 +22,7 @@ use crate::io::try_set_output_capture;
2222use crate::mem::{self, ManuallyDrop};
2323use crate::panic::{BacktraceStyle, PanicHookInfo};
2424use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
25use crate::sync::{PoisonError, RwLock};
25use crate::sync::nonpoison::RwLock;
2626use crate::sys::backtrace;
2727use crate::sys::stdio::panic_output;
2828use crate::{fmt, intrinsics, process, thread};
......@@ -144,13 +144,9 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send>) {
144144 panic!("cannot modify the panic hook from a panicking thread");
145145 }
146146
147 let new = Hook::Custom(hook);
148 let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner);
149 let old = mem::replace(&mut *hook, new);
150 drop(hook);
151 // Only drop the old hook after releasing the lock to avoid deadlocking
152 // if its destructor panics.
153 drop(old);
147 // Drop the old hook after changing the hook to avoid deadlocking if its
148 // destructor panics.
149 drop(HOOK.replace(Hook::Custom(hook)));
154150}
155151
156152/// Unregisters the current panic hook and returns it, registering the default hook
......@@ -188,11 +184,7 @@ pub fn take_hook() -> Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send> {
188184 panic!("cannot modify the panic hook from a panicking thread");
189185 }
190186
191 let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner);
192 let old_hook = mem::take(&mut *hook);
193 drop(hook);
194
195 old_hook.into_box()
187 HOOK.replace(Hook::Default).into_box()
196188}
197189
198190/// Atomic combination of [`take_hook`] and [`set_hook`]. Use this to replace the panic handler with
......@@ -238,7 +230,7 @@ where
238230 panic!("cannot modify the panic hook from a panicking thread");
239231 }
240232
241 let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner);
233 let mut hook = HOOK.write();
242234 let prev = mem::take(&mut *hook).into_box();
243235 *hook = Hook::Custom(Box::new(move |info| hook_fn(&prev, info)));
244236}
......@@ -822,7 +814,7 @@ fn panic_with_hook(
822814 crate::process::abort();
823815 }
824816
825 match *HOOK.read().unwrap_or_else(PoisonError::into_inner) {
817 match *HOOK.read() {
826818 // Some platforms (like wasm) know that printing to stderr won't ever actually
827819 // print anything, and if that's the case we can skip the default
828820 // hook. Since string formatting happens lazily when calling `payload`
src/bootstrap/src/utils/helpers.rs+1
......@@ -430,6 +430,7 @@ pub fn linker_flags(
430430 match builder.config.bootstrap_override_lld {
431431 BootstrapOverrideLld::External => {
432432 args.push("-Clinker-features=+lld".to_string());
433 args.push("-Clink-self-contained=-linker".to_string());
433434 args.push("-Zunstable-options".to_string());
434435 }
435436 BootstrapOverrideLld::SelfContained => {
src/bootstrap/src/utils/render_tests.rs+19
......@@ -306,6 +306,14 @@ impl<'a> Renderer<'a> {
306306 );
307307 }
308308
309 fn render_report(&self, report: &Report) {
310 let &Report { total_time, compilation_time } = report;
311 // Should match `write_merged_doctest_times` in `library/test/src/formatters/pretty.rs`.
312 println!(
313 "all doctests ran in {total_time:.2}s; merged doctests compilation took {compilation_time:.2}s"
314 );
315 }
316
309317 fn render_message(&mut self, message: Message) {
310318 match message {
311319 Message::Suite(SuiteMessage::Started { test_count }) => {
......@@ -323,6 +331,9 @@ impl<'a> Renderer<'a> {
323331 Message::Suite(SuiteMessage::Failed(outcome)) => {
324332 self.render_suite_outcome(Outcome::Failed, &outcome);
325333 }
334 Message::Report(report) => {
335 self.render_report(&report);
336 }
326337 Message::Bench(outcome) => {
327338 // The formatting for benchmarks doesn't replicate 1:1 the formatting libtest
328339 // outputs, mostly because libtest's formatting is broken in terse mode, which is
......@@ -435,6 +446,7 @@ enum Message {
435446 Suite(SuiteMessage),
436447 Test(TestMessage),
437448 Bench(BenchOutcome),
449 Report(Report),
438450}
439451
440452#[derive(serde_derive::Deserialize)]
......@@ -481,3 +493,10 @@ struct TestOutcome {
481493 stdout: Option<String>,
482494 message: Option<String>,
483495}
496
497/// Emitted when running doctests.
498#[derive(serde_derive::Deserialize)]
499struct Report {
500 total_time: f64,
501 compilation_time: f64,
502}
src/doc/unstable-book/src/compiler-flags/sanitizer.md+1-1
......@@ -993,7 +993,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
993993[clang-kcfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-kcfi
994994[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
995995[clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
996[clan-rtsan]: https://clang.llvm.org/docs/RealtimeSanitizer.html
996[clang-rtsan]: https://clang.llvm.org/docs/RealtimeSanitizer.html
997997[clang-safestack]: https://clang.llvm.org/docs/SafeStack.html
998998[clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html
999999[clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html
src/tools/miri/cargo-miri/src/phases.rs+8-69
......@@ -52,18 +52,6 @@ fn show_version() {
5252 println!();
5353}
5454
55fn forward_patched_extern_arg(args: &mut impl Iterator<Item = String>, cmd: &mut Command) {
56 cmd.arg("--extern"); // always forward flag, but adjust filename:
57 let path = args.next().expect("`--extern` should be followed by a filename");
58 if let Some(lib) = path.strip_suffix(".rlib") {
59 // If this is an rlib, make it an rmeta.
60 cmd.arg(format!("{lib}.rmeta"));
61 } else {
62 // Some other extern file (e.g. a `.so`). Forward unchanged.
63 cmd.arg(path);
64 }
65}
66
6755pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
6856 // Require a subcommand before any flags.
6957 // We cannot know which of those flags take arguments and which do not,
......@@ -276,7 +264,7 @@ pub enum RustcPhase {
276264 Rustdoc,
277265}
278266
279pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
267pub fn phase_rustc(args: impl Iterator<Item = String>, phase: RustcPhase) {
280268 /// Determines if we are being invoked (as rustc) to build a crate for
281269 /// the "target" architecture, in contrast to the "host" architecture.
282270 /// Host crates are for build scripts and proc macros and still need to
......@@ -444,7 +432,6 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
444432 }
445433
446434 let mut cmd = miri();
447 let mut emit_link_hack = false;
448435 // Arguments are treated very differently depending on whether this crate is
449436 // for interpretation by Miri, or for use by a build script / proc macro.
450437 if target_crate {
......@@ -455,7 +442,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
455442 }
456443
457444 // Forward arguments, but patched.
458 let emit_flag = "--emit";
445
459446 // This hack helps bootstrap run standard library tests in Miri. The issue is as follows:
460447 // when running `cargo miri test` on libcore, cargo builds a local copy of core and makes it
461448 // a dependency of the integration test crate. This copy duplicates all the lang items, so
......@@ -471,30 +458,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
471458 let replace_librs = env::var_os("MIRI_REPLACE_LIBRS_IF_NOT_TEST").is_some()
472459 && !runnable_crate
473460 && phase == RustcPhase::Build;
474 while let Some(arg) = args.next() {
475 // Patch `--emit`: remove "link" from "--emit" to make this a check-only build.
476 if let Some(val) = arg.strip_prefix(emit_flag) {
477 // Patch this argument. First, extract its value.
478 let val =
479 val.strip_prefix('=').expect("`cargo` should pass `--emit=X` as one argument");
480 let mut val: Vec<_> = val.split(',').collect();
481 // Now make sure "link" is not in there, but "metadata" is.
482 if let Some(i) = val.iter().position(|&s| s == "link") {
483 emit_link_hack = true;
484 val.remove(i);
485 if !val.contains(&"metadata") {
486 val.push("metadata");
487 }
488 }
489 cmd.arg(format!("{emit_flag}={}", val.join(",")));
490 continue;
491 }
492 // Patch `--extern` filenames, since Cargo sometimes passes stub `.rlib` files:
493 // https://github.com/rust-lang/miri/issues/1705
494 if arg == "--extern" {
495 forward_patched_extern_arg(&mut args, &mut cmd);
496 continue;
497 }
461 for arg in args {
498462 // If the REPLACE_LIBRS hack is enabled and we are building a `lib.rs` file, and a
499463 // `lib.miri.rs` file exists, then build that instead.
500464 if replace_librs {
......@@ -543,17 +507,6 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
543507 eprintln!("[cargo-miri rustc] target_crate={target_crate} runnable_crate={runnable_crate}");
544508 }
545509
546 // Create a stub .rlib file if "link" was requested by cargo.
547 // This is necessary to prevent cargo from doing rebuilds all the time.
548 if emit_link_hack {
549 for filename in out_filenames() {
550 if verbose > 0 {
551 eprintln!("[cargo-miri rustc] creating fake lib file at `{}`", filename.display());
552 }
553 File::create(filename).expect("failed to create fake lib file");
554 }
555 }
556
557510 debug_cmd("[cargo-miri rustc]", verbose, &cmd);
558511 exec(cmd);
559512}
......@@ -624,17 +577,11 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
624577 cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap());
625578 }
626579 // Forward rustc arguments.
627 // We need to patch "--extern" filenames because we forced a check-only
628 // build without cargo knowing about that: replace `.rlib` suffix by
629 // `.rmeta`.
630 // We also need to remove `--error-format` as cargo specifies that to be JSON,
580 // We need to remove `--error-format` as cargo specifies that to be JSON,
631581 // but when we run here, cargo does not interpret the JSON any more. `--json`
632582 // then also needs to be dropped.
633 let mut args = info.args.iter();
634 while let Some(arg) = args.next() {
635 if arg == "--extern" {
636 forward_patched_extern_arg(&mut (&mut args).cloned(), &mut cmd);
637 } else if let Some(suffix) = arg.strip_prefix("--error-format") {
583 for arg in &info.args {
584 if let Some(suffix) = arg.strip_prefix("--error-format") {
638585 assert!(suffix.starts_with('='));
639586 // Drop this argument.
640587 } else if let Some(suffix) = arg.strip_prefix("--json") {
......@@ -668,7 +615,7 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
668615 }
669616}
670617
671pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
618pub fn phase_rustdoc(args: impl Iterator<Item = String>) {
672619 let verbose = env::var("MIRI_VERBOSE")
673620 .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
674621
......@@ -676,15 +623,7 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
676623 // of the old value into MIRI_ORIG_RUSTDOC. So that's what we have to invoke now.
677624 let rustdoc = env::var("MIRI_ORIG_RUSTDOC").unwrap_or("rustdoc".to_string());
678625 let mut cmd = Command::new(rustdoc);
679
680 while let Some(arg) = args.next() {
681 if arg == "--extern" {
682 // Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files.
683 forward_patched_extern_arg(&mut args, &mut cmd);
684 } else {
685 cmd.arg(arg);
686 }
687 }
626 cmd.args(args);
688627
689628 // Doctests of `proc-macro` crates (and their dependencies) are always built for the host,
690629 // so we are not able to run them in Miri.
src/tools/miri/cargo-miri/src/setup.rs+1-1
......@@ -160,7 +160,7 @@ pub fn setup(
160160
161161 // Do the build.
162162 let status = SysrootBuilder::new(&sysroot_dir, target)
163 .build_mode(BuildMode::Check)
163 .build_mode(BuildMode::Build) // not a real build, since we use dummy codegen
164164 .rustc_version(rustc_version.clone())
165165 .sysroot_config(sysroot_config)
166166 .rustflags(rustflags)
src/tools/miri/miri-script/src/commands.rs+9-7
......@@ -57,7 +57,9 @@ impl MiriEnv {
5757 .arg("--")
5858 .args(&["miri", "setup", "--print-sysroot"])
5959 .args(target_flag);
60 cmd.set_quiet(quiet);
60 if quiet {
61 cmd = cmd.arg("--quiet");
62 }
6163 let output = cmd.read()?;
6264 self.sh.set_var("MIRI_SYSROOT", &output);
6365 Ok(output.into())
......@@ -112,8 +114,8 @@ impl Command {
112114 Command::Check { features, flags } => Self::check(features, flags),
113115 Command::Test { bless, target, coverage, features, flags } =>
114116 Self::test(bless, target, coverage, features, flags),
115 Command::Run { dep, verbose, target, edition, features, flags } =>
116 Self::run(dep, verbose, target, edition, features, flags),
117 Command::Run { dep, quiet, target, edition, features, flags } =>
118 Self::run(dep, quiet, target, edition, features, flags),
117119 Command::Doc { features, flags } => Self::doc(features, flags),
118120 Command::Fmt { flags } => Self::fmt(flags),
119121 Command::Clippy { features, flags } => Self::clippy(features, flags),
......@@ -458,7 +460,7 @@ impl Command {
458460
459461 fn run(
460462 dep: bool,
461 verbose: bool,
463 quiet: bool,
462464 target: Option<String>,
463465 edition: Option<String>,
464466 features: Vec<String>,
......@@ -468,7 +470,7 @@ impl Command {
468470
469471 // Preparation: get a sysroot, and get the miri binary.
470472 let miri_sysroot =
471 e.build_miri_sysroot(/* quiet */ !verbose, target.as_deref(), &features)?;
473 e.build_miri_sysroot(/* quiet */ quiet, target.as_deref(), &features)?;
472474 let miri_bin = e
473475 .build_get_binary(".", &features)
474476 .context("failed to get filename of miri executable")?;
......@@ -492,7 +494,7 @@ impl Command {
492494 // Compute flags.
493495 let miri_flags = e.sh.var("MIRIFLAGS").unwrap_or_default();
494496 let miri_flags = flagsplit(&miri_flags);
495 let quiet_flag = if verbose { None } else { Some("--quiet") };
497 let quiet_flag = if quiet { Some("--quiet") } else { None };
496498
497499 // Run Miri.
498500 // The basic command that executes the Miri driver.
......@@ -506,7 +508,7 @@ impl Command {
506508 } else {
507509 cmd!(e.sh, "{miri_bin}")
508510 };
509 cmd.set_quiet(!verbose);
511 cmd.set_quiet(quiet);
510512 // Add Miri flags
511513 let mut cmd = cmd.args(&miri_flags).args(&early_flags).args(&flags);
512514 // For `--dep` we also need to set the target in the env var.
src/tools/miri/miri-script/src/main.rs+2-2
......@@ -78,9 +78,9 @@ pub enum Command {
7878 /// Build the program with the dependencies declared in `tests/deps/Cargo.toml`.
7979 #[arg(long)]
8080 dep: bool,
81 /// Show build progress.
81 /// Hide build progress.
8282 #[arg(long, short)]
83 verbose: bool,
83 quiet: bool,
8484 /// The cross-interpretation target.
8585 #[arg(long)]
8686 target: Option<String>,
src/tools/miri/rust-version+1-1
......@@ -1 +1 @@
15f9dd05862d2e4bceb3be1031b6c936e35671501
1ceb7df7e6f17c92c7d49f7e4f02df0e68bc9b38b
src/tools/miri/src/bin/miri.rs+17-23
......@@ -16,7 +16,6 @@ extern crate rustc_hir;
1616extern crate rustc_hir_analysis;
1717extern crate rustc_interface;
1818extern crate rustc_log;
19extern crate rustc_metadata;
2019extern crate rustc_middle;
2120extern crate rustc_session;
2221extern crate rustc_span;
......@@ -26,10 +25,8 @@ mod log;
2625use std::env;
2726use std::num::NonZero;
2827use std::ops::Range;
29use std::path::PathBuf;
3028use std::rc::Rc;
3129use std::str::FromStr;
32use std::sync::Arc;
3330use std::sync::atomic::{AtomicI32, AtomicU32, Ordering};
3431
3532use miri::{
......@@ -51,10 +48,8 @@ use rustc_middle::middle::exported_symbols::{
5148use rustc_middle::query::LocalCrate;
5249use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
5350use rustc_middle::ty::{self, Ty, TyCtxt};
54use rustc_middle::util::Providers;
5551use rustc_session::EarlyDiagCtxt;
5652use rustc_session::config::{CrateType, ErrorOutputType, OptLevel};
57use rustc_session::search_paths::PathKind;
5853use rustc_span::def_id::DefId;
5954
6055use crate::log::setup::{deinit_loggers, init_early_loggers, init_late_loggers};
......@@ -126,21 +121,6 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
126121}
127122
128123impl rustc_driver::Callbacks for MiriCompilerCalls {
129 fn config(&mut self, config: &mut Config) {
130 config.override_queries = Some(|_, providers| {
131 providers.extern_queries.used_crate_source = |tcx, cnum| {
132 let mut providers = Providers::default();
133 rustc_metadata::provide(&mut providers);
134 let mut crate_source = (providers.extern_queries.used_crate_source)(tcx, cnum);
135 // HACK: rustc will emit "crate ... required to be available in rlib format, but
136 // was not found in this form" errors once we use `tcx.dependency_formats()` if
137 // there's no rlib provided, so setting a dummy path here to workaround those errors.
138 Arc::make_mut(&mut crate_source).rlib = Some((PathBuf::new(), PathKind::All));
139 crate_source
140 };
141 });
142 }
143
144124 fn after_analysis<'tcx>(
145125 &mut self,
146126 _: &rustc_interface::interface::Compiler,
......@@ -253,12 +233,26 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
253233 #[allow(rustc::potential_query_instability)] // rustc_codegen_ssa (where this code is copied from) also allows this lint
254234 fn config(&mut self, config: &mut Config) {
255235 if config.opts.prints.is_empty() && self.target_crate {
236 #[allow(rustc::bad_opt_access)] // tcx does not exist yet
237 {
238 let any_crate_types = !config.opts.crate_types.is_empty();
239 // Avoid warnings about unsupported crate types.
240 config
241 .opts
242 .crate_types
243 .retain(|&c| c == CrateType::Executable || c == CrateType::Rlib);
244 if any_crate_types {
245 // Assert that we didn't remove all crate types if any crate type was passed on
246 // the cli. Otherwise we might silently change what kind of crate we are building.
247 assert!(!config.opts.crate_types.is_empty());
248 }
249 }
250
256251 // Queries overridden here affect the data stored in `rmeta` files of dependencies,
257252 // which will be used later in non-`MIRI_BE_RUSTC` mode.
258253 config.override_queries = Some(|_, local_providers| {
259 // `exported_non_generic_symbols` and `reachable_non_generics` provided by rustc always returns
260 // an empty result if `tcx.sess.opts.output_types.should_codegen()` is false.
261 // In addition we need to add #[used] symbols to exported_symbols for `lookup_link_section`.
254 // We need to add #[used] symbols to exported_symbols for `lookup_link_section`.
255 // FIXME handle this somehow in rustc itself to avoid this hack.
262256 local_providers.exported_non_generic_symbols = |tcx, LocalCrate| {
263257 let reachable_set = tcx.with_stable_hashing_context(|hcx| {
264258 tcx.reachable_set(()).to_sorted(&hcx, true)
src/tools/miri/src/borrow_tracker/mod.rs+16-9
......@@ -11,6 +11,22 @@ use crate::*;
1111pub mod stacked_borrows;
1212pub mod tree_borrows;
1313
14/// Indicates which kind of access is being performed.
15#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
16pub enum AccessKind {
17 Read,
18 Write,
19}
20
21impl fmt::Display for AccessKind {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 AccessKind::Read => write!(f, "read access"),
25 AccessKind::Write => write!(f, "write access"),
26 }
27 }
28}
29
1430/// Tracking pointer provenance
1531#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1632pub struct BorTag(NonZero<u64>);
......@@ -115,15 +131,6 @@ impl VisitProvenance for GlobalStateInner {
115131/// We need interior mutable access to the global state.
116132pub type GlobalState = RefCell<GlobalStateInner>;
117133
118impl fmt::Display for AccessKind {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 match self {
121 AccessKind::Read => write!(f, "read access"),
122 AccessKind::Write => write!(f, "write access"),
123 }
124 }
125}
126
127134/// Policy on whether to recurse into fields to retag
128135#[derive(Copy, Clone, Debug)]
129136pub enum RetagFields {
src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs+1-1
......@@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashSet;
55use rustc_span::{Span, SpanData};
66use smallvec::SmallVec;
77
8use crate::borrow_tracker::{GlobalStateInner, ProtectorKind};
8use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind};
99use crate::*;
1010
1111/// Error reporting
src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs+1-1
......@@ -21,7 +21,7 @@ pub use self::stack::Stack;
2121use crate::borrow_tracker::stacked_borrows::diagnostics::{
2222 AllocHistory, DiagnosticCx, DiagnosticCxBuilder,
2323};
24use crate::borrow_tracker::{GlobalStateInner, ProtectorKind};
24use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind};
2525use crate::concurrency::data_race::{NaReadType, NaWriteType};
2626use crate::*;
2727
src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs+1-1
......@@ -4,10 +4,10 @@ use std::ops::Range;
44use rustc_data_structures::fx::FxHashMap;
55use rustc_span::{Span, SpanData};
66
7use crate::borrow_tracker::ProtectorKind;
87use crate::borrow_tracker::tree_borrows::perms::{PermTransition, Permission};
98use crate::borrow_tracker::tree_borrows::tree::LocationState;
109use crate::borrow_tracker::tree_borrows::unimap::UniIndex;
10use crate::borrow_tracker::{AccessKind, ProtectorKind};
1111use crate::*;
1212
1313/// Cause of an access: either a real access or one
src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs+1-1
......@@ -5,7 +5,7 @@ use rustc_middle::ty::{self, Ty};
55
66use self::foreign_access_skipping::IdempotentForeignAccess;
77use self::tree::LocationState;
8use crate::borrow_tracker::{GlobalState, GlobalStateInner, ProtectorKind};
8use crate::borrow_tracker::{AccessKind, GlobalState, GlobalStateInner, ProtectorKind};
99use crate::concurrency::data_race::NaReadType;
1010use crate::*;
1111
src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs+1-1
......@@ -1,7 +1,7 @@
11use std::cmp::{Ordering, PartialOrd};
22use std::fmt;
33
4use crate::AccessKind;
4use crate::borrow_tracker::AccessKind;
55use crate::borrow_tracker::tree_borrows::diagnostics::TransitionError;
66use crate::borrow_tracker::tree_borrows::tree::AccessRelatedness;
77
src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs+1-1
......@@ -25,7 +25,7 @@ use crate::borrow_tracker::tree_borrows::diagnostics::{
2525use crate::borrow_tracker::tree_borrows::foreign_access_skipping::IdempotentForeignAccess;
2626use crate::borrow_tracker::tree_borrows::perms::PermTransition;
2727use crate::borrow_tracker::tree_borrows::unimap::{UniIndex, UniKeyMap, UniValMap};
28use crate::borrow_tracker::{GlobalState, ProtectorKind};
28use crate::borrow_tracker::{AccessKind, GlobalState, ProtectorKind};
2929use crate::*;
3030
3131mod tests;
src/tools/miri/src/concurrency/init_once.rs+4
......@@ -57,6 +57,10 @@ impl InitOnceRef {
5757 pub fn begin(&self) {
5858 self.0.borrow_mut().begin();
5959 }
60
61 pub fn queue_is_empty(&self) -> bool {
62 self.0.borrow().waiters.is_empty()
63 }
6064}
6165
6266impl VisitProvenance for InitOnceRef {
src/tools/miri/src/concurrency/sync.rs+156-85
......@@ -1,3 +1,4 @@
1use std::any::Any;
12use std::cell::RefCell;
23use std::collections::VecDeque;
34use std::collections::hash_map::Entry;
......@@ -5,6 +6,7 @@ use std::default::Default;
56use std::ops::Not;
67use std::rc::Rc;
78use std::time::Duration;
9use std::{fmt, iter};
810
911use rustc_abi::Size;
1012use rustc_data_structures::fx::FxHashMap;
......@@ -12,6 +14,52 @@ use rustc_data_structures::fx::FxHashMap;
1214use super::vector_clock::VClock;
1315use crate::*;
1416
17/// Indicates which kind of access is being performed.
18#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
19pub enum AccessKind {
20 Read,
21 Write,
22 Dealloc,
23}
24
25impl fmt::Display for AccessKind {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 match self {
28 AccessKind::Read => write!(f, "read"),
29 AccessKind::Write => write!(f, "write"),
30 AccessKind::Dealloc => write!(f, "deallocation"),
31 }
32 }
33}
34
35/// A trait for the synchronization metadata that can be attached to a memory location.
36pub trait SyncObj: Any {
37 /// Determines whether reads/writes to this object's location are currently permitted.
38 fn on_access<'tcx>(&self, _access_kind: AccessKind) -> InterpResult<'tcx> {
39 interp_ok(())
40 }
41
42 /// Determines whether this object's metadata shall be deleted when a write to its
43 /// location occurs.
44 fn delete_on_write(&self) -> bool {
45 false
46 }
47}
48
49impl dyn SyncObj {
50 #[inline(always)]
51 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
52 let x: &dyn Any = self;
53 x.downcast_ref()
54 }
55}
56
57impl fmt::Debug for dyn SyncObj {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 f.debug_struct("SyncObj").finish_non_exhaustive()
60 }
61}
62
1563/// The mutex state.
1664#[derive(Default, Debug)]
1765struct Mutex {
......@@ -37,6 +85,10 @@ impl MutexRef {
3785 pub fn owner(&self) -> Option<ThreadId> {
3886 self.0.borrow().owner
3987 }
88
89 pub fn queue_is_empty(&self) -> bool {
90 self.0.borrow().queue.is_empty()
91 }
4092}
4193
4294impl VisitProvenance for MutexRef {
......@@ -113,6 +165,11 @@ impl RwLockRef {
113165 pub fn is_write_locked(&self) -> bool {
114166 self.0.borrow().is_write_locked()
115167 }
168
169 pub fn queue_is_empty(&self) -> bool {
170 let inner = self.0.borrow();
171 inner.reader_queue.is_empty() && inner.writer_queue.is_empty()
172 }
116173}
117174
118175impl VisitProvenance for RwLockRef {
......@@ -140,8 +197,8 @@ impl CondvarRef {
140197 Self(Default::default())
141198 }
142199
143 pub fn is_awaited(&self) -> bool {
144 !self.0.borrow().waiters.is_empty()
200 pub fn queue_is_empty(&self) -> bool {
201 self.0.borrow().waiters.is_empty()
145202 }
146203}
147204
......@@ -214,127 +271,141 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
214271
215272impl<'tcx> AllocExtra<'tcx> {
216273 fn get_sync<T: 'static>(&self, offset: Size) -> Option<&T> {
217 self.sync.get(&offset).and_then(|s| s.downcast_ref::<T>())
274 self.sync_objs.get(&offset).and_then(|s| s.downcast_ref::<T>())
218275 }
219276}
220277
221/// We designate an `init`` field in all primitives.
222/// If `init` is set to this, we consider the primitive initialized.
223pub const LAZY_INIT_COOKIE: u32 = 0xcafe_affe;
224
225// Public interface to synchronization primitives. Please note that in most
278// Public interface to synchronization objects. Please note that in most
226279// cases, the function calls are infallible and it is the client's (shim
227280// implementation's) responsibility to detect and deal with erroneous
228281// situations.
229282impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
230283pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
231 /// Helper for lazily initialized `alloc_extra.sync` data:
232 /// this forces an immediate init.
233 /// Return a reference to the data in the machine state.
234 fn lazy_sync_init<'a, T: 'static>(
284 /// Get the synchronization object associated with the given pointer,
285 /// or initialize a new one.
286 ///
287 /// Return `None` if this pointer does not point to at least 1 byte of mutable memory.
288 fn get_sync_or_init<'a, T: SyncObj>(
235289 &'a mut self,
236 primitive: &MPlaceTy<'tcx>,
237 init_offset: Size,
238 data: T,
239 ) -> InterpResult<'tcx, &'a T>
290 ptr: Pointer,
291 new: impl FnOnce(&'a mut MiriMachine<'tcx>) -> T,
292 ) -> Option<&'a T>
240293 where
241294 'tcx: 'a,
242295 {
243296 let this = self.eval_context_mut();
297 if !this.ptr_try_get_alloc_id(ptr, 0).ok().is_some_and(|(alloc_id, offset, ..)| {
298 let info = this.get_alloc_info(alloc_id);
299 info.kind == AllocKind::LiveData && info.mutbl.is_mut() && offset < info.size
300 }) {
301 return None;
302 }
303 // This cannot fail now.
304 let (alloc, offset, _) = this.ptr_get_alloc_id(ptr, 0).unwrap();
305 let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc).unwrap();
306 // Due to borrow checker reasons, we have to do the lookup twice.
307 if alloc_extra.get_sync::<T>(offset).is_none() {
308 let new = new(machine);
309 alloc_extra.sync_objs.insert(offset, Box::new(new));
310 }
311 Some(alloc_extra.get_sync::<T>(offset).unwrap())
312 }
244313
245 let (alloc, offset, _) = this.ptr_get_alloc_id(primitive.ptr(), 0)?;
246 let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc)?;
247 alloc_extra.sync.insert(offset, Box::new(data));
248 // Mark this as "initialized".
249 let init_field = primitive.offset(init_offset, this.machine.layouts.u32, this)?;
250 this.write_scalar_atomic(
251 Scalar::from_u32(LAZY_INIT_COOKIE),
252 &init_field,
253 AtomicWriteOrd::Relaxed,
254 )?;
255 interp_ok(this.get_alloc_extra(alloc)?.get_sync::<T>(offset).unwrap())
256 }
257
258 /// Helper for lazily initialized `alloc_extra.sync` data:
259 /// Checks if the primitive is initialized:
260 /// - If yes, fetches the data from `alloc_extra.sync`, or calls `missing_data` if that fails
261 /// and stores that in `alloc_extra.sync`.
262 /// - Otherwise, calls `new_data` to initialize the primitive.
314 /// Helper for "immovable" synchronization objects: the expected protocol for these objects is
315 /// that they use a static initializer of `uninit_val`, and we set them to `init_val` upon
316 /// initialization. At that point we also register a synchronization object, which is expected
317 /// to have `delete_on_write() == true`. So in the future, if we still see the object, we know
318 /// the location must still contain `init_val`. If the object is copied somewhere, that will
319 /// show up as a non-`init_val` value without a synchronization object, which we can then use to
320 /// error.
263321 ///
264 /// Return a reference to the data in the machine state.
265 fn lazy_sync_get_data<'a, T: 'static>(
322 /// `new_meta_obj` gets invoked when there is not yet an initialization object.
323 /// It has to ensure that the in-memory representation indeed matches `uninit_val`.
324 ///
325 /// The point of storing an `init_val` is so that if this memory gets copied somewhere else,
326 /// it does not look like the static initializer (i.e., `uninit_val`) any more. For some
327 /// objects we could just entirely forbid reading their bytes to ensure they don't get copied,
328 /// but that does not work for objects without a destructor (Windows `InitOnce`, macOS
329 /// `os_unfair_lock`).
330 fn get_immovable_sync_with_static_init<'a, T: SyncObj>(
266331 &'a mut self,
267 primitive: &MPlaceTy<'tcx>,
332 obj: &MPlaceTy<'tcx>,
268333 init_offset: Size,
269 missing_data: impl FnOnce() -> InterpResult<'tcx, T>,
270 new_data: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>,
334 uninit_val: u8,
335 init_val: u8,
336 new_meta_obj: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>,
271337 ) -> InterpResult<'tcx, &'a T>
272338 where
273339 'tcx: 'a,
274340 {
341 assert!(init_val != uninit_val);
275342 let this = self.eval_context_mut();
343 this.check_ptr_access(obj.ptr(), obj.layout.size, CheckInAllocMsg::Dereferenceable)?;
344 assert!(init_offset < obj.layout.size); // ensure our 1-byte flag fits
345 let init_field = obj.offset(init_offset, this.machine.layouts.u8, this)?;
346
347 let (alloc, offset, _) = this.ptr_get_alloc_id(init_field.ptr(), 0)?;
348 let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc)?;
349 // Due to borrow checker reasons, we have to do the lookup twice.
350 if alloc_extra.get_sync::<T>(offset).is_some() {
351 let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc).unwrap();
352 return interp_ok(alloc_extra.get_sync::<T>(offset).unwrap());
353 }
276354
277 // Check if this is already initialized. Needs to be atomic because we can race with another
278 // thread initializing. Needs to be an RMW operation to ensure we read the *latest* value.
279 // So we just try to replace MUTEX_INIT_COOKIE with itself.
280 let init_cookie = Scalar::from_u32(LAZY_INIT_COOKIE);
281 let init_field = primitive.offset(init_offset, this.machine.layouts.u32, this)?;
282 let (_init, success) = this
355 // There's no sync object there yet. Create one, and try a CAS for uninit_val to init_val.
356 let meta_obj = new_meta_obj(this)?;
357 let (old_init, success) = this
283358 .atomic_compare_exchange_scalar(
284359 &init_field,
285 &ImmTy::from_scalar(init_cookie, this.machine.layouts.u32),
286 init_cookie,
360 &ImmTy::from_scalar(Scalar::from_u8(uninit_val), this.machine.layouts.u8),
361 Scalar::from_u8(init_val),
287362 AtomicRwOrd::Relaxed,
288363 AtomicReadOrd::Relaxed,
289364 /* can_fail_spuriously */ false,
290365 )?
291366 .to_scalar_pair();
292
293 if success.to_bool()? {
294 // If it is initialized, it must be found in the "sync primitive" table,
295 // or else it has been moved illegally.
296 let (alloc, offset, _) = this.ptr_get_alloc_id(primitive.ptr(), 0)?;
297 let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc)?;
298 // Due to borrow checker reasons, we have to do the lookup twice.
299 if alloc_extra.get_sync::<T>(offset).is_none() {
300 let data = missing_data()?;
301 alloc_extra.sync.insert(offset, Box::new(data));
302 }
303 interp_ok(alloc_extra.get_sync::<T>(offset).unwrap())
304 } else {
305 let data = new_data(this)?;
306 this.lazy_sync_init(primitive, init_offset, data)
367 if !success.to_bool()? {
368 // This can happen for the macOS lock if it is already marked as initialized.
369 assert_eq!(
370 old_init.to_u8()?,
371 init_val,
372 "`new_meta_obj` should have ensured that this CAS succeeds"
373 );
307374 }
375
376 let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc).unwrap();
377 assert!(meta_obj.delete_on_write());
378 alloc_extra.sync_objs.insert(offset, Box::new(meta_obj));
379 interp_ok(alloc_extra.get_sync::<T>(offset).unwrap())
308380 }
309381
310 /// Get the synchronization primitive associated with the given pointer,
311 /// or initialize a new one.
312 ///
313 /// Return `None` if this pointer does not point to at least 1 byte of mutable memory.
314 fn get_sync_or_init<'a, T: 'static>(
382 /// Explicitly initializes an object that would usually be implicitly initialized with
383 /// `get_immovable_sync_with_static_init`.
384 fn init_immovable_sync<'a, T: SyncObj>(
315385 &'a mut self,
316 ptr: Pointer,
317 new: impl FnOnce(&'a mut MiriMachine<'tcx>) -> T,
318 ) -> Option<&'a T>
386 obj: &MPlaceTy<'tcx>,
387 init_offset: Size,
388 init_val: u8,
389 new_meta_obj: T,
390 ) -> InterpResult<'tcx, Option<&'a T>>
319391 where
320392 'tcx: 'a,
321393 {
322394 let this = self.eval_context_mut();
323 if !this.ptr_try_get_alloc_id(ptr, 0).ok().is_some_and(|(alloc_id, offset, ..)| {
324 let info = this.get_alloc_info(alloc_id);
325 info.kind == AllocKind::LiveData && info.mutbl.is_mut() && offset < info.size
326 }) {
327 return None;
328 }
329 // This cannot fail now.
330 let (alloc, offset, _) = this.ptr_get_alloc_id(ptr, 0).unwrap();
331 let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc).unwrap();
332 // Due to borrow checker reasons, we have to do the lookup twice.
333 if alloc_extra.get_sync::<T>(offset).is_none() {
334 let new = new(machine);
335 alloc_extra.sync.insert(offset, Box::new(new));
336 }
337 Some(alloc_extra.get_sync::<T>(offset).unwrap())
395 this.check_ptr_access(obj.ptr(), obj.layout.size, CheckInAllocMsg::Dereferenceable)?;
396 assert!(init_offset < obj.layout.size); // ensure our 1-byte flag fits
397 let init_field = obj.offset(init_offset, this.machine.layouts.u8, this)?;
398
399 // Zero the entire object, and then store `init_val` directly.
400 this.write_bytes_ptr(obj.ptr(), iter::repeat_n(0, obj.layout.size.bytes_usize()))?;
401 this.write_scalar(Scalar::from_u8(init_val), &init_field)?;
402
403 // Create meta-level initialization object.
404 let (alloc, offset, _) = this.ptr_get_alloc_id(init_field.ptr(), 0)?;
405 let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc).unwrap();
406 assert!(new_meta_obj.delete_on_write());
407 alloc_extra.sync_objs.insert(offset, Box::new(new_meta_obj));
408 interp_ok(Some(alloc_extra.get_sync::<T>(offset).unwrap()))
338409 }
339410
340411 /// Lock by setting the mutex owner and increasing the lock count.
src/tools/miri/src/diagnostics.rs+1-1
......@@ -128,7 +128,7 @@ pub enum NonHaltingDiagnostic {
128128 PoppedPointerTag(Item, String),
129129 TrackingAlloc(AllocId, Size, Align),
130130 FreedAlloc(AllocId),
131 AccessedAlloc(AllocId, AllocRange, AccessKind),
131 AccessedAlloc(AllocId, AllocRange, borrow_tracker::AccessKind),
132132 RejectedIsolatedOp(String),
133133 ProgressReport {
134134 block_count: u64, // how many basic blocks have been run so far
src/tools/miri/src/helpers.rs-7
......@@ -22,13 +22,6 @@ use rustc_symbol_mangling::mangle_internal_symbol;
2222
2323use crate::*;
2424
25/// Indicates which kind of access is being performed.
26#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
27pub enum AccessKind {
28 Read,
29 Write,
30}
31
3225/// Gets an instance for a path.
3326///
3427/// A `None` namespace indicates we are looking for a module.
src/tools/miri/src/lib.rs+2-1
......@@ -139,7 +139,7 @@ pub use crate::diagnostics::{
139139 EvalContextExt as _, NonHaltingDiagnostic, TerminationInfo, report_error,
140140};
141141pub use crate::eval::{MiriConfig, MiriEntryFnType, create_ecx, eval_entry};
142pub use crate::helpers::{AccessKind, EvalContextExt as _, ToU64 as _, ToUsize as _};
142pub use crate::helpers::{EvalContextExt as _, ToU64 as _, ToUsize as _};
143143pub use crate::intrinsics::EvalContextExt as _;
144144pub use crate::machine::{
145145 AlignmentCheck, AllocExtra, BacktraceStyle, DynMachineCallback, FloatRoundingErrorMode,
......@@ -165,6 +165,7 @@ pub use crate::shims::unwind::{CatchUnwindData, EvalContextExt as _};
165165/// Also disable the MIR pass that inserts an alignment check on every pointer dereference. Miri
166166/// does that too, and with a better error message.
167167pub const MIRI_DEFAULT_ARGS: &[&str] = &[
168 "-Zcodegen-backend=dummy",
168169 "--cfg=miri",
169170 "-Zalways-encode-mir",
170171 "-Zextra-const-ub-checks",
src/tools/miri/src/machine.rs+37-7
......@@ -1,9 +1,9 @@
11//! Global machine state as well as implementation of the interpreter engine
22//! `Machine` trait.
33
4use std::any::Any;
54use std::borrow::Cow;
65use std::cell::{Cell, RefCell};
6use std::collections::BTreeMap;
77use std::path::Path;
88use std::rc::Rc;
99use std::{fmt, process};
......@@ -36,6 +36,7 @@ use rustc_target::spec::Arch;
3636use crate::alloc_addresses::EvalContextExt;
3737use crate::concurrency::cpu_affinity::{self, CpuAffinityMask};
3838use crate::concurrency::data_race::{self, NaReadType, NaWriteType};
39use crate::concurrency::sync::SyncObj;
3940use crate::concurrency::{
4041 AllocDataRaceHandler, GenmcCtx, GenmcEvalContextExt as _, GlobalDataRaceHandler, weak_memory,
4142};
......@@ -399,11 +400,11 @@ pub struct AllocExtra<'tcx> {
399400 /// if this allocation is leakable. The backtrace is not
400401 /// pruned yet; that should be done before printing it.
401402 pub backtrace: Option<Vec<FrameInfo<'tcx>>>,
402 /// Synchronization primitives like to attach extra data to particular addresses. We store that
403 /// Synchronization objects like to attach extra data to particular addresses. We store that
403404 /// inside the relevant allocation, to ensure that everything is removed when the allocation is
404405 /// freed.
405406 /// This maps offsets to synchronization-primitive-specific data.
406 pub sync: FxHashMap<Size, Box<dyn Any>>,
407 pub sync_objs: BTreeMap<Size, Box<dyn SyncObj>>,
407408}
408409
409410// We need a `Clone` impl because the machine passes `Allocation` through `Cow`...
......@@ -416,7 +417,7 @@ impl<'tcx> Clone for AllocExtra<'tcx> {
416417
417418impl VisitProvenance for AllocExtra<'_> {
418419 fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
419 let AllocExtra { borrow_tracker, data_race, backtrace: _, sync: _ } = self;
420 let AllocExtra { borrow_tracker, data_race, backtrace: _, sync_objs: _ } = self;
420421
421422 borrow_tracker.visit_provenance(visit);
422423 data_race.visit_provenance(visit);
......@@ -991,7 +992,12 @@ impl<'tcx> MiriMachine<'tcx> {
991992 .insert(id, (ecx.machine.current_user_relevant_span(), None));
992993 }
993994
994 interp_ok(AllocExtra { borrow_tracker, data_race, backtrace, sync: FxHashMap::default() })
995 interp_ok(AllocExtra {
996 borrow_tracker,
997 data_race,
998 backtrace,
999 sync_objs: BTreeMap::default(),
1000 })
9951001 }
9961002}
9971003
......@@ -1516,7 +1522,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
15161522 machine.emit_diagnostic(NonHaltingDiagnostic::AccessedAlloc(
15171523 alloc_id,
15181524 range,
1519 AccessKind::Read,
1525 borrow_tracker::AccessKind::Read,
15201526 ));
15211527 }
15221528 // The order of checks is deliberate, to prefer reporting a data race over a borrow tracker error.
......@@ -1536,6 +1542,11 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
15361542 if let Some(borrow_tracker) = &alloc_extra.borrow_tracker {
15371543 borrow_tracker.before_memory_read(alloc_id, prov_extra, range, machine)?;
15381544 }
1545 // Check if there are any sync objects that would like to prevent reading this memory.
1546 for (_offset, obj) in alloc_extra.sync_objs.range(range.start..range.end()) {
1547 obj.on_access(concurrency::sync::AccessKind::Read)?;
1548 }
1549
15391550 interp_ok(())
15401551 }
15411552
......@@ -1552,7 +1563,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
15521563 machine.emit_diagnostic(NonHaltingDiagnostic::AccessedAlloc(
15531564 alloc_id,
15541565 range,
1555 AccessKind::Write,
1566 borrow_tracker::AccessKind::Write,
15561567 ));
15571568 }
15581569 match &machine.data_race {
......@@ -1576,6 +1587,20 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
15761587 if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker {
15771588 borrow_tracker.before_memory_write(alloc_id, prov_extra, range, machine)?;
15781589 }
1590 // Delete sync objects that don't like writes.
1591 // Most of the time, we can just skip this.
1592 if !alloc_extra.sync_objs.is_empty() {
1593 let mut to_delete = vec![];
1594 for (offset, obj) in alloc_extra.sync_objs.range(range.start..range.end()) {
1595 obj.on_access(concurrency::sync::AccessKind::Write)?;
1596 if obj.delete_on_write() {
1597 to_delete.push(*offset);
1598 }
1599 }
1600 for offset in to_delete {
1601 alloc_extra.sync_objs.remove(&offset);
1602 }
1603 }
15791604 interp_ok(())
15801605 }
15811606
......@@ -1612,6 +1637,11 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
16121637 if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker {
16131638 borrow_tracker.before_memory_deallocation(alloc_id, prove_extra, size, machine)?;
16141639 }
1640 // Check if there are any sync objects that would like to prevent freeing this memory.
1641 for obj in alloc_extra.sync_objs.values() {
1642 obj.on_access(concurrency::sync::AccessKind::Dealloc)?;
1643 }
1644
16151645 if let Some((_, deallocated_at)) = machine.allocation_spans.borrow_mut().get_mut(&alloc_id)
16161646 {
16171647 *deallocated_at = Some(machine.current_user_relevant_span());
src/tools/miri/src/shims/foreign_items.rs+1-4
......@@ -800,10 +800,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
800800
801801 // Target-specific shims
802802 name if name.starts_with("llvm.x86.")
803 && matches!(
804 this.tcx.sess.target.arch,
805 Arch::X86 | Arch::X86_64
806 ) =>
803 && matches!(this.tcx.sess.target.arch, Arch::X86 | Arch::X86_64) =>
807804 {
808805 return shims::x86::EvalContextExt::emulate_x86_intrinsic(
809806 this, link_name, abi, args, dest,
src/tools/miri/src/shims/unix/freebsd/sync.rs+3-1
......@@ -4,13 +4,15 @@ use core::time::Duration;
44
55use rustc_abi::FieldIdx;
66
7use crate::concurrency::sync::FutexRef;
7use crate::concurrency::sync::{FutexRef, SyncObj};
88use crate::*;
99
1010pub struct FreeBsdFutex {
1111 futex: FutexRef,
1212}
1313
14impl SyncObj for FreeBsdFutex {}
15
1416/// Extended variant of the `timespec` struct.
1517pub struct UmtxTime {
1618 timeout: Duration,
src/tools/miri/src/shims/unix/linux_like/sync.rs+3-1
......@@ -1,4 +1,4 @@
1use crate::concurrency::sync::FutexRef;
1use crate::concurrency::sync::{FutexRef, SyncObj};
22use crate::shims::sig::check_min_vararg_count;
33use crate::*;
44
......@@ -6,6 +6,8 @@ struct LinuxFutex {
66 futex: FutexRef,
77}
88
9impl SyncObj for LinuxFutex {}
10
911/// Implementation of the SYS_futex syscall.
1012/// `args` is the arguments *including* the syscall number.
1113pub fn futex<'tcx>(
src/tools/miri/src/shims/unix/macos/sync.rs+49-17
......@@ -13,15 +13,32 @@
1313use std::cell::Cell;
1414use std::time::Duration;
1515
16use rustc_abi::Size;
16use rustc_abi::{Endian, FieldIdx, Size};
1717
18use crate::concurrency::sync::FutexRef;
18use crate::concurrency::sync::{AccessKind, FutexRef, SyncObj};
1919use crate::*;
2020
2121#[derive(Clone)]
2222enum MacOsUnfairLock {
23 Poisoned,
2423 Active { mutex_ref: MutexRef },
24 PermanentlyLocked,
25}
26
27impl SyncObj for MacOsUnfairLock {
28 fn on_access<'tcx>(&self, access_kind: AccessKind) -> InterpResult<'tcx> {
29 if let MacOsUnfairLock::Active { mutex_ref } = self
30 && !mutex_ref.queue_is_empty()
31 {
32 throw_ub_format!(
33 "{access_kind} of `os_unfair_lock` is forbidden while the queue is non-empty"
34 );
35 }
36 interp_ok(())
37 }
38
39 fn delete_on_write(&self) -> bool {
40 true
41 }
2542}
2643
2744pub enum MacOsFutexTimeout<'a, 'tcx> {
......@@ -44,6 +61,8 @@ struct MacOsFutex {
4461 shared: Cell<bool>,
4562}
4663
64impl SyncObj for MacOsFutex {}
65
4766impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
4867trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
4968 fn os_unfair_lock_get_data<'a>(
......@@ -53,22 +72,35 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
5372 where
5473 'tcx: 'a,
5574 {
75 // `os_unfair_lock_s` wraps a single `u32` field. We use the first byte to store the "init"
76 // flag. Due to macOS always being little endian, that's the least significant byte.
5677 let this = self.eval_context_mut();
78 assert!(this.tcx.data_layout.endian == Endian::Little);
79
5780 let lock = this.deref_pointer_as(lock_ptr, this.libc_ty_layout("os_unfair_lock_s"))?;
58 this.lazy_sync_get_data(
81 this.get_immovable_sync_with_static_init(
5982 &lock,
6083 Size::ZERO, // offset for init tracking
61 || {
62 // If we get here, due to how we reset things to zero in `os_unfair_lock_unlock`,
63 // this means the lock was moved while locked. This can happen with a `std` lock,
64 // but then any future attempt to unlock will just deadlock. In practice, terrible
65 // things can probably happen if you swap two locked locks, since they'd wake up
66 // from the wrong queue... we just won't catch all UB of this library API then (we
67 // would need to store some unique identifer in-memory for this, instead of a static
68 // LAZY_INIT_COOKIE). This can't be hit via `std::sync::Mutex`.
69 interp_ok(MacOsUnfairLock::Poisoned)
84 /* uninit_val */ 0,
85 /* init_val */ 1,
86 |this| {
87 let field = this.project_field(&lock, FieldIdx::from_u32(0))?;
88 let val = this.read_scalar(&field)?.to_u32()?;
89 if val == 0 {
90 interp_ok(MacOsUnfairLock::Active { mutex_ref: MutexRef::new() })
91 } else if val == 1 {
92 // This is a lock that got copied while it is initialized. We de-initialize
93 // locks when they get released, so it got copied while locked. Unfortunately
94 // that is something `std` needs to support (the guard could have been leaked).
95 // On the plus side, we know nobody was queued for the lock while it got copied;
96 // that would have been rejected by our `on_access`. So we behave like a
97 // futex-based lock would in this case: any attempt to acquire the lock will
98 // just wait forever, since there's nobody to wake us up.
99 interp_ok(MacOsUnfairLock::PermanentlyLocked)
100 } else {
101 throw_ub_format!("`os_unfair_lock` was not properly initialized at this location, or it got overwritten");
102 }
70103 },
71 |_| interp_ok(MacOsUnfairLock::Active { mutex_ref: MutexRef::new() }),
72104 )
73105 }
74106}
......@@ -332,7 +364,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
332364 let this = self.eval_context_mut();
333365
334366 let MacOsUnfairLock::Active { mutex_ref } = this.os_unfair_lock_get_data(lock_op)? else {
335 // The lock is poisoned, who knows who owns it... we'll pretend: someone else.
367 // A perma-locked lock is definitely not held by us.
336368 throw_machine_stop!(TerminationInfo::Abort(
337369 "attempted to unlock an os_unfair_lock not owned by the current thread".to_owned()
338370 ));
......@@ -361,7 +393,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
361393 let this = self.eval_context_mut();
362394
363395 let MacOsUnfairLock::Active { mutex_ref } = this.os_unfair_lock_get_data(lock_op)? else {
364 // The lock is poisoned, who knows who owns it... we'll pretend: someone else.
396 // A perma-locked lock is definitely not held by us.
365397 throw_machine_stop!(TerminationInfo::Abort(
366398 "called os_unfair_lock_assert_owner on an os_unfair_lock not owned by the current thread".to_owned()
367399 ));
......@@ -383,7 +415,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
383415 let this = self.eval_context_mut();
384416
385417 let MacOsUnfairLock::Active { mutex_ref } = this.os_unfair_lock_get_data(lock_op)? else {
386 // The lock is poisoned, who knows who owns it... we'll pretend: someone else.
418 // A perma-locked lock is definitely not held by us.
387419 return interp_ok(());
388420 };
389421 let mutex_ref = mutex_ref.clone();
src/tools/miri/src/shims/unix/sync.rs+108-65
......@@ -1,13 +1,11 @@
11use rustc_abi::Size;
22
3use crate::concurrency::sync::LAZY_INIT_COOKIE;
3use crate::concurrency::sync::{AccessKind, SyncObj};
44use crate::*;
55
6/// Do a bytewise comparison of the two places, using relaxed atomic reads. This is used to check if
6/// Do a bytewise comparison of the two places. This is used to check if
77/// a synchronization primitive matches its static initializer value.
8///
9/// The reads happen in chunks of 4, so all racing accesses must also use that access size.
10fn bytewise_equal_atomic_relaxed<'tcx>(
8fn bytewise_equal<'tcx>(
119 ecx: &MiriInterpCx<'tcx>,
1210 left: &MPlaceTy<'tcx>,
1311 right: &MPlaceTy<'tcx>,
......@@ -15,25 +13,16 @@ fn bytewise_equal_atomic_relaxed<'tcx>(
1513 let size = left.layout.size;
1614 assert_eq!(size, right.layout.size);
1715
18 // We do this in chunks of 4, so that we are okay to race with (sufficiently aligned)
19 // 4-byte atomic accesses.
20 assert!(size.bytes().is_multiple_of(4));
21 for i in 0..(size.bytes() / 4) {
22 let offset = Size::from_bytes(i.strict_mul(4));
23 let load = |place: &MPlaceTy<'tcx>| {
24 let byte = place.offset(offset, ecx.machine.layouts.u32, ecx)?;
25 ecx.read_scalar_atomic(&byte, AtomicReadOrd::Relaxed)?.to_u32()
26 };
27 let left = load(left)?;
28 let right = load(right)?;
29 if left != right {
30 return interp_ok(false);
31 }
32 }
16 let left_bytes = ecx.read_bytes_ptr_strip_provenance(left.ptr(), size)?;
17 let right_bytes = ecx.read_bytes_ptr_strip_provenance(right.ptr(), size)?;
3318
34 interp_ok(true)
19 interp_ok(left_bytes == right_bytes)
3520}
3621
22// The in-memory marker values we use to indicate whether objects have been initialized.
23const PTHREAD_UNINIT: u8 = 0;
24const PTHREAD_INIT: u8 = 1;
25
3726// # pthread_mutexattr_t
3827// We store some data directly inside the type, ignoring the platform layout:
3928// - kind: i32
......@@ -103,7 +92,7 @@ fn mutexattr_translate_kind<'tcx>(
10392
10493// # pthread_mutex_t
10594// We store some data directly inside the type, ignoring the platform layout:
106// - init: u32
95// - init: u8
10796
10897/// The mutex kind.
10998#[derive(Debug, Clone, Copy)]
......@@ -120,6 +109,21 @@ struct PthreadMutex {
120109 kind: MutexKind,
121110}
122111
112impl SyncObj for PthreadMutex {
113 fn on_access<'tcx>(&self, access_kind: AccessKind) -> InterpResult<'tcx> {
114 if !self.mutex_ref.queue_is_empty() {
115 throw_ub_format!(
116 "{access_kind} of `pthread_mutex_t` is forbidden while the queue is non-empty"
117 );
118 }
119 interp_ok(())
120 }
121
122 fn delete_on_write(&self) -> bool {
123 true
124 }
125}
126
123127/// To ensure an initialized mutex that was moved somewhere else can be distinguished from
124128/// a statically initialized mutex that is used the first time, we pick some offset within
125129/// `pthread_mutex_t` and use it as an "initialized" flag.
......@@ -138,11 +142,11 @@ fn mutex_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size>
138142 let check_static_initializer = |name| {
139143 let static_initializer = ecx.eval_path(&["libc", name]);
140144 let init_field =
141 static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap();
142 let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap();
143 assert_ne!(
144 init, LAZY_INIT_COOKIE,
145 "{name} is incompatible with our initialization cookie"
145 static_initializer.offset(offset, ecx.machine.layouts.u8, ecx).unwrap();
146 let init = ecx.read_scalar(&init_field).unwrap().to_u8().unwrap();
147 assert_eq!(
148 init, PTHREAD_UNINIT,
149 "{name} is incompatible with our initialization logic"
146150 );
147151 };
148152
......@@ -172,7 +176,7 @@ fn mutex_create<'tcx>(
172176) -> InterpResult<'tcx, PthreadMutex> {
173177 let mutex = ecx.deref_pointer_as(mutex_ptr, ecx.libc_ty_layout("pthread_mutex_t"))?;
174178 let data = PthreadMutex { mutex_ref: MutexRef::new(), kind };
175 ecx.lazy_sync_init(&mutex, mutex_init_offset(ecx)?, data.clone())?;
179 ecx.init_immovable_sync(&mutex, mutex_init_offset(ecx)?, PTHREAD_INIT, data.clone())?;
176180 interp_ok(data)
177181}
178182
......@@ -186,10 +190,11 @@ where
186190 'tcx: 'a,
187191{
188192 let mutex = ecx.deref_pointer_as(mutex_ptr, ecx.libc_ty_layout("pthread_mutex_t"))?;
189 ecx.lazy_sync_get_data(
193 ecx.get_immovable_sync_with_static_init(
190194 &mutex,
191195 mutex_init_offset(ecx)?,
192 || throw_ub_format!("`pthread_mutex_t` can't be moved after first use"),
196 PTHREAD_UNINIT,
197 PTHREAD_INIT,
193198 |ecx| {
194199 let kind = mutex_kind_from_static_initializer(ecx, &mutex)?;
195200 interp_ok(PthreadMutex { mutex_ref: MutexRef::new(), kind })
......@@ -203,8 +208,7 @@ fn mutex_kind_from_static_initializer<'tcx>(
203208 mutex: &MPlaceTy<'tcx>,
204209) -> InterpResult<'tcx, MutexKind> {
205210 // All the static initializers recognized here *must* be checked in `mutex_init_offset`!
206 let is_initializer =
207 |name| bytewise_equal_atomic_relaxed(ecx, mutex, &ecx.eval_path(&["libc", name]));
211 let is_initializer = |name| bytewise_equal(ecx, mutex, &ecx.eval_path(&["libc", name]));
208212
209213 // PTHREAD_MUTEX_INITIALIZER is recognized on all targets.
210214 if is_initializer("PTHREAD_MUTEX_INITIALIZER")? {
......@@ -220,18 +224,35 @@ fn mutex_kind_from_static_initializer<'tcx>(
220224 },
221225 _ => {}
222226 }
223 throw_unsup_format!("unsupported static initializer used for `pthread_mutex_t`");
227 throw_ub_format!(
228 "`pthread_mutex_t` was not properly initialized at this location, or it got overwritten"
229 );
224230}
225231
226232// # pthread_rwlock_t
227233// We store some data directly inside the type, ignoring the platform layout:
228// - init: u32
234// - init: u8
229235
230236#[derive(Debug, Clone)]
231237struct PthreadRwLock {
232238 rwlock_ref: RwLockRef,
233239}
234240
241impl SyncObj for PthreadRwLock {
242 fn on_access<'tcx>(&self, access_kind: AccessKind) -> InterpResult<'tcx> {
243 if !self.rwlock_ref.queue_is_empty() {
244 throw_ub_format!(
245 "{access_kind} of `pthread_rwlock_t` is forbidden while the queue is non-empty"
246 );
247 }
248 interp_ok(())
249 }
250
251 fn delete_on_write(&self) -> bool {
252 true
253 }
254}
255
235256fn rwlock_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> {
236257 let offset = match &*ecx.tcx.sess.target.os {
237258 "linux" | "illumos" | "solaris" | "freebsd" | "android" => 0,
......@@ -245,11 +266,11 @@ fn rwlock_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size
245266 // the `init` field must start out not equal to LAZY_INIT_COOKIE.
246267 if !ecx.machine.pthread_rwlock_sanity.replace(true) {
247268 let static_initializer = ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]);
248 let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap();
249 let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap();
250 assert_ne!(
251 init, LAZY_INIT_COOKIE,
252 "PTHREAD_RWLOCK_INITIALIZER is incompatible with our initialization cookie"
269 let init_field = static_initializer.offset(offset, ecx.machine.layouts.u8, ecx).unwrap();
270 let init = ecx.read_scalar(&init_field).unwrap().to_u8().unwrap();
271 assert_eq!(
272 init, PTHREAD_UNINIT,
273 "PTHREAD_RWLOCK_INITIALIZER is incompatible with our initialization logic"
253274 );
254275 }
255276
......@@ -264,17 +285,20 @@ where
264285 'tcx: 'a,
265286{
266287 let rwlock = ecx.deref_pointer_as(rwlock_ptr, ecx.libc_ty_layout("pthread_rwlock_t"))?;
267 ecx.lazy_sync_get_data(
288 ecx.get_immovable_sync_with_static_init(
268289 &rwlock,
269290 rwlock_init_offset(ecx)?,
270 || throw_ub_format!("`pthread_rwlock_t` can't be moved after first use"),
291 PTHREAD_UNINIT,
292 PTHREAD_INIT,
271293 |ecx| {
272 if !bytewise_equal_atomic_relaxed(
294 if !bytewise_equal(
273295 ecx,
274296 &rwlock,
275297 &ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]),
276298 )? {
277 throw_unsup_format!("unsupported static initializer used for `pthread_rwlock_t`");
299 throw_ub_format!(
300 "`pthread_rwlock_t` was not properly initialized at this location, or it got overwritten"
301 );
278302 }
279303 interp_ok(PthreadRwLock { rwlock_ref: RwLockRef::new() })
280304 },
......@@ -322,7 +346,7 @@ fn condattr_set_clock_id<'tcx>(
322346
323347// # pthread_cond_t
324348// We store some data directly inside the type, ignoring the platform layout:
325// - init: u32
349// - init: u8
326350
327351fn cond_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> {
328352 let offset = match &*ecx.tcx.sess.target.os {
......@@ -337,11 +361,11 @@ fn cond_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size>
337361 // the `init` field must start out not equal to LAZY_INIT_COOKIE.
338362 if !ecx.machine.pthread_condvar_sanity.replace(true) {
339363 let static_initializer = ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]);
340 let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap();
341 let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap();
342 assert_ne!(
343 init, LAZY_INIT_COOKIE,
344 "PTHREAD_COND_INITIALIZER is incompatible with our initialization cookie"
364 let init_field = static_initializer.offset(offset, ecx.machine.layouts.u8, ecx).unwrap();
365 let init = ecx.read_scalar(&init_field).unwrap().to_u8().unwrap();
366 assert_eq!(
367 init, PTHREAD_UNINIT,
368 "PTHREAD_COND_INITIALIZER is incompatible with our initialization logic"
345369 );
346370 }
347371
......@@ -354,6 +378,21 @@ struct PthreadCondvar {
354378 clock: TimeoutClock,
355379}
356380
381impl SyncObj for PthreadCondvar {
382 fn on_access<'tcx>(&self, access_kind: AccessKind) -> InterpResult<'tcx> {
383 if !self.condvar_ref.queue_is_empty() {
384 throw_ub_format!(
385 "{access_kind} of `pthread_cond_t` is forbidden while the queue is non-empty"
386 );
387 }
388 interp_ok(())
389 }
390
391 fn delete_on_write(&self) -> bool {
392 true
393 }
394}
395
357396fn cond_create<'tcx>(
358397 ecx: &mut MiriInterpCx<'tcx>,
359398 cond_ptr: &OpTy<'tcx>,
......@@ -361,7 +400,7 @@ fn cond_create<'tcx>(
361400) -> InterpResult<'tcx, PthreadCondvar> {
362401 let cond = ecx.deref_pointer_as(cond_ptr, ecx.libc_ty_layout("pthread_cond_t"))?;
363402 let data = PthreadCondvar { condvar_ref: CondvarRef::new(), clock };
364 ecx.lazy_sync_init(&cond, cond_init_offset(ecx)?, data.clone())?;
403 ecx.init_immovable_sync(&cond, cond_init_offset(ecx)?, PTHREAD_INIT, data.clone())?;
365404 interp_ok(data)
366405}
367406
......@@ -373,17 +412,20 @@ where
373412 'tcx: 'a,
374413{
375414 let cond = ecx.deref_pointer_as(cond_ptr, ecx.libc_ty_layout("pthread_cond_t"))?;
376 ecx.lazy_sync_get_data(
415 ecx.get_immovable_sync_with_static_init(
377416 &cond,
378417 cond_init_offset(ecx)?,
379 || throw_ub_format!("`pthread_cond_t` can't be moved after first use"),
418 PTHREAD_UNINIT,
419 PTHREAD_INIT,
380420 |ecx| {
381 if !bytewise_equal_atomic_relaxed(
421 if !bytewise_equal(
382422 ecx,
383423 &cond,
384424 &ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]),
385425 )? {
386 throw_unsup_format!("unsupported static initializer used for `pthread_cond_t`");
426 throw_ub_format!(
427 "`pthread_cond_t` was not properly initialized at this location, or it got overwritten"
428 );
387429 }
388430 // This used the static initializer. The clock there is always CLOCK_REALTIME.
389431 interp_ok(PthreadCondvar {
......@@ -575,11 +617,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
575617 throw_ub_format!("destroyed a locked mutex");
576618 }
577619
620 // This write also deletes the interpreter state for this mutex.
578621 // This might lead to false positives, see comment in pthread_mutexattr_destroy
579 this.write_uninit(
580 &this.deref_pointer_as(mutex_op, this.libc_ty_layout("pthread_mutex_t"))?,
581 )?;
582 // FIXME: delete interpreter state associated with this mutex.
622 let mutex_place =
623 this.deref_pointer_as(mutex_op, this.libc_ty_layout("pthread_mutex_t"))?;
624 this.write_uninit(&mutex_place)?;
583625
584626 interp_ok(())
585627 }
......@@ -693,11 +735,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
693735 throw_ub_format!("destroyed a locked rwlock");
694736 }
695737
738 // This write also deletes the interpreter state for this rwlock.
696739 // This might lead to false positives, see comment in pthread_mutexattr_destroy
697 this.write_uninit(
698 &this.deref_pointer_as(rwlock_op, this.libc_ty_layout("pthread_rwlock_t"))?,
699 )?;
700 // FIXME: delete interpreter state associated with this rwlock.
740 let rwlock_place =
741 this.deref_pointer_as(rwlock_op, this.libc_ty_layout("pthread_rwlock_t"))?;
742 this.write_uninit(&rwlock_place)?;
701743
702744 interp_ok(())
703745 }
......@@ -885,13 +927,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
885927 // Reading the field also has the side-effect that we detect double-`destroy`
886928 // since we make the field uninit below.
887929 let condvar = &cond_get_data(this, cond_op)?.condvar_ref;
888 if condvar.is_awaited() {
930 if !condvar.queue_is_empty() {
889931 throw_ub_format!("destroying an awaited conditional variable");
890932 }
891933
934 // This write also deletes the interpreter state for this mutex.
892935 // This might lead to false positives, see comment in pthread_mutexattr_destroy
893 this.write_uninit(&this.deref_pointer_as(cond_op, this.libc_ty_layout("pthread_cond_t"))?)?;
894 // FIXME: delete interpreter state associated with this condvar.
936 let cond_place = this.deref_pointer_as(cond_op, this.libc_ty_layout("pthread_cond_t"))?;
937 this.write_uninit(&cond_place)?;
895938
896939 interp_ok(())
897940 }
src/tools/miri/src/shims/windows/sync.rs+31-8
......@@ -1,9 +1,9 @@
11use std::time::Duration;
22
3use rustc_abi::Size;
3use rustc_abi::{FieldIdx, Size};
44
55use crate::concurrency::init_once::{EvalContextExt as _, InitOnceStatus};
6use crate::concurrency::sync::FutexRef;
6use crate::concurrency::sync::{AccessKind, FutexRef, SyncObj};
77use crate::*;
88
99#[derive(Clone)]
......@@ -11,14 +11,31 @@ struct WindowsInitOnce {
1111 init_once: InitOnceRef,
1212}
1313
14impl SyncObj for WindowsInitOnce {
15 fn on_access<'tcx>(&self, access_kind: AccessKind) -> InterpResult<'tcx> {
16 if !self.init_once.queue_is_empty() {
17 throw_ub_format!(
18 "{access_kind} of `INIT_ONCE` is forbidden while the queue is non-empty"
19 );
20 }
21 interp_ok(())
22 }
23
24 fn delete_on_write(&self) -> bool {
25 true
26 }
27}
28
1429struct WindowsFutex {
1530 futex: FutexRef,
1631}
1732
33impl SyncObj for WindowsFutex {}
34
1835impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
1936trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
2037 // Windows sync primitives are pointer sized.
21 // We only use the first 4 bytes for the id.
38 // We only use the first byte for the "init" flag.
2239
2340 fn init_once_get_data<'a>(
2441 &'a mut self,
......@@ -33,13 +50,19 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
3350 this.deref_pointer_as(init_once_ptr, this.windows_ty_layout("INIT_ONCE"))?;
3451 let init_offset = Size::ZERO;
3552
36 this.lazy_sync_get_data(
53 this.get_immovable_sync_with_static_init(
3754 &init_once,
3855 init_offset,
39 || throw_ub_format!("`INIT_ONCE` can't be moved after first use"),
40 |_| {
41 // TODO: check that this is still all-zero.
42 interp_ok(WindowsInitOnce { init_once: InitOnceRef::new() })
56 /* uninit_val */ 0,
57 /* init_val */ 1,
58 |this| {
59 let ptr_field = this.project_field(&init_once, FieldIdx::from_u32(0))?;
60 let val = this.read_target_usize(&ptr_field)?;
61 if val == 0 {
62 interp_ok(WindowsInitOnce { init_once: InitOnceRef::new() })
63 } else {
64 throw_ub_format!("`INIT_ONCE` was not properly initialized at this location, or it got overwritten");
65 }
4366 },
4467 )
4568 }
src/tools/miri/src/shims/x86/avx.rs+10-36
......@@ -1,14 +1,12 @@
11use rustc_abi::CanonAbi;
22use rustc_apfloat::ieee::{Double, Single};
3use rustc_middle::mir;
43use rustc_middle::ty::Ty;
54use rustc_span::Symbol;
65use rustc_target::callconv::FnAbi;
76
87use super::{
98 FloatBinOp, FloatUnaryOp, bin_op_simd_float_all, conditional_dot_product, convert_float_to_int,
10 horizontal_bin_op, mask_load, mask_store, round_all, test_bits_masked, test_high_bits_masked,
11 unary_op_ps,
9 mask_load, mask_store, round_all, test_bits_masked, test_high_bits_masked, unary_op_ps,
1210};
1311use crate::*;
1412
......@@ -93,21 +91,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
9391
9492 conditional_dot_product(this, left, right, imm, dest)?;
9593 }
96 // Used to implement the _mm256_h{add,sub}_p{s,d} functions.
97 // Horizontally add/subtract adjacent floating point values
98 // in `left` and `right`.
99 "hadd.ps.256" | "hadd.pd.256" | "hsub.ps.256" | "hsub.pd.256" => {
100 let [left, right] =
101 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
102
103 let which = match unprefixed_name {
104 "hadd.ps.256" | "hadd.pd.256" => mir::BinOp::Add,
105 "hsub.ps.256" | "hsub.pd.256" => mir::BinOp::Sub,
106 _ => unreachable!(),
107 };
108
109 horizontal_bin_op(this, which, /*saturating*/ false, left, right, dest)?;
110 }
11194 // Used to implement the _mm256_cmp_ps function.
11295 // Performs a comparison operation on each component of `left`
11396 // and `right`. For each component, returns 0 if false or u32::MAX
......@@ -251,40 +234,31 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
251234 // Unaligned copy, which is what we want.
252235 this.mem_copy(src_ptr, dest.ptr(), dest.layout.size, /*nonoverlapping*/ true)?;
253236 }
254 // Used to implement the _mm256_testz_si256, _mm256_testc_si256 and
255 // _mm256_testnzc_si256 functions.
256 // Tests `op & mask == 0`, `op & mask == mask` or
257 // `op & mask != 0 && op & mask != mask`
258 "ptestz.256" | "ptestc.256" | "ptestnzc.256" => {
237 // Used to implement the _mm256_testnzc_si256 function.
238 // Tests `op & mask != 0 && op & mask != mask`
239 "ptestnzc.256" => {
259240 let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
260241
261242 let (all_zero, masked_set) = test_bits_masked(this, op, mask)?;
262 let res = match unprefixed_name {
263 "ptestz.256" => all_zero,
264 "ptestc.256" => masked_set,
265 "ptestnzc.256" => !all_zero && !masked_set,
266 _ => unreachable!(),
267 };
243 let res = !all_zero && !masked_set;
268244
269245 this.write_scalar(Scalar::from_i32(res.into()), dest)?;
270246 }
271247 // Used to implement the _mm256_testz_pd, _mm256_testc_pd, _mm256_testnzc_pd
272 // _mm_testz_pd, _mm_testc_pd, _mm_testnzc_pd, _mm256_testz_ps,
273 // _mm256_testc_ps, _mm256_testnzc_ps, _mm_testz_ps, _mm_testc_ps and
248 // _mm_testnzc_pd, _mm256_testz_ps, _mm256_testc_ps, _mm256_testnzc_ps and
274249 // _mm_testnzc_ps functions.
275250 // Calculates two booleans:
276251 // `direct`, which is true when the highest bit of each element of `op & mask` is zero.
277252 // `negated`, which is true when the highest bit of each element of `!op & mask` is zero.
278253 // Return `direct` (testz), `negated` (testc) or `!direct & !negated` (testnzc)
279 "vtestz.pd.256" | "vtestc.pd.256" | "vtestnzc.pd.256" | "vtestz.pd" | "vtestc.pd"
280 | "vtestnzc.pd" | "vtestz.ps.256" | "vtestc.ps.256" | "vtestnzc.ps.256"
281 | "vtestz.ps" | "vtestc.ps" | "vtestnzc.ps" => {
254 "vtestz.pd.256" | "vtestc.pd.256" | "vtestnzc.pd.256" | "vtestnzc.pd"
255 | "vtestz.ps.256" | "vtestc.ps.256" | "vtestnzc.ps.256" | "vtestnzc.ps" => {
282256 let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
283257
284258 let (direct, negated) = test_high_bits_masked(this, op, mask)?;
285259 let res = match unprefixed_name {
286 "vtestz.pd.256" | "vtestz.pd" | "vtestz.ps.256" | "vtestz.ps" => direct,
287 "vtestc.pd.256" | "vtestc.pd" | "vtestc.ps.256" | "vtestc.ps" => negated,
260 "vtestz.pd.256" | "vtestz.ps.256" => direct,
261 "vtestc.pd.256" | "vtestc.ps.256" => negated,
288262 "vtestnzc.pd.256" | "vtestnzc.pd" | "vtestnzc.ps.256" | "vtestnzc.ps" =>
289263 !direct && !negated,
290264 _ => unreachable!(),
src/tools/miri/src/shims/x86/avx2.rs+9-87
......@@ -5,8 +5,8 @@ use rustc_span::Symbol;
55use rustc_target::callconv::FnAbi;
66
77use super::{
8 ShiftOp, horizontal_bin_op, int_abs, mask_load, mask_store, mpsadbw, packssdw, packsswb,
9 packusdw, packuswb, pmulhrsw, psign, shift_simd_by_scalar, shift_simd_by_simd,
8 ShiftOp, horizontal_bin_op, mask_load, mask_store, mpsadbw, packssdw, packsswb, packusdw,
9 packuswb, pmulhrsw, psign, shift_simd_by_scalar, shift_simd_by_simd,
1010};
1111use crate::*;
1212
......@@ -25,29 +25,20 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
2525 let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.avx2.").unwrap();
2626
2727 match unprefixed_name {
28 // Used to implement the _mm256_abs_epi{8,16,32} functions.
29 // Calculates the absolute value of packed 8/16/32-bit integers.
30 "pabs.b" | "pabs.w" | "pabs.d" => {
31 let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
32
33 int_abs(this, op, dest)?;
34 }
35 // Used to implement the _mm256_h{add,adds,sub}_epi{16,32} functions.
36 // Horizontally add / add with saturation / subtract adjacent 16/32-bit
28 // Used to implement the _mm256_h{adds,subs}_epi16 functions.
29 // Horizontally add / subtract with saturation adjacent 16-bit
3730 // integer values in `left` and `right`.
38 "phadd.w" | "phadd.sw" | "phadd.d" | "phsub.w" | "phsub.sw" | "phsub.d" => {
31 "phadd.sw" | "phsub.sw" => {
3932 let [left, right] =
4033 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
4134
42 let (which, saturating) = match unprefixed_name {
43 "phadd.w" | "phadd.d" => (mir::BinOp::Add, false),
44 "phadd.sw" => (mir::BinOp::Add, true),
45 "phsub.w" | "phsub.d" => (mir::BinOp::Sub, false),
46 "phsub.sw" => (mir::BinOp::Sub, true),
35 let which = match unprefixed_name {
36 "phadd.sw" => mir::BinOp::Add,
37 "phsub.sw" => mir::BinOp::Sub,
4738 _ => unreachable!(),
4839 };
4940
50 horizontal_bin_op(this, which, saturating, left, right, dest)?;
41 horizontal_bin_op(this, which, /*saturating*/ true, left, right, dest)?;
5142 }
5243 // Used to implement `_mm{,_mask}_{i32,i64}gather_{epi32,epi64,pd,ps}` functions
5344 // Gathers elements from `slice` using `offsets * scale` as indices.
......@@ -110,42 +101,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
110101 this.write_scalar(Scalar::from_int(0, dest.layout.size), &dest)?;
111102 }
112103 }
113 // Used to implement the _mm256_madd_epi16 function.
114 // Multiplies packed signed 16-bit integers in `left` and `right`, producing
115 // intermediate signed 32-bit integers. Horizontally add adjacent pairs of
116 // intermediate 32-bit integers, and pack the results in `dest`.
117 "pmadd.wd" => {
118 let [left, right] =
119 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
120
121 let (left, left_len) = this.project_to_simd(left)?;
122 let (right, right_len) = this.project_to_simd(right)?;
123 let (dest, dest_len) = this.project_to_simd(dest)?;
124
125 assert_eq!(left_len, right_len);
126 assert_eq!(dest_len.strict_mul(2), left_len);
127
128 for i in 0..dest_len {
129 let j1 = i.strict_mul(2);
130 let left1 = this.read_scalar(&this.project_index(&left, j1)?)?.to_i16()?;
131 let right1 = this.read_scalar(&this.project_index(&right, j1)?)?.to_i16()?;
132
133 let j2 = j1.strict_add(1);
134 let left2 = this.read_scalar(&this.project_index(&left, j2)?)?.to_i16()?;
135 let right2 = this.read_scalar(&this.project_index(&right, j2)?)?.to_i16()?;
136
137 let dest = this.project_index(&dest, i)?;
138
139 // Multiplications are i16*i16->i32, which will not overflow.
140 let mul1 = i32::from(left1).strict_mul(right1.into());
141 let mul2 = i32::from(left2).strict_mul(right2.into());
142 // However, this addition can overflow in the most extreme case
143 // (-0x8000)*(-0x8000)+(-0x8000)*(-0x8000) = 0x80000000
144 let res = mul1.wrapping_add(mul2);
145
146 this.write_scalar(Scalar::from_i32(res), &dest)?;
147 }
148 }
149104 // Used to implement the _mm256_maddubs_epi16 function.
150105 // Multiplies packed 8-bit unsigned integers from `left` and packed
151106 // signed 8-bit integers from `right` into 16-bit signed integers. Then,
......@@ -285,39 +240,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
285240 this.copy_op(&left, &dest)?;
286241 }
287242 }
288 // Used to implement the _mm256_permute2x128_si256 function.
289 // Shuffles 128-bit blocks of `a` and `b` using `imm` as pattern.
290 "vperm2i128" => {
291 let [left, right, imm] =
292 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
293
294 assert_eq!(left.layout.size.bits(), 256);
295 assert_eq!(right.layout.size.bits(), 256);
296 assert_eq!(dest.layout.size.bits(), 256);
297
298 // Transmute to `[i128; 2]`
299
300 let array_layout =
301 this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.i128, 2))?;
302 let left = left.transmute(array_layout, this)?;
303 let right = right.transmute(array_layout, this)?;
304 let dest = dest.transmute(array_layout, this)?;
305
306 let imm = this.read_scalar(imm)?.to_u8()?;
307
308 for i in 0..2 {
309 let dest = this.project_index(&dest, i)?;
310 let src = match (imm >> i.strict_mul(4)) & 0b11 {
311 0 => this.project_index(&left, 0)?,
312 1 => this.project_index(&left, 1)?,
313 2 => this.project_index(&right, 0)?,
314 3 => this.project_index(&right, 1)?,
315 _ => unreachable!(),
316 };
317
318 this.copy_op(&src, &dest)?;
319 }
320 }
321243 // Used to implement the _mm256_sad_epu8 function.
322244 // Compute the absolute differences of packed unsigned 8-bit integers
323245 // in `left` and `right`, then horizontally sum each consecutive 8
src/tools/miri/src/shims/x86/mod.rs+1-55
......@@ -42,9 +42,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
4242 // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarry-u32-addcarry-u64.html
4343 // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/subborrow-u32-subborrow-u64.html
4444 "addcarry.32" | "addcarry.64" | "subborrow.32" | "subborrow.64" => {
45 if unprefixed_name.ends_with("64")
46 && this.tcx.sess.target.arch != Arch::X86_64
47 {
45 if unprefixed_name.ends_with("64") && this.tcx.sess.target.arch != Arch::X86_64 {
4846 return interp_ok(EmulateItemResult::NotSupported);
4947 }
5048
......@@ -61,28 +59,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
6159 this.write_immediate(*sum, &this.project_field(dest, FieldIdx::ONE)?)?;
6260 }
6361
64 // Used to implement the `_addcarryx_u{32, 64}` functions. They are semantically identical with the `_addcarry_u{32, 64}` functions,
65 // except for a slightly different type signature and the requirement for the "adx" target feature.
66 // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarryx-u32-addcarryx-u64.html
67 "addcarryx.u32" | "addcarryx.u64" => {
68 this.expect_target_feature_for_intrinsic(link_name, "adx")?;
69
70 let is_u64 = unprefixed_name.ends_with("64");
71 if is_u64 && this.tcx.sess.target.arch != Arch::X86_64 {
72 return interp_ok(EmulateItemResult::NotSupported);
73 }
74 let [c_in, a, b, out] =
75 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
76 let out = this.deref_pointer_as(
77 out,
78 if is_u64 { this.machine.layouts.u64 } else { this.machine.layouts.u32 },
79 )?;
80
81 let (sum, c_out) = carrying_add(this, c_in, a, b, mir::BinOp::AddWithOverflow)?;
82 this.write_scalar(c_out, dest)?;
83 this.write_immediate(*sum, &out)?;
84 }
85
8662 // Used to implement the `_mm_pause` function.
8763 // The intrinsic is used to hint the processor that the code is in a spin-loop.
8864 // It is compiled down to a `pause` instruction. When SSE2 is not available,
......@@ -721,36 +697,6 @@ fn convert_float_to_int<'tcx>(
721697 interp_ok(())
722698}
723699
724/// Calculates absolute value of integers in `op` and stores the result in `dest`.
725///
726/// In case of overflow (when the operand is the minimum value), the operation
727/// will wrap around.
728fn int_abs<'tcx>(
729 ecx: &mut crate::MiriInterpCx<'tcx>,
730 op: &OpTy<'tcx>,
731 dest: &MPlaceTy<'tcx>,
732) -> InterpResult<'tcx, ()> {
733 let (op, op_len) = ecx.project_to_simd(op)?;
734 let (dest, dest_len) = ecx.project_to_simd(dest)?;
735
736 assert_eq!(op_len, dest_len);
737
738 let zero = ImmTy::from_int(0, op.layout.field(ecx, 0));
739
740 for i in 0..dest_len {
741 let op = ecx.read_immediate(&ecx.project_index(&op, i)?)?;
742 let dest = ecx.project_index(&dest, i)?;
743
744 let lt_zero = ecx.binary_op(mir::BinOp::Lt, &op, &zero)?;
745 let res =
746 if lt_zero.to_scalar().to_bool()? { ecx.unary_op(mir::UnOp::Neg, &op)? } else { op };
747
748 ecx.write_immediate(*res, &dest)?;
749 }
750
751 interp_ok(())
752}
753
754700/// Splits `op` (which must be a SIMD vector) into 128-bit chunks.
755701///
756702/// Returns a tuple where:
src/tools/miri/src/shims/x86/sse.rs-23
......@@ -180,29 +180,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
180180
181181 this.write_immediate(*res, dest)?;
182182 }
183 // Used to implement the _mm_cvtsi32_ss and _mm_cvtsi64_ss functions.
184 // Converts `right` from i32/i64 to f32. Returns a SIMD vector with
185 // the result in the first component and the remaining components
186 // are copied from `left`.
187 // https://www.felixcloutier.com/x86/cvtsi2ss
188 "cvtsi2ss" | "cvtsi642ss" => {
189 let [left, right] =
190 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
191
192 let (left, left_len) = this.project_to_simd(left)?;
193 let (dest, dest_len) = this.project_to_simd(dest)?;
194
195 assert_eq!(dest_len, left_len);
196
197 let right = this.read_immediate(right)?;
198 let dest0 = this.project_index(&dest, 0)?;
199 let res0 = this.int_to_int_or_float(&right, dest0.layout)?;
200 this.write_immediate(*res0, &dest0)?;
201
202 for i in 1..dest_len {
203 this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?;
204 }
205 }
206183 _ => return interp_ok(EmulateItemResult::NotSupported),
207184 }
208185 interp_ok(EmulateItemResult::NeedsReturn)
src/tools/miri/src/shims/x86/sse2.rs+4-42
......@@ -36,42 +36,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
3636 // Intrinsincs sufixed with "epiX" or "epuX" operate with X-bit signed or unsigned
3737 // vectors.
3838 match unprefixed_name {
39 // Used to implement the _mm_madd_epi16 function.
40 // Multiplies packed signed 16-bit integers in `left` and `right`, producing
41 // intermediate signed 32-bit integers. Horizontally add adjacent pairs of
42 // intermediate 32-bit integers, and pack the results in `dest`.
43 "pmadd.wd" => {
44 let [left, right] =
45 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
46
47 let (left, left_len) = this.project_to_simd(left)?;
48 let (right, right_len) = this.project_to_simd(right)?;
49 let (dest, dest_len) = this.project_to_simd(dest)?;
50
51 assert_eq!(left_len, right_len);
52 assert_eq!(dest_len.strict_mul(2), left_len);
53
54 for i in 0..dest_len {
55 let j1 = i.strict_mul(2);
56 let left1 = this.read_scalar(&this.project_index(&left, j1)?)?.to_i16()?;
57 let right1 = this.read_scalar(&this.project_index(&right, j1)?)?.to_i16()?;
58
59 let j2 = j1.strict_add(1);
60 let left2 = this.read_scalar(&this.project_index(&left, j2)?)?.to_i16()?;
61 let right2 = this.read_scalar(&this.project_index(&right, j2)?)?.to_i16()?;
62
63 let dest = this.project_index(&dest, i)?;
64
65 // Multiplications are i16*i16->i32, which will not overflow.
66 let mul1 = i32::from(left1).strict_mul(right1.into());
67 let mul2 = i32::from(left2).strict_mul(right2.into());
68 // However, this addition can overflow in the most extreme case
69 // (-0x8000)*(-0x8000)+(-0x8000)*(-0x8000) = 0x80000000
70 let res = mul1.wrapping_add(mul2);
71
72 this.write_scalar(Scalar::from_i32(res), &dest)?;
73 }
74 }
7539 // Used to implement the _mm_sad_epu8 function.
7640 // Computes the absolute differences of packed unsigned 8-bit integers in `a`
7741 // and `b`, then horizontally sum each consecutive 8 differences to produce
......@@ -320,10 +284,10 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
320284
321285 this.write_immediate(*res, dest)?;
322286 }
323 // Used to implement the _mm_cvtsd_ss and _mm_cvtss_sd functions.
324 // Converts the first f64/f32 from `right` to f32/f64 and copies
325 // the remaining elements from `left`
326 "cvtsd2ss" | "cvtss2sd" => {
287 // Used to implement the _mm_cvtsd_ss function.
288 // Converts the first f64 from `right` to f32 and copies the remaining
289 // elements from `left`
290 "cvtsd2ss" => {
327291 let [left, right] =
328292 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
329293
......@@ -336,8 +300,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
336300 // Convert first element of `right`
337301 let right0 = this.read_immediate(&this.project_index(&right, 0)?)?;
338302 let dest0 = this.project_index(&dest, 0)?;
339 // `float_to_float_or_int` here will convert from f64 to f32 (cvtsd2ss) or
340 // from f32 to f64 (cvtss2sd).
341303 let res0 = this.float_to_float_or_int(&right0, dest0.layout)?;
342304 this.write_immediate(*res0, &dest0)?;
343305
src/tools/miri/src/shims/x86/sse3.rs-17
......@@ -1,10 +1,8 @@
11use rustc_abi::CanonAbi;
2use rustc_middle::mir;
32use rustc_middle::ty::Ty;
43use rustc_span::Symbol;
54use rustc_target::callconv::FnAbi;
65
7use super::horizontal_bin_op;
86use crate::*;
97
108impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
......@@ -22,21 +20,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
2220 let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse3.").unwrap();
2321
2422 match unprefixed_name {
25 // Used to implement the _mm_h{add,sub}_p{s,d} functions.
26 // Horizontally add/subtract adjacent floating point values
27 // in `left` and `right`.
28 "hadd.ps" | "hadd.pd" | "hsub.ps" | "hsub.pd" => {
29 let [left, right] =
30 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
31
32 let which = match unprefixed_name {
33 "hadd.ps" | "hadd.pd" => mir::BinOp::Add,
34 "hsub.ps" | "hsub.pd" => mir::BinOp::Sub,
35 _ => unreachable!(),
36 };
37
38 horizontal_bin_op(this, which, /*saturating*/ false, left, right, dest)?;
39 }
4023 // Used to implement the _mm_lddqu_si128 function.
4124 // Reads a 128-bit vector from an unaligned pointer. This intrinsic
4225 // is expected to perform better than a regular unaligned read when
src/tools/miri/src/shims/x86/sse41.rs+4-11
......@@ -157,20 +157,13 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
157157
158158 mpsadbw(this, left, right, imm, dest)?;
159159 }
160 // Used to implement the _mm_testz_si128, _mm_testc_si128
161 // and _mm_testnzc_si128 functions.
162 // Tests `(op & mask) == 0`, `(op & mask) == mask` or
163 // `(op & mask) != 0 && (op & mask) != mask`
164 "ptestz" | "ptestc" | "ptestnzc" => {
160 // Used to implement the _mm_testnzc_si128 function.
161 // Tests `(op & mask) != 0 && (op & mask) != mask`
162 "ptestnzc" => {
165163 let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
166164
167165 let (all_zero, masked_set) = test_bits_masked(this, op, mask)?;
168 let res = match unprefixed_name {
169 "ptestz" => all_zero,
170 "ptestc" => masked_set,
171 "ptestnzc" => !all_zero && !masked_set,
172 _ => unreachable!(),
173 };
166 let res = !all_zero && !masked_set;
174167
175168 this.write_scalar(Scalar::from_i32(res.into()), dest)?;
176169 }
src/tools/miri/src/shims/x86/ssse3.rs+8-18
......@@ -4,7 +4,7 @@ use rustc_middle::ty::Ty;
44use rustc_span::Symbol;
55use rustc_target::callconv::FnAbi;
66
7use super::{horizontal_bin_op, int_abs, pmulhrsw, psign};
7use super::{horizontal_bin_op, pmulhrsw, psign};
88use crate::*;
99
1010impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
......@@ -22,13 +22,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
2222 let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.ssse3.").unwrap();
2323
2424 match unprefixed_name {
25 // Used to implement the _mm_abs_epi{8,16,32} functions.
26 // Calculates the absolute value of packed 8/16/32-bit integers.
27 "pabs.b.128" | "pabs.w.128" | "pabs.d.128" => {
28 let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
29
30 int_abs(this, op, dest)?;
31 }
3225 // Used to implement the _mm_shuffle_epi8 intrinsic.
3326 // Shuffles bytes from `left` using `right` as pattern.
3427 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_epi8
......@@ -58,23 +51,20 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
5851 this.write_scalar(res, &dest)?;
5952 }
6053 }
61 // Used to implement the _mm_h{add,adds,sub}_epi{16,32} functions.
62 // Horizontally add / add with saturation / subtract adjacent 16/32-bit
54 // Used to implement the _mm_h{adds,subs}_epi16 functions.
55 // Horizontally add / subtract with saturation adjacent 16-bit
6356 // integer values in `left` and `right`.
64 "phadd.w.128" | "phadd.sw.128" | "phadd.d.128" | "phsub.w.128" | "phsub.sw.128"
65 | "phsub.d.128" => {
57 "phadd.sw.128" | "phsub.sw.128" => {
6658 let [left, right] =
6759 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
6860
69 let (which, saturating) = match unprefixed_name {
70 "phadd.w.128" | "phadd.d.128" => (mir::BinOp::Add, false),
71 "phadd.sw.128" => (mir::BinOp::Add, true),
72 "phsub.w.128" | "phsub.d.128" => (mir::BinOp::Sub, false),
73 "phsub.sw.128" => (mir::BinOp::Sub, true),
61 let which = match unprefixed_name {
62 "phadd.sw.128" => mir::BinOp::Add,
63 "phsub.sw.128" => mir::BinOp::Sub,
7464 _ => unreachable!(),
7565 };
7666
77 horizontal_bin_op(this, which, saturating, left, right, dest)?;
67 horizontal_bin_op(this, which, /*saturating*/ true, left, right, dest)?;
7868 }
7969 // Used to implement the _mm_maddubs_epi16 function.
8070 // Multiplies packed 8-bit unsigned integers from `left` and packed
src/tools/miri/test-cargo-miri/Cargo.lock-8
......@@ -27,7 +27,6 @@ dependencies = [
2727 "autocfg",
2828 "byteorder 0.5.3",
2929 "byteorder 1.5.0",
30 "cdylib",
3130 "exported_symbol",
3231 "eyre",
3332 "issue_1567",
......@@ -38,13 +37,6 @@ dependencies = [
3837 "proc_macro_crate",
3938]
4039
41[[package]]
42name = "cdylib"
43version = "0.1.0"
44dependencies = [
45 "byteorder 1.5.0",
46]
47
4840[[package]]
4941name = "exported_symbol"
5042version = "0.1.0"
src/tools/miri/test-cargo-miri/Cargo.toml-1
......@@ -10,7 +10,6 @@ edition = "2024"
1010
1111[dependencies]
1212byteorder = "1.0"
13cdylib = { path = "cdylib" }
1413exported_symbol = { path = "exported-symbol" }
1514proc_macro_crate = { path = "proc-macro-crate" }
1615issue_1567 = { path = "issue-1567" }
src/tools/miri/test-cargo-miri/cdylib/Cargo.toml deleted-12
......@@ -1,12 +0,0 @@
1[package]
2name = "cdylib"
3version = "0.1.0"
4authors = ["Miri Team"]
5edition = "2018"
6
7[lib]
8# cargo-miri used to handle `cdylib` crate-type specially (https://github.com/rust-lang/miri/pull/1577).
9crate-type = ["cdylib"]
10
11[dependencies]
12byteorder = "1.0" # to test dependencies of sub-crates
src/tools/miri/test-cargo-miri/cdylib/src/lib.rs deleted-6
......@@ -1,6 +0,0 @@
1use byteorder::{BigEndian, ByteOrder};
2
3#[no_mangle]
4extern "C" fn use_the_dependency() {
5 let _n = <BigEndian as ByteOrder>::read_u64(&[1, 2, 3, 4, 5, 6, 7, 8]);
6}
src/tools/miri/test-cargo-miri/run.local_crate.stdout.ref+1-1
......@@ -1 +1 @@
1subcrate,issue_1567,exported_symbol_dep,test_local_crate_detection,cargo_miri_test,cdylib,exported_symbol,issue_1691,issue_1705,issue_rust_86261,proc_macro_crate
1subcrate,issue_1567,exported_symbol_dep,test_local_crate_detection,cargo_miri_test,exported_symbol,issue_1691,issue_1705,issue_rust_86261,proc_macro_crate
src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.rs created+29
......@@ -0,0 +1,29 @@
1//@only-target: darwin
2#![feature(sync_unsafe_cell)]
3
4use std::cell::SyncUnsafeCell;
5use std::sync::atomic::*;
6use std::thread;
7
8fn main() {
9 let lock = SyncUnsafeCell::new(libc::OS_UNFAIR_LOCK_INIT);
10
11 thread::scope(|s| {
12 // First thread: grabs the lock.
13 s.spawn(|| {
14 unsafe { libc::os_unfair_lock_lock(lock.get()) };
15 thread::yield_now();
16 unreachable!();
17 });
18 // Second thread: queues for the lock.
19 s.spawn(|| {
20 unsafe { libc::os_unfair_lock_lock(lock.get()) };
21 unreachable!();
22 });
23 // Third thread: tries to read the lock while second thread is queued.
24 s.spawn(|| {
25 let atomic_ref = unsafe { &*lock.get().cast::<AtomicU32>() };
26 let _val = atomic_ref.load(Ordering::Relaxed); //~ERROR: read of `os_unfair_lock` is forbidden while the queue is non-empty
27 });
28 });
29}
src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.stderr created+13
......@@ -0,0 +1,13 @@
1error: Undefined Behavior: read of `os_unfair_lock` is forbidden while the queue is non-empty
2 --> tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.rs:LL:CC
3 |
4LL | let _val = atomic_ref.load(Ordering::Relaxed);
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
6 |
7 = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9
10note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
11
12error: aborting due to 1 previous error
13
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs+1-1
......@@ -1,6 +1,6 @@
11//@ignore-target: windows # No pthreads on Windows
22//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
3//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
3//@ normalize-stderr-test: "\[0x[0-9a-z]+..0x[0-9a-z]+\]" -> "[0xX..0xY]"
44
55/// Test that destroying a pthread_cond twice fails, even without a check for number validity
66
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr+1-1
......@@ -1,4 +1,4 @@
1error: Undefined Behavior: `pthread_cond_t` can't be moved after first use
1error: Undefined Behavior: `pthread_cond_t` was not properly initialized at this location, or it got overwritten
22 --> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC
33 |
44LL | libc::pthread_cond_destroy(cond2.as_mut_ptr());
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.rs+2-2
......@@ -18,7 +18,7 @@ fn check() {
1818 // move pthread_cond_t
1919 let mut cond2 = cond;
2020
21 libc::pthread_cond_destroy(cond2.as_mut_ptr()); //~[init] ERROR: can't be moved after first use
21 libc::pthread_cond_destroy(cond2.as_mut_ptr()); //~[init] ERROR: not properly initialized
2222 }
2323}
2424
......@@ -32,6 +32,6 @@ fn check() {
3232 // move pthread_cond_t
3333 let mut cond2 = cond;
3434
35 libc::pthread_cond_destroy(&mut cond2 as *mut _); //~[static_initializer] ERROR: can't be moved after first use
35 libc::pthread_cond_destroy(&mut cond2 as *mut _); //~[static_initializer] ERROR: not properly initialized
3636 }
3737}
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.static_initializer.stderr+1-1
......@@ -1,4 +1,4 @@
1error: Undefined Behavior: `pthread_cond_t` can't be moved after first use
1error: Undefined Behavior: `pthread_cond_t` was not properly initialized at this location, or it got overwritten
22 --> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC
33 |
44LL | libc::pthread_cond_destroy(&mut cond2 as *mut _);
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs+1-1
......@@ -1,6 +1,6 @@
11//@ignore-target: windows # No pthreads on Windows
22//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
3//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
3//@ normalize-stderr-test: "\[0x[0-9a-z]+..0x[0-9a-z]+\]" -> "[0xX..0xY]"
44
55/// Test that destroying a pthread_mutex twice fails, even without a check for number validity
66
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.rs created+48
......@@ -0,0 +1,48 @@
1//@ignore-target: windows # No pthreads on Windows
2//@compile-flags: -Zmiri-deterministic-concurrency
3//@error-in-other-file: deallocation of `pthread_mutex_t` is forbidden while the queue is non-empty
4
5use std::cell::UnsafeCell;
6use std::sync::atomic::*;
7use std::thread;
8
9struct Mutex(UnsafeCell<libc::pthread_mutex_t>);
10impl Mutex {
11 fn get(&self) -> *mut libc::pthread_mutex_t {
12 self.0.get()
13 }
14}
15
16unsafe impl Send for Mutex {}
17unsafe impl Sync for Mutex {}
18
19fn main() {
20 let m = Box::new(Mutex(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER)));
21 let initialized = AtomicBool::new(false);
22 thread::scope(|s| {
23 // First thread: initializes the lock, and then grabs it.
24 s.spawn(|| {
25 // Initialize (so the third thread can happens-after the write that occurs here).
26 assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0);
27 assert_eq!(unsafe { libc::pthread_mutex_unlock(m.get()) }, 0);
28 initialized.store(true, Ordering::Release);
29 // Grab and hold.
30 assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0);
31 thread::yield_now();
32 unreachable!();
33 });
34 // Second thread: queues for the lock.
35 s.spawn(|| {
36 assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0);
37 unreachable!();
38 });
39 // Third thread: tries to free the lock while second thread is queued.
40 s.spawn(|| {
41 // Ensure we happen-after the initialization write.
42 assert!(initialized.load(Ordering::Acquire));
43 // Now drop it.
44 drop(unsafe { Box::from_raw(m.get().cast::<Mutex>()) });
45 });
46 });
47 unreachable!();
48}
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.stderr created+22
......@@ -0,0 +1,22 @@
1error: Undefined Behavior: deallocation of `pthread_mutex_t` is forbidden while the queue is non-empty
2 --> RUSTLIB/alloc/src/boxed.rs:LL:CC
3 |
4LL | self.1.deallocate(From::from(ptr.cast()), layout);
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
6 |
7 = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9 = note: BACKTRACE on thread `unnamed-ID`:
10 = note: inside `<std::boxed::Box<Mutex> as std::ops::Drop>::drop` at RUSTLIB/alloc/src/boxed.rs:LL:CC
11 = note: inside `std::ptr::drop_in_place::<std::boxed::Box<Mutex>> - shim(Some(std::boxed::Box<Mutex>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
12 = note: inside `std::mem::drop::<std::boxed::Box<Mutex>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
13note: inside closure
14 --> tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.rs:LL:CC
15 |
16LL | drop(unsafe { Box::from_raw(m.get().cast::<Mutex>()) });
17 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18
19note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
20
21error: aborting due to 1 previous error
22
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr+1-1
......@@ -1,4 +1,4 @@
1error: Undefined Behavior: `pthread_mutex_t` can't be moved after first use
1error: Undefined Behavior: `pthread_mutex_t` was not properly initialized at this location, or it got overwritten
22 --> tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC
33 |
44LL | libc::pthread_mutex_lock(&mut m2 as *mut _);
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs+2-2
......@@ -12,7 +12,7 @@ fn check() {
1212 assert_eq!(libc::pthread_mutex_init(&mut m as *mut _, std::ptr::null()), 0);
1313
1414 let mut m2 = m; // move the mutex
15 libc::pthread_mutex_lock(&mut m2 as *mut _); //~[init] ERROR: can't be moved after first use
15 libc::pthread_mutex_lock(&mut m2 as *mut _); //~[init] ERROR: not properly initialized
1616 }
1717}
1818
......@@ -23,6 +23,6 @@ fn check() {
2323 libc::pthread_mutex_lock(&mut m as *mut _);
2424
2525 let mut m2 = m; // move the mutex
26 libc::pthread_mutex_unlock(&mut m2 as *mut _); //~[static_initializer] ERROR: can't be moved after first use
26 libc::pthread_mutex_unlock(&mut m2 as *mut _); //~[static_initializer] ERROR: not properly initialized
2727 }
2828}
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr+1-1
......@@ -1,4 +1,4 @@
1error: Undefined Behavior: `pthread_mutex_t` can't be moved after first use
1error: Undefined Behavior: `pthread_mutex_t` was not properly initialized at this location, or it got overwritten
22 --> tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC
33 |
44LL | libc::pthread_mutex_unlock(&mut m2 as *mut _);
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_overwrite.rs created+14
......@@ -0,0 +1,14 @@
1//@ignore-target: windows # No pthreads on Windows
2
3fn main() {
4 unsafe {
5 let mut m: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
6 libc::pthread_mutex_lock(&mut m as *mut _);
7
8 // Overwrite the mutex with itself. This de-initializes it.
9 let copy = m;
10 m = copy;
11
12 libc::pthread_mutex_unlock(&mut m as *mut _); //~ERROR: not properly initialized
13 }
14}
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_overwrite.stderr created+13
......@@ -0,0 +1,13 @@
1error: Undefined Behavior: `pthread_mutex_t` was not properly initialized at this location, or it got overwritten
2 --> tests/fail-dep/concurrency/libc_pthread_mutex_overwrite.rs:LL:CC
3 |
4LL | libc::pthread_mutex_unlock(&mut m as *mut _);
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
6 |
7 = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9
10note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
11
12error: aborting due to 1 previous error
13
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_read_while_queued.rs created+41
......@@ -0,0 +1,41 @@
1//@ignore-target: windows # No pthreads on Windows
2//@compile-flags: -Zmiri-fixed-schedule
3
4use std::cell::UnsafeCell;
5use std::sync::atomic::*;
6use std::thread;
7
8struct Mutex(UnsafeCell<libc::pthread_mutex_t>);
9impl Mutex {
10 fn get(&self) -> *mut libc::pthread_mutex_t {
11 self.0.get()
12 }
13}
14
15unsafe impl Send for Mutex {}
16unsafe impl Sync for Mutex {}
17
18// The offset to the "sensitive" part of the mutex (that Miri attaches the metadata to).
19const OFFSET: usize = if cfg!(target_os = "macos") { 4 } else { 0 };
20
21fn main() {
22 let m = Mutex(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER));
23 thread::scope(|s| {
24 // First thread: grabs the lock.
25 s.spawn(|| {
26 assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0);
27 thread::yield_now();
28 unreachable!();
29 });
30 // Second thread: queues for the lock.
31 s.spawn(|| {
32 assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0);
33 unreachable!();
34 });
35 // Third thread: tries to read the lock while second thread is queued.
36 s.spawn(|| {
37 let atomic_ref = unsafe { &*m.get().byte_add(OFFSET).cast::<AtomicU32>() };
38 let _val = atomic_ref.load(Ordering::Relaxed); //~ERROR: read of `pthread_mutex_t` is forbidden while the queue is non-empty
39 });
40 });
41}
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_read_while_queued.stderr created+13
......@@ -0,0 +1,13 @@
1error: Undefined Behavior: read of `pthread_mutex_t` is forbidden while the queue is non-empty
2 --> tests/fail-dep/concurrency/libc_pthread_mutex_read_while_queued.rs:LL:CC
3 |
4LL | ... let _val = atomic_ref.load(Ordering::Relaxed);
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
6 |
7 = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9
10note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
11
12error: aborting due to 1 previous error
13
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_write_while_queued.rs created+41
......@@ -0,0 +1,41 @@
1//@ignore-target: windows # No pthreads on Windows
2//@compile-flags: -Zmiri-fixed-schedule
3
4use std::cell::UnsafeCell;
5use std::sync::atomic::*;
6use std::thread;
7
8struct Mutex(UnsafeCell<libc::pthread_mutex_t>);
9impl Mutex {
10 fn get(&self) -> *mut libc::pthread_mutex_t {
11 self.0.get()
12 }
13}
14
15unsafe impl Send for Mutex {}
16unsafe impl Sync for Mutex {}
17
18// The offset to the "sensitive" part of the mutex (that Miri attaches the metadata to).
19const OFFSET: usize = if cfg!(target_os = "macos") { 4 } else { 0 };
20
21fn main() {
22 let m = Mutex(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER));
23 thread::scope(|s| {
24 // First thread: grabs the lock.
25 s.spawn(|| {
26 assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0);
27 thread::yield_now();
28 unreachable!();
29 });
30 // Second thread: queues for the lock.
31 s.spawn(|| {
32 assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0);
33 unreachable!();
34 });
35 // Third thread: tries to overwrite the lock while second thread is queued.
36 s.spawn(|| {
37 let atomic_ref = unsafe { &*m.get().byte_add(OFFSET).cast::<AtomicU32>() };
38 atomic_ref.store(0, Ordering::Relaxed); //~ERROR: write of `pthread_mutex_t` is forbidden while the queue is non-empty
39 });
40 });
41}
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_write_while_queued.stderr created+13
......@@ -0,0 +1,13 @@
1error: Undefined Behavior: write of `pthread_mutex_t` is forbidden while the queue is non-empty
2 --> tests/fail-dep/concurrency/libc_pthread_mutex_write_while_queued.rs:LL:CC
3 |
4LL | atomic_ref.store(0, Ordering::Relaxed);
5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
6 |
7 = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9
10note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
11
12error: aborting due to 1 previous error
13
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs+1-1
......@@ -1,6 +1,6 @@
11//@ignore-target: windows # No pthreads on Windows
22//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}"
3//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]"
3//@ normalize-stderr-test: "\[0x[0-9a-z]+..0x[0-9a-z]+\]" -> "[0xX..0xY]"
44
55/// Test that destroying a pthread_rwlock twice fails, even without a check for number validity
66
src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs+1-1
......@@ -9,6 +9,6 @@ fn main() {
99 // Move rwlock
1010 let mut rw2 = rw;
1111
12 libc::pthread_rwlock_unlock(&mut rw2 as *mut _); //~ ERROR: can't be moved after first use
12 libc::pthread_rwlock_unlock(&mut rw2 as *mut _); //~ ERROR: not properly initialized
1313 }
1414}
src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.stderr+1-1
......@@ -1,4 +1,4 @@
1error: Undefined Behavior: `pthread_rwlock_t` can't be moved after first use
1error: Undefined Behavior: `pthread_rwlock_t` was not properly initialized at this location, or it got overwritten
22 --> tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs:LL:CC
33 |
44LL | libc::pthread_rwlock_unlock(&mut rw2 as *mut _);
src/tools/miri/tests/fail/intrinsics/simd_masked_load_element_misaligned.rs+1-1
......@@ -6,7 +6,7 @@ use std::simd::*;
66fn main() {
77 unsafe {
88 let buf = [0u32; 5];
9 //~v ERROR: accessing memory with alignment
9 //~v ERROR: accessing memory with alignment
1010 simd_masked_load::<_, _, _, { SimdAlign::Element }>(
1111 i32x4::splat(-1),
1212 // This is not i32-aligned
src/tools/miri/tests/pass-dep/concurrency/apple-os-unfair-lock.rs+5-7
......@@ -14,12 +14,10 @@ fn main() {
1414 libc::os_unfair_lock_assert_not_owner(lock.get());
1515 }
1616
17 // `os_unfair_lock`s can be moved and leaked.
18 // In the real implementation, even moving it while locked is possible
19 // (and "forks" the lock, i.e. old and new location have independent wait queues).
20 // We only test the somewhat sane case of moving while unlocked that `std` plans to rely on.
17 // `os_unfair_lock`s can be moved, and even acquired again then.
2118 let lock = lock;
22 let locked = unsafe { libc::os_unfair_lock_trylock(lock.get()) };
23 assert!(locked);
24 let _lock = lock;
19 assert!(unsafe { libc::os_unfair_lock_trylock(lock.get()) });
20 // We can even move it while locked, but then we cannot acquire it any more.
21 let lock = lock;
22 assert!(!unsafe { libc::os_unfair_lock_trylock(lock.get()) });
2523}
src/tools/miri/tests/pass-dep/libc/pthread-sync.rs+34-19
......@@ -8,18 +8,21 @@ use std::mem::MaybeUninit;
88use std::{mem, ptr, thread};
99
1010fn main() {
11 test_mutex();
1112 test_mutex_libc_init_recursive();
1213 test_mutex_libc_init_normal();
1314 test_mutex_libc_init_errorcheck();
14 test_rwlock_libc_static_initializer();
1515 #[cfg(target_os = "linux")]
1616 test_mutex_libc_static_initializer_recursive();
17 #[cfg(target_os = "linux")]
18 test_mutex_libc_static_initializer_errorcheck();
19
20 test_cond();
21 test_condattr();
1722
18 check_mutex();
19 check_rwlock_write();
20 check_rwlock_read_no_deadlock();
21 check_cond();
22 check_condattr();
23 test_rwlock();
24 test_rwlock_write();
25 test_rwlock_read_no_deadlock();
2326}
2427
2528// We want to only use pthread APIs here for easier testing.
......@@ -107,8 +110,7 @@ fn test_mutex_libc_init_errorcheck() {
107110 }
108111}
109112
110// Only linux provides PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
111// libc for macOS just has the default PTHREAD_MUTEX_INITIALIZER.
113// Only linux provides PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP.
112114#[cfg(target_os = "linux")]
113115fn test_mutex_libc_static_initializer_recursive() {
114116 let mutex = std::cell::UnsafeCell::new(libc::PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
......@@ -126,6 +128,22 @@ fn test_mutex_libc_static_initializer_recursive() {
126128 }
127129}
128130
131// Only linux provides PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP.
132#[cfg(target_os = "linux")]
133fn test_mutex_libc_static_initializer_errorcheck() {
134 let mutex = std::cell::UnsafeCell::new(libc::PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP);
135 unsafe {
136 assert_eq!(libc::pthread_mutex_lock(mutex.get()), 0);
137 assert_eq!(libc::pthread_mutex_trylock(mutex.get()), libc::EBUSY);
138 assert_eq!(libc::pthread_mutex_lock(mutex.get()), libc::EDEADLK);
139 assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
140 assert_eq!(libc::pthread_mutex_trylock(mutex.get()), 0);
141 assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0);
142 assert_eq!(libc::pthread_mutex_unlock(mutex.get()), libc::EPERM);
143 assert_eq!(libc::pthread_mutex_destroy(mutex.get()), 0);
144 }
145}
146
129147struct SendPtr<T> {
130148 ptr: *mut T,
131149}
......@@ -137,7 +155,7 @@ impl<T> Clone for SendPtr<T> {
137155 }
138156}
139157
140fn check_mutex() {
158fn test_mutex() {
141159 let bomb = AbortOnDrop;
142160 // Specifically *not* using `Arc` to make sure there is no synchronization apart from the mutex.
143161 unsafe {
......@@ -168,7 +186,7 @@ fn check_mutex() {
168186 bomb.defuse();
169187}
170188
171fn check_rwlock_write() {
189fn test_rwlock_write() {
172190 let bomb = AbortOnDrop;
173191 unsafe {
174192 let data = SyncUnsafeCell::new((libc::PTHREAD_RWLOCK_INITIALIZER, 0));
......@@ -209,7 +227,7 @@ fn check_rwlock_write() {
209227 bomb.defuse();
210228}
211229
212fn check_rwlock_read_no_deadlock() {
230fn test_rwlock_read_no_deadlock() {
213231 let bomb = AbortOnDrop;
214232 unsafe {
215233 let l1 = SyncUnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER);
......@@ -237,12 +255,11 @@ fn check_rwlock_read_no_deadlock() {
237255 bomb.defuse();
238256}
239257
240fn check_cond() {
258fn test_cond() {
241259 let bomb = AbortOnDrop;
242260 unsafe {
243 let mut cond: MaybeUninit<libc::pthread_cond_t> = MaybeUninit::uninit();
244 assert_eq!(libc::pthread_cond_init(cond.as_mut_ptr(), ptr::null()), 0);
245 let cond = SendPtr { ptr: cond.as_mut_ptr() };
261 let mut cond: libc::pthread_cond_t = libc::PTHREAD_COND_INITIALIZER;
262 let cond = SendPtr { ptr: &mut cond };
246263
247264 let mut mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
248265 let mutex = SendPtr { ptr: &mut mutex };
......@@ -286,7 +303,7 @@ fn check_cond() {
286303 bomb.defuse();
287304}
288305
289fn check_condattr() {
306fn test_condattr() {
290307 unsafe {
291308 // Just smoke-testing that these functions can be called.
292309 let mut attr: MaybeUninit<libc::pthread_condattr_t> = MaybeUninit::uninit();
......@@ -311,9 +328,7 @@ fn check_condattr() {
311328 }
312329}
313330
314// std::sync::RwLock does not even used pthread_rwlock any more.
315// Do some smoke testing of the API surface.
316fn test_rwlock_libc_static_initializer() {
331fn test_rwlock() {
317332 let rw = std::cell::UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER);
318333 unsafe {
319334 assert_eq!(libc::pthread_rwlock_rdlock(rw.get()), 0);
src/tools/miri/triagebot.toml+1-1
......@@ -20,7 +20,7 @@ contributing_url = "https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.m
2020[assign.custom_welcome_messages]
2121welcome-message = "(unused)"
2222welcome-message-no-reviewer = """
23Thank you for contributing to Miri!
23Thank you for contributing to Miri! A reviewer will take a look at your PR, typically within a week or two.
2424Please remember to not force-push to the PR branch except when you need to rebase due to a conflict or when the reviewer asks you for it.
2525"""
2626
src/tools/tidy/src/diagnostics.rs+43-9
......@@ -1,9 +1,10 @@
11use std::collections::HashSet;
22use std::fmt::{Display, Formatter};
3use std::io;
34use std::path::{Path, PathBuf};
45use std::sync::{Arc, Mutex};
56
6use termcolor::{Color, WriteColor};
7use termcolor::Color;
78
89#[derive(Clone, Default)]
910///CLI flags used by tidy.
......@@ -245,30 +246,63 @@ pub const COLOR_WARNING: Color = Color::Yellow;
245246/// Output a message to stderr.
246247/// The message can be optionally scoped to a certain check, and it can also have a certain color.
247248pub fn output_message(msg: &str, id: Option<&CheckId>, color: Option<Color>) {
248 use std::io::Write;
249 use termcolor::{ColorChoice, ColorSpec};
249250
250 use termcolor::{ColorChoice, ColorSpec, StandardStream};
251 let stderr: &mut dyn termcolor::WriteColor = if cfg!(test) {
252 &mut StderrForUnitTests
253 } else {
254 &mut termcolor::StandardStream::stderr(ColorChoice::Auto)
255 };
251256
252 let mut stderr = StandardStream::stderr(ColorChoice::Auto);
253257 if let Some(color) = &color {
254258 stderr.set_color(ColorSpec::new().set_fg(Some(*color))).unwrap();
255259 }
256260
257261 match id {
258262 Some(id) => {
259 write!(&mut stderr, "tidy [{}", id.name).unwrap();
263 write!(stderr, "tidy [{}", id.name).unwrap();
260264 if let Some(path) = &id.path {
261 write!(&mut stderr, " ({})", path.display()).unwrap();
265 write!(stderr, " ({})", path.display()).unwrap();
262266 }
263 write!(&mut stderr, "]").unwrap();
267 write!(stderr, "]").unwrap();
264268 }
265269 None => {
266 write!(&mut stderr, "tidy").unwrap();
270 write!(stderr, "tidy").unwrap();
267271 }
268272 }
269273 if color.is_some() {
270274 stderr.set_color(&ColorSpec::new()).unwrap();
271275 }
272276
273 writeln!(&mut stderr, ": {msg}").unwrap();
277 writeln!(stderr, ": {msg}").unwrap();
278}
279
280/// An implementation of `io::Write` and `termcolor::WriteColor` that writes
281/// to stderr via `eprint!`, so that the output can be properly captured when
282/// running tidy's unit tests.
283struct StderrForUnitTests;
284
285impl io::Write for StderrForUnitTests {
286 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
287 eprint!("{}", String::from_utf8_lossy(buf));
288 Ok(buf.len())
289 }
290
291 fn flush(&mut self) -> io::Result<()> {
292 Ok(())
293 }
294}
295
296impl termcolor::WriteColor for StderrForUnitTests {
297 fn supports_color(&self) -> bool {
298 false
299 }
300
301 fn set_color(&mut self, _spec: &termcolor::ColorSpec) -> io::Result<()> {
302 Ok(())
303 }
304
305 fn reset(&mut self) -> io::Result<()> {
306 Ok(())
307 }
274308}
tests/crashes/119783.rs deleted-11
......@@ -1,11 +0,0 @@
1//@ known-bug: #119783
2#![feature(associated_const_equality, min_generic_const_args)]
3
4trait Trait {
5 #[type_const]
6 const F: fn();
7}
8
9fn take(_: impl Trait<F = { || {} }>) {}
10
11fn main() {}
tests/crashes/140729.rs deleted-11
......@@ -1,11 +0,0 @@
1//@ known-bug: #140729
2#![feature(min_generic_const_args)]
3
4const C: usize = 0;
5pub struct A<const M: usize> {}
6impl A<C> {
7 fn fun1() {}
8}
9impl A {
10 fn fun1() {}
11}
tests/crashes/140860.rs deleted-10
......@@ -1,10 +0,0 @@
1//@ known-bug: #140860
2#![feature(min_generic_const_args)]
3#![feature(unsized_const_params)]
4#![feature(with_negative_coherence, negative_impls)]
5trait a < const b : &'static str> {} trait c {} struct d< e >(e);
6impl<e> c for e where e: a<""> {}
7impl<e> c for d<e> {}
8impl<e> !a<f> for e {}
9const f : &str = "";
10fn main() {}
tests/crashes/mgca/type_const-only-in-trait.rs deleted-23
......@@ -1,23 +0,0 @@
1//@ known-bug: #132980
2// Move this test to tests/ui/const-generics/mgca/type_const-only-in-trait.rs
3// once fixed.
4
5#![expect(incomplete_features)]
6#![feature(associated_const_equality, min_generic_const_args)]
7
8trait GoodTr {
9 #[type_const]
10 const NUM: usize;
11}
12
13struct BadS;
14
15impl GoodTr for BadS {
16 const NUM: usize = 42;
17}
18
19fn accept_good_tr<const N: usize, T: GoodTr<NUM = { N }>>(_x: &T) {}
20
21fn main() {
22 accept_good_tr(&BadS);
23}
tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-disabled.stderr+7-8
......@@ -38,8 +38,8 @@ LL | trait Bar: [const] Foo {}
3838 |
3939help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations
4040 |
41LL | #[const_trait] trait Foo {
42 | ++++++++++++++
41LL | const trait Foo {
42 | +++++
4343
4444error: `[const]` can only be applied to `const` traits
4545 --> const-super-trait.rs:9:17
......@@ -49,8 +49,8 @@ LL | const fn foo<T: [const] Bar>(x: &T) {
4949 |
5050help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations
5151 |
52LL | #[const_trait] trait Bar: [const] Foo {}
53 | ++++++++++++++
52LL | const trait Bar: [const] Foo {}
53 | +++++
5454
5555error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
5656 --> const-super-trait.rs:10:7
......@@ -65,13 +65,12 @@ LL | trait Foo {
6565 | ^^^^^^^^^ this trait is not const
6666LL | fn a(&self);
6767 | ------------ this method is not const
68 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]`
68 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable const traits
6969 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
7070help: consider making trait `Foo` const
7171 |
72LL + #[const_trait]
73LL | trait Foo {
74 |
72LL | const trait Foo {
73 | +++++
7574
7675error: aborting due to 6 previous errors
7776
tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-enabled.stderr+6-7
......@@ -18,8 +18,8 @@ LL | trait Bar: [const] Foo {}
1818 |
1919help: mark `Foo` as `const` to allow it to have `const` implementations
2020 |
21LL | #[const_trait] trait Foo {
22 | ++++++++++++++
21LL | const trait Foo {
22 | +++++
2323
2424error: `[const]` can only be applied to `const` traits
2525 --> const-super-trait.rs:9:17
......@@ -29,8 +29,8 @@ LL | const fn foo<T: [const] Bar>(x: &T) {
2929 |
3030help: mark `Bar` as `const` to allow it to have `const` implementations
3131 |
32LL | #[const_trait] trait Bar: [const] Foo {}
33 | ++++++++++++++
32LL | const trait Bar: [const] Foo {}
33 | +++++
3434
3535error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
3636 --> const-super-trait.rs:10:7
......@@ -48,9 +48,8 @@ LL | fn a(&self);
4848 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
4949help: consider making trait `Foo` const
5050 |
51LL + #[const_trait]
52LL | trait Foo {
53 |
51LL | const trait Foo {
52 | +++++
5453
5554error: aborting due to 4 previous errors
5655
tests/rustdoc/constant/const-effect-param.rs+1-2
......@@ -3,8 +3,7 @@
33#![crate_name = "foo"]
44#![feature(const_trait_impl)]
55
6#[const_trait]
7pub trait Tr {
6pub const trait Tr {
87 fn f();
98}
109
tests/rustdoc/constant/const-trait-and-impl-methods.rs+2-4
......@@ -1,5 +1,4 @@
1// check that we don't render `#[const_trait]` methods as `const` - even for
2// const `trait`s and `impl`s.
1// check that we don't render assoc fns as `const` - even for const `trait`s and `impl`s.
32#![crate_name = "foo"]
43#![feature(const_trait_impl)]
54
......@@ -8,8 +7,7 @@
87//@ !has - '//*[@id="tymethod.required"]' 'const'
98//@ has - '//*[@id="method.defaulted"]' 'fn defaulted()'
109//@ !has - '//*[@id="method.defaulted"]' 'const'
11#[const_trait]
12pub trait Tr {
10pub const trait Tr {
1311 fn required();
1412 fn defaulted() {}
1513}
tests/rustdoc/constant/rfc-2632-const-trait-impl.rs+1-2
......@@ -19,8 +19,7 @@ pub struct S<T>(T);
1919//@ has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Fn'
2020//@ !has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' '[const]'
2121//@ has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' ': Fn'
22#[const_trait]
23pub trait Tr<T> {
22pub const trait Tr<T> {
2423 //@ !has - '//section[@id="method.a"]/h4[@class="code-header"]' '[const]'
2524 //@ has - '//section[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn'
2625 //@ !has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '[const]'
tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs+1-2
......@@ -1,8 +1,7 @@
11//@ compile-flags: -Znext-solver
22#![feature(const_trait_impl)]
33
4#[const_trait]
5pub trait Resource {}
4pub const trait Resource {}
65
76pub const fn load<R: [const] Resource>() -> i32 {
87 0
tests/ui/associated-consts/assoc-const-eq-ambiguity.rs+1-1
......@@ -1,7 +1,7 @@
11// We used to say "ambiguous associated type" on ambiguous associated consts.
22// Ensure that we now use the correct label.
33
4#![feature(associated_const_equality, min_generic_const_args)]
4#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)]
55#![allow(incomplete_features)]
66
77trait Trait0: Parent0<i32> + Parent0<u32> {}
tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.rs+9-2
......@@ -1,9 +1,16 @@
11// Check that we eventually catch types of assoc const bounds
22// (containing late-bound vars) that are ill-formed.
3#![feature(associated_const_equality, min_generic_const_args)]
3#![feature(
4 associated_const_equality,
5 min_generic_const_args,
6 adt_const_params,
7 unsized_const_params,
8)]
49#![allow(incomplete_features)]
510
6trait Trait<T> {
11use std::marker::ConstParamTy_;
12
13trait Trait<T: ConstParamTy_> {
714 #[type_const]
815 const K: T;
916}
tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr+3-3
......@@ -1,11 +1,11 @@
11error: higher-ranked subtype error
2 --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:14:13
2 --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:13
33 |
44LL | K = { () }
55 | ^^^^^^
66
77error: higher-ranked subtype error
8 --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:14:13
8 --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:13
99 |
1010LL | K = { () }
1111 | ^^^^^^
......@@ -13,7 +13,7 @@ LL | K = { () }
1313 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
1414
1515error: implementation of `Project` is not general enough
16 --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:12:13
16 --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:19:13
1717 |
1818LL | _: impl Trait<
1919 | _____________^
tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs+9-2
......@@ -3,10 +3,17 @@
33//
44//@ check-pass
55
6#![feature(associated_const_equality, min_generic_const_args)]
6#![feature(
7 associated_const_equality,
8 min_generic_const_args,
9 adt_const_params,
10 unsized_const_params,
11)]
712#![allow(incomplete_features)]
813
9trait Trait<T> {
14use std::marker::ConstParamTy_;
15
16trait Trait<T: ConstParamTy_> {
1017 #[type_const]
1118 const K: T;
1219}
tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.rs+1-1
......@@ -1,6 +1,6 @@
11// Detect and reject escaping late-bound generic params in
22// the type of assoc consts used in an equality bound.
3#![feature(associated_const_equality, min_generic_const_args)]
3#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)]
44#![allow(incomplete_features)]
55
66trait Trait<'a> {
tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs+12-5
......@@ -1,14 +1,21 @@
11// Regression test for issue #108271.
22// Detect and reject generic params in the type of assoc consts used in an equality bound.
3#![feature(associated_const_equality, min_generic_const_args)]
3#![feature(
4 associated_const_equality,
5 min_generic_const_args,
6 adt_const_params,
7 unsized_const_params,
8)]
49#![allow(incomplete_features)]
510
6trait Trait<'a, T: 'a, const N: usize> {
11use std::marker::ConstParamTy_;
12
13trait Trait<'a, T: 'a + ConstParamTy_, const N: usize> {
714 #[type_const]
815 const K: &'a [T; N];
916}
1017
11fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
18fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
1219//~^ ERROR the type of the associated constant `K` must not depend on generic parameters
1320//~| NOTE its type must not depend on the lifetime parameter `'r`
1421//~| NOTE the lifetime parameter `'r` is defined here
......@@ -22,7 +29,7 @@ fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
2229//~| NOTE the const parameter `Q` is defined here
2330//~| NOTE `K` has type `&'r [A; Q]`
2431
25trait Project {
32trait Project: ConstParamTy_ {
2633 #[type_const]
2734 const SELF: Self;
2835}
......@@ -38,7 +45,7 @@ fn take2<P: Project<SELF = {}>>(_: P) {}
3845//~| NOTE the type parameter `P` is defined here
3946//~| NOTE `SELF` has type `P`
4047
41trait Iface<'r> {
48trait Iface<'r>: ConstParamTy_ {
4249 //~^ NOTE the lifetime parameter `'r` is defined here
4350 //~| NOTE the lifetime parameter `'r` is defined here
4451 type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr+21-21
......@@ -1,31 +1,31 @@
11error: the type of the associated constant `K` must not depend on generic parameters
2 --> $DIR/assoc-const-eq-param-in-ty.rs:11:61
2 --> $DIR/assoc-const-eq-param-in-ty.rs:18:77
33 |
4LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
5 | -- the lifetime parameter `'r` is defined here ^ its type must not depend on the lifetime parameter `'r`
4LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
5 | -- the lifetime parameter `'r` is defined here ^ its type must not depend on the lifetime parameter `'r`
66 |
77 = note: `K` has type `&'r [A; Q]`
88
99error: the type of the associated constant `K` must not depend on generic parameters
10 --> $DIR/assoc-const-eq-param-in-ty.rs:11:61
10 --> $DIR/assoc-const-eq-param-in-ty.rs:18:77
1111 |
12LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
13 | - the type parameter `A` is defined here ^ its type must not depend on the type parameter `A`
12LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
13 | - the type parameter `A` is defined here ^ its type must not depend on the type parameter `A`
1414 |
1515 = note: `K` has type `&'r [A; Q]`
1616
1717error: the type of the associated constant `K` must not depend on generic parameters
18 --> $DIR/assoc-const-eq-param-in-ty.rs:11:61
18 --> $DIR/assoc-const-eq-param-in-ty.rs:18:77
1919 |
20LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
21 | - ^ its type must not depend on the const parameter `Q`
22 | |
23 | the const parameter `Q` is defined here
20LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
21 | - ^ its type must not depend on the const parameter `Q`
22 | |
23 | the const parameter `Q` is defined here
2424 |
2525 = note: `K` has type `&'r [A; Q]`
2626
2727error: the type of the associated constant `SELF` must not depend on `impl Trait`
28 --> $DIR/assoc-const-eq-param-in-ty.rs:30:26
28 --> $DIR/assoc-const-eq-param-in-ty.rs:37:26
2929 |
3030LL | fn take1(_: impl Project<SELF = {}>) {}
3131 | -------------^^^^------
......@@ -34,7 +34,7 @@ LL | fn take1(_: impl Project<SELF = {}>) {}
3434 | the `impl Trait` is specified here
3535
3636error: the type of the associated constant `SELF` must not depend on generic parameters
37 --> $DIR/assoc-const-eq-param-in-ty.rs:35:21
37 --> $DIR/assoc-const-eq-param-in-ty.rs:42:21
3838 |
3939LL | fn take2<P: Project<SELF = {}>>(_: P) {}
4040 | - ^^^^ its type must not depend on the type parameter `P`
......@@ -44,9 +44,9 @@ LL | fn take2<P: Project<SELF = {}>>(_: P) {}
4444 = note: `SELF` has type `P`
4545
4646error: the type of the associated constant `K` must not depend on generic parameters
47 --> $DIR/assoc-const-eq-param-in-ty.rs:44:52
47 --> $DIR/assoc-const-eq-param-in-ty.rs:51:52
4848 |
49LL | trait Iface<'r> {
49LL | trait Iface<'r>: ConstParamTy_ {
5050 | -- the lifetime parameter `'r` is defined here
5151...
5252LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
......@@ -55,7 +55,7 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
5555 = note: `K` has type `&'r [Self; Q]`
5656
5757error: the type of the associated constant `K` must not depend on `Self`
58 --> $DIR/assoc-const-eq-param-in-ty.rs:44:52
58 --> $DIR/assoc-const-eq-param-in-ty.rs:51:52
5959 |
6060LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
6161 | ^ its type must not depend on `Self`
......@@ -63,7 +63,7 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
6363 = note: `K` has type `&'r [Self; Q]`
6464
6565error: the type of the associated constant `K` must not depend on generic parameters
66 --> $DIR/assoc-const-eq-param-in-ty.rs:44:52
66 --> $DIR/assoc-const-eq-param-in-ty.rs:51:52
6767 |
6868LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
6969 | - ^ its type must not depend on the const parameter `Q`
......@@ -73,9 +73,9 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
7373 = note: `K` has type `&'r [Self; Q]`
7474
7575error: the type of the associated constant `K` must not depend on generic parameters
76 --> $DIR/assoc-const-eq-param-in-ty.rs:44:52
76 --> $DIR/assoc-const-eq-param-in-ty.rs:51:52
7777 |
78LL | trait Iface<'r> {
78LL | trait Iface<'r>: ConstParamTy_ {
7979 | -- the lifetime parameter `'r` is defined here
8080...
8181LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
......@@ -85,7 +85,7 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
8585 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
8686
8787error: the type of the associated constant `K` must not depend on `Self`
88 --> $DIR/assoc-const-eq-param-in-ty.rs:44:52
88 --> $DIR/assoc-const-eq-param-in-ty.rs:51:52
8989 |
9090LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
9191 | ^ its type must not depend on `Self`
......@@ -94,7 +94,7 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
9494 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
9595
9696error: the type of the associated constant `K` must not depend on generic parameters
97 --> $DIR/assoc-const-eq-param-in-ty.rs:44:52
97 --> $DIR/assoc-const-eq-param-in-ty.rs:51:52
9898 |
9999LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
100100 | - ^ its type must not depend on the const parameter `Q`
tests/ui/associated-consts/assoc-const-eq-supertraits.rs+9-2
......@@ -3,12 +3,19 @@
33
44//@ check-pass
55
6#![feature(associated_const_equality, min_generic_const_args)]
6#![feature(
7 associated_const_equality,
8 min_generic_const_args,
9 adt_const_params,
10 unsized_const_params,
11)]
712#![allow(incomplete_features)]
813
14use std::marker::ConstParamTy_;
15
916trait Trait: SuperTrait {}
1017trait SuperTrait: SuperSuperTrait<i32> {}
11trait SuperSuperTrait<T> {
18trait SuperSuperTrait<T: ConstParamTy_> {
1219 #[type_const]
1320 const K: T;
1421}
tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs+1-1
......@@ -5,7 +5,7 @@
55
66//@ check-pass
77
8#![feature(associated_const_equality, min_generic_const_args)]
8#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)]
99#![allow(incomplete_features)]
1010
1111trait Trait: SuperTrait {
tests/ui/const-generics/const_trait_fn-issue-88433.rs+1-2
......@@ -3,8 +3,7 @@
33
44#![feature(const_trait_impl)]
55
6#[const_trait]
7trait Func<T> {
6const trait Func<T> {
87 type Output;
98
109 fn call_once(self, arg: T) -> Self::Output;
tests/ui/const-generics/issues/issue-88119.rs+1-2
......@@ -3,8 +3,7 @@
33#![allow(incomplete_features)]
44#![feature(const_trait_impl, generic_const_exprs)]
55
6#[const_trait]
7trait ConstName {
6const trait ConstName {
87 const NAME_BYTES: &'static [u8];
98}
109
tests/ui/const-generics/issues/issue-88119.stderr+14-14
......@@ -7,85 +7,85 @@ LL | #![feature(const_trait_impl, generic_const_exprs)]
77 = help: remove one of these features
88
99error[E0275]: overflow evaluating the requirement `&T: [const] ConstName`
10 --> $DIR/issue-88119.rs:19:49
10 --> $DIR/issue-88119.rs:18:49
1111 |
1212LL | impl<T: ?Sized + ConstName> const ConstName for &T
1313 | ^^
1414
1515error[E0275]: overflow evaluating the requirement `&T: ConstName`
16 --> $DIR/issue-88119.rs:19:49
16 --> $DIR/issue-88119.rs:18:49
1717 |
1818LL | impl<T: ?Sized + ConstName> const ConstName for &T
1919 | ^^
2020
2121error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
22 --> $DIR/issue-88119.rs:21:5
22 --> $DIR/issue-88119.rs:20:5
2323 |
2424LL | [(); name_len::<T>()]:,
2525 | ^^^^^^^^^^^^^^^^^^^^^
2626 |
2727note: required by a bound in `<&T as ConstName>`
28 --> $DIR/issue-88119.rs:21:5
28 --> $DIR/issue-88119.rs:20:5
2929 |
3030LL | [(); name_len::<T>()]:,
3131 | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
3232
3333error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
34 --> $DIR/issue-88119.rs:21:10
34 --> $DIR/issue-88119.rs:20:10
3535 |
3636LL | [(); name_len::<T>()]:,
3737 | ^^^^^^^^^^^^^^^
3838 |
3939note: required by a bound in `<&T as ConstName>`
40 --> $DIR/issue-88119.rs:21:5
40 --> $DIR/issue-88119.rs:20:5
4141 |
4242LL | [(); name_len::<T>()]:,
4343 | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
4444
4545error[E0275]: overflow evaluating the requirement `&mut T: [const] ConstName`
46 --> $DIR/issue-88119.rs:26:49
46 --> $DIR/issue-88119.rs:25:49
4747 |
4848LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
4949 | ^^^^^^
5050
5151error[E0275]: overflow evaluating the requirement `&mut T: ConstName`
52 --> $DIR/issue-88119.rs:26:49
52 --> $DIR/issue-88119.rs:25:49
5353 |
5454LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
5555 | ^^^^^^
5656
5757error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
58 --> $DIR/issue-88119.rs:28:5
58 --> $DIR/issue-88119.rs:27:5
5959 |
6060LL | [(); name_len::<T>()]:,
6161 | ^^^^^^^^^^^^^^^^^^^^^
6262 |
6363note: required by a bound in `<&mut T as ConstName>`
64 --> $DIR/issue-88119.rs:28:5
64 --> $DIR/issue-88119.rs:27:5
6565 |
6666LL | [(); name_len::<T>()]:,
6767 | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>`
6868
6969error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
70 --> $DIR/issue-88119.rs:28:10
70 --> $DIR/issue-88119.rs:27:10
7171 |
7272LL | [(); name_len::<T>()]:,
7373 | ^^^^^^^^^^^^^^^
7474 |
7575note: required by a bound in `<&mut T as ConstName>`
76 --> $DIR/issue-88119.rs:28:5
76 --> $DIR/issue-88119.rs:27:5
7777 |
7878LL | [(); name_len::<T>()]:,
7979 | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>`
8080
8181error[E0275]: overflow evaluating the requirement `&&mut u8: ConstName`
82 --> $DIR/issue-88119.rs:33:35
82 --> $DIR/issue-88119.rs:32:35
8383 |
8484LL | pub const ICE_1: &'static [u8] = <&&mut u8 as ConstName>::NAME_BYTES;
8585 | ^^^^^^^^
8686
8787error[E0275]: overflow evaluating the requirement `&mut &u8: ConstName`
88 --> $DIR/issue-88119.rs:34:35
88 --> $DIR/issue-88119.rs:33:35
8989 |
9090LL | pub const ICE_2: &'static [u8] = <&mut &u8 as ConstName>::NAME_BYTES;
9191 | ^^^^^^^^
tests/ui/const-generics/issues/issue-98629.rs+1-2
......@@ -1,7 +1,6 @@
11#![feature(const_trait_impl)]
22
3#[const_trait]
4trait Trait {
3const trait Trait {
54 const N: usize;
65}
76
tests/ui/const-generics/issues/issue-98629.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0046]: not all trait items implemented, missing: `N`
2 --> $DIR/issue-98629.rs:8:1
2 --> $DIR/issue-98629.rs:7:1
33 |
44LL | const N: usize;
55 | -------------- `N` from trait
tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs created+26
......@@ -0,0 +1,26 @@
1//@ check-pass
2
3#![expect(incomplete_features)]
4#![feature(min_generic_const_args, generic_const_items)]
5
6pub trait Tr<const X: usize> {
7 #[type_const]
8 const N1<T>: usize;
9 #[type_const]
10 const N2<const I: usize>: usize;
11 #[type_const]
12 const N3: usize;
13}
14
15pub struct S;
16
17impl<const X: usize> Tr<X> for S {
18 #[type_const]
19 const N1<T>: usize = 0;
20 #[type_const]
21 const N2<const I: usize>: usize = 1;
22 #[type_const]
23 const N3: usize = 2;
24}
25
26fn main() {}
tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs created+17
......@@ -0,0 +1,17 @@
1// Regression test for #140729
2
3#![expect(incomplete_features)]
4#![feature(min_generic_const_args)]
5
6const C: usize = 0;
7pub struct A<const M: usize> {}
8impl A<C> {
9 fn fun1() {}
10 //~^ ERROR duplicate definitions with name `fun1`
11}
12impl A {
13 //~^ ERROR missing generics for struct `A`
14 fn fun1() {}
15}
16
17fn main() {}
tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr created+29
......@@ -0,0 +1,29 @@
1error[E0107]: missing generics for struct `A`
2 --> $DIR/const-arg-coherence-conflicting-methods.rs:12:6
3 |
4LL | impl A {
5 | ^ expected 1 generic argument
6 |
7note: struct defined here, with 1 generic parameter: `M`
8 --> $DIR/const-arg-coherence-conflicting-methods.rs:7:12
9 |
10LL | pub struct A<const M: usize> {}
11 | ^ --------------
12help: add missing generic argument
13 |
14LL | impl A<M> {
15 | +++
16
17error[E0592]: duplicate definitions with name `fun1`
18 --> $DIR/const-arg-coherence-conflicting-methods.rs:9:5
19 |
20LL | fn fun1() {}
21 | ^^^^^^^^^ duplicate definitions for `fun1`
22...
23LL | fn fun1() {}
24 | --------- other definition for `fun1`
25
26error: aborting due to 2 previous errors
27
28Some errors have detailed explanations: E0107, E0592.
29For more information about an error, try `rustc --explain E0107`.
tests/ui/const-generics/mgca/type_const-mismatched-types.rs created+23
......@@ -0,0 +1,23 @@
1#![expect(incomplete_features)]
2#![feature(min_generic_const_args)]
3
4#[type_const]
5const FREE: u32 = 5_usize;
6//~^ ERROR mismatched types
7
8#[type_const]
9const FREE2: isize = FREE;
10//~^ ERROR the constant `5` is not of type `isize`
11
12trait Tr {
13 #[type_const]
14 const N: usize;
15}
16
17impl Tr for () {
18 #[type_const]
19 const N: usize = false;
20 //~^ ERROR mismatched types
21}
22
23fn main() {}
tests/ui/const-generics/mgca/type_const-mismatched-types.stderr created+27
......@@ -0,0 +1,27 @@
1error: the constant `5` is not of type `isize`
2 --> $DIR/type_const-mismatched-types.rs:9:1
3 |
4LL | const FREE2: isize = FREE;
5 | ^^^^^^^^^^^^^^^^^^ expected `isize`, found `u32`
6
7error[E0308]: mismatched types
8 --> $DIR/type_const-mismatched-types.rs:5:19
9 |
10LL | const FREE: u32 = 5_usize;
11 | ^^^^^^^ expected `u32`, found `usize`
12 |
13help: change the type of the numeric literal from `usize` to `u32`
14 |
15LL - const FREE: u32 = 5_usize;
16LL + const FREE: u32 = 5_u32;
17 |
18
19error[E0308]: mismatched types
20 --> $DIR/type_const-mismatched-types.rs:19:22
21 |
22LL | const N: usize = false;
23 | ^^^^^ expected `usize`, found `bool`
24
25error: aborting due to 3 previous errors
26
27For more information about this error, try `rustc --explain E0308`.
tests/ui/const-generics/mgca/type_const-not-constparamty.rs created+26
......@@ -0,0 +1,26 @@
1#![expect(incomplete_features)]
2#![feature(min_generic_const_args)]
3
4struct S;
5
6// FIXME(mgca): need support for ctors without anon const
7// (we use double-braces to trigger an anon const here)
8#[type_const]
9const FREE: S = { { S } };
10//~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
11
12trait Tr {
13 #[type_const]
14 const N: S;
15 //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
16}
17
18impl Tr for S {
19 // FIXME(mgca): need support for ctors without anon const
20 // (we use double-braces to trigger an anon const here)
21 #[type_const]
22 const N: S = { { S } };
23 //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
24}
25
26fn main() {}
tests/ui/const-generics/mgca/type_const-not-constparamty.stderr created+39
......@@ -0,0 +1,39 @@
1error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
2 --> $DIR/type_const-not-constparamty.rs:9:13
3 |
4LL | const FREE: S = { { S } };
5 | ^
6 |
7help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct
8 |
9LL + #[derive(ConstParamTy, PartialEq, Eq)]
10LL | struct S;
11 |
12
13error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
14 --> $DIR/type_const-not-constparamty.rs:22:14
15 |
16LL | const N: S = { { S } };
17 | ^
18 |
19help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct
20 |
21LL + #[derive(ConstParamTy, PartialEq, Eq)]
22LL | struct S;
23 |
24
25error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
26 --> $DIR/type_const-not-constparamty.rs:14:14
27 |
28LL | const N: S;
29 | ^
30 |
31help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct
32 |
33LL + #[derive(ConstParamTy, PartialEq, Eq)]
34LL | struct S;
35 |
36
37error: aborting due to 3 previous errors
38
39For more information about this error, try `rustc --explain E0741`.
tests/ui/const-generics/mgca/type_const-on-generic-expr.rs created+34
......@@ -0,0 +1,34 @@
1#![expect(incomplete_features)]
2#![feature(min_generic_const_args, generic_const_items)]
3
4#[type_const]
5const FREE1<T>: usize = std::mem::size_of::<T>();
6//~^ ERROR generic parameters may not be used in const operations
7#[type_const]
8const FREE2<const I: usize>: usize = I + 1;
9//~^ ERROR generic parameters may not be used in const operations
10
11pub trait Tr<const X: usize> {
12 #[type_const]
13 const N1<T>: usize;
14 #[type_const]
15 const N2<const I: usize>: usize;
16 #[type_const]
17 const N3: usize;
18}
19
20pub struct S;
21
22impl<const X: usize> Tr<X> for S {
23 #[type_const]
24 const N1<T>: usize = std::mem::size_of::<T>();
25 //~^ ERROR generic parameters may not be used in const operations
26 #[type_const]
27 const N2<const I: usize>: usize = I + 1;
28 //~^ ERROR generic parameters may not be used in const operations
29 #[type_const]
30 const N3: usize = 2 & X;
31 //~^ ERROR generic parameters may not be used in const operations
32}
33
34fn main() {}
tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr created+47
......@@ -0,0 +1,47 @@
1error: generic parameters may not be used in const operations
2 --> $DIR/type_const-on-generic-expr.rs:5:45
3 |
4LL | const FREE1<T>: usize = std::mem::size_of::<T>();
5 | ^ cannot perform const operation using `T`
6 |
7 = note: type parameters may not be used in const expressions
8 = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
9
10error: generic parameters may not be used in const operations
11 --> $DIR/type_const-on-generic-expr.rs:8:38
12 |
13LL | const FREE2<const I: usize>: usize = I + 1;
14 | ^ cannot perform const operation using `I`
15 |
16 = help: const parameters may only be used as standalone arguments here, i.e. `I`
17 = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
18
19error: generic parameters may not be used in const operations
20 --> $DIR/type_const-on-generic-expr.rs:24:46
21 |
22LL | const N1<T>: usize = std::mem::size_of::<T>();
23 | ^ cannot perform const operation using `T`
24 |
25 = note: type parameters may not be used in const expressions
26 = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
27
28error: generic parameters may not be used in const operations
29 --> $DIR/type_const-on-generic-expr.rs:27:39
30 |
31LL | const N2<const I: usize>: usize = I + 1;
32 | ^ cannot perform const operation using `I`
33 |
34 = help: const parameters may only be used as standalone arguments here, i.e. `I`
35 = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
36
37error: generic parameters may not be used in const operations
38 --> $DIR/type_const-on-generic-expr.rs:30:27
39 |
40LL | const N3: usize = 2 & X;
41 | ^ cannot perform const operation using `X`
42 |
43 = help: const parameters may only be used as standalone arguments here, i.e. `X`
44 = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
45
46error: aborting due to 5 previous errors
47
tests/ui/const-generics/mgca/type_const-only-in-trait.rs created+20
......@@ -0,0 +1,20 @@
1#![expect(incomplete_features)]
2#![feature(associated_const_equality, min_generic_const_args)]
3
4trait GoodTr {
5 #[type_const]
6 const NUM: usize;
7}
8
9struct BadS;
10
11impl GoodTr for BadS {
12 const NUM: usize = 42;
13 //~^ ERROR implementation of `#[type_const]` const must be marked with `#[type_const]`
14}
15
16fn accept_good_tr<const N: usize, T: GoodTr<NUM = { N }>>(_x: &T) {}
17
18fn main() {
19 accept_good_tr(&BadS);
20}
tests/ui/const-generics/mgca/type_const-only-in-trait.stderr created+16
......@@ -0,0 +1,16 @@
1error: implementation of `#[type_const]` const must be marked with `#[type_const]`
2 --> $DIR/type_const-only-in-trait.rs:12:5
3 |
4LL | const NUM: usize = 42;
5 | ^^^^^^^^^^^^^^^^
6 |
7note: trait declaration of const is marked with `#[type_const]`
8 --> $DIR/type_const-only-in-trait.rs:5:5
9 |
10LL | #[type_const]
11 | ^^^^^^^^^^^^^
12LL | const NUM: usize;
13 | ^^^^^^^^^^^^^^^^
14
15error: aborting due to 1 previous error
16
tests/ui/const-generics/mgca/using-fnptr-as-type_const.rs created+14
......@@ -0,0 +1,14 @@
1// Regression test for #119783
2
3#![expect(incomplete_features)]
4#![feature(associated_const_equality, min_generic_const_args)]
5
6trait Trait {
7 #[type_const]
8 const F: fn();
9 //~^ ERROR using function pointers as const generic parameters is forbidden
10}
11
12fn take(_: impl Trait<F = { || {} }>) {}
13
14fn main() {}
tests/ui/const-generics/mgca/using-fnptr-as-type_const.stderr created+9
......@@ -0,0 +1,9 @@
1error[E0741]: using function pointers as const generic parameters is forbidden
2 --> $DIR/using-fnptr-as-type_const.rs:8:14
3 |
4LL | const F: fn();
5 | ^^^^
6
7error: aborting due to 1 previous error
8
9For more information about this error, try `rustc --explain E0741`.
tests/ui/consts/constifconst-call-in-const-position.rs+1-2
......@@ -3,8 +3,7 @@
33#![feature(const_trait_impl, generic_const_exprs)]
44#![allow(incomplete_features)]
55
6#[const_trait]
7pub trait Tr {
6pub const trait Tr {
87 fn a() -> usize;
98}
109
tests/ui/consts/constifconst-call-in-const-position.stderr+2-2
......@@ -1,11 +1,11 @@
11error[E0277]: the trait bound `T: const Tr` is not satisfied
2 --> $DIR/constifconst-call-in-const-position.rs:17:39
2 --> $DIR/constifconst-call-in-const-position.rs:16:39
33 |
44LL | const fn foo<T: [const] Tr>() -> [u8; T::a()] {
55 | ^
66
77error[E0277]: the trait bound `T: const Tr` is not satisfied
8 --> $DIR/constifconst-call-in-const-position.rs:18:9
8 --> $DIR/constifconst-call-in-const-position.rs:17:9
99 |
1010LL | [0; T::a()]
1111 | ^
tests/ui/delegation/unsupported.current.stderr+1-1
......@@ -46,7 +46,7 @@ LL | reuse to_reuse1::foo;
4646 | ^^^
4747
4848error[E0283]: type annotations needed
49 --> $DIR/unsupported.rs:56:18
49 --> $DIR/unsupported.rs:55:18
5050 |
5151LL | reuse Trait::foo;
5252 | ^^^ cannot infer type
tests/ui/delegation/unsupported.next.stderr+1-1
......@@ -38,7 +38,7 @@ LL | reuse to_reuse1::foo;
3838 | ^^^
3939
4040error[E0283]: type annotations needed
41 --> $DIR/unsupported.rs:56:18
41 --> $DIR/unsupported.rs:55:18
4242 |
4343LL | reuse Trait::foo;
4444 | ^^^ cannot infer type
tests/ui/delegation/unsupported.rs+1-2
......@@ -48,8 +48,7 @@ mod recursive {
4848}
4949
5050mod effects {
51 #[const_trait]
52 trait Trait {
51 const trait Trait {
5352 fn foo();
5453 }
5554
tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs+1-1
......@@ -1,6 +1,6 @@
11// ICE: assertion failed: !value.has_infer()
22// issue: rust-lang/rust#115806
3#![feature(associated_const_equality, min_generic_const_args)]
3#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)]
44#![allow(incomplete_features)]
55
66pub struct NoPin;
tests/ui/generic-const-items/associated-const-equality.rs+7-5
......@@ -9,8 +9,8 @@ trait Owner {
99 const C<const N: u32>: u32;
1010 #[type_const]
1111 const K<const N: u32>: u32;
12 #[type_const]
13 const Q<T>: Maybe<T>;
12 // #[type_const]
13 // const Q<T>: Maybe<T>;
1414}
1515
1616impl Owner for () {
......@@ -18,13 +18,15 @@ impl Owner for () {
1818 const C<const N: u32>: u32 = N;
1919 #[type_const]
2020 const K<const N: u32>: u32 = 99 + 1;
21 #[type_const]
22 const Q<T>: Maybe<T> = Maybe::Nothing;
21 // FIXME(mgca): re-enable once we properly support ctors and generics on paths
22 // #[type_const]
23 // const Q<T>: Maybe<T> = Maybe::Nothing;
2324}
2425
2526fn take0<const N: u32>(_: impl Owner<C<N> = { N }>) {}
2627fn take1(_: impl Owner<K<99> = 100>) {}
27fn take2(_: impl Owner<Q<()> = { Maybe::Just(()) }>) {}
28// FIXME(mgca): re-enable once we properly support ctors and generics on paths
29// fn take2(_: impl Owner<Q<()> = { Maybe::Just(()) }>) {}
2830
2931fn main() {
3032 take0::<128>(());
tests/ui/generic-const-items/const-trait-impl.rs+2-3
......@@ -11,8 +11,7 @@ const CREATE<T: const Create>: T = T::create();
1111pub const K0: i32 = CREATE::<i32>;
1212pub const K1: i32 = CREATE; // arg inferred
1313
14#[const_trait]
15trait Create {
14const trait Create {
1615 fn create() -> Self;
1716}
1817
......@@ -22,7 +21,7 @@ impl const Create for i32 {
2221 }
2322}
2423
25trait Mod { // doesn't need to be a `#[const_trait]`
24trait Mod { // doesn't need to be a const trait
2625 const CREATE<T: const Create>: T;
2726}
2827
tests/ui/parser/impls-nested-within-fns-semantic-1.rs+1-2
......@@ -4,8 +4,7 @@
44
55#![feature(const_trait_impl)]
66
7#[const_trait]
8trait Trait {
7const trait Trait {
98 fn required();
109}
1110
tests/ui/resolve/issue-39559-2.stderr+6-8
......@@ -11,13 +11,12 @@ LL | trait Dim {
1111 | ^^^^^^^^^ this trait is not const
1212LL | fn dim() -> usize;
1313 | ------------------ this associated function is not const
14 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]`
14 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable const traits
1515 = note: calls in constants are limited to constant functions, tuple structs and tuple variants
1616help: consider making trait `Dim` const
1717 |
18LL + #[const_trait]
19LL | trait Dim {
20 |
18LL | const trait Dim {
19 | +++++
2120
2221error[E0015]: cannot call non-const associated function `<Dim3 as Dim>::dim` in constants
2322 --> $DIR/issue-39559-2.rs:16:15
......@@ -32,13 +31,12 @@ LL | trait Dim {
3231 | ^^^^^^^^^ this trait is not const
3332LL | fn dim() -> usize;
3433 | ------------------ this associated function is not const
35 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]`
34 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable const traits
3635 = note: calls in constants are limited to constant functions, tuple structs and tuple variants
3736help: consider making trait `Dim` const
3837 |
39LL + #[const_trait]
40LL | trait Dim {
41 |
38LL | const trait Dim {
39 | +++++
4240
4341error: aborting due to 2 previous errors
4442
tests/ui/specialization/const_trait_impl.rs+3-6
......@@ -5,14 +5,12 @@
55use std::fmt::Debug;
66
77#[rustc_specialization_trait]
8#[const_trait]
9pub unsafe trait Sup {
8pub const unsafe trait Sup {
109 fn foo() -> u32;
1110}
1211
1312#[rustc_specialization_trait]
14#[const_trait]
15pub unsafe trait Sub: [const] Sup {}
13pub const unsafe trait Sub: [const] Sup {}
1614
1715unsafe impl const Sup for u8 {
1816 default fn foo() -> u32 {
......@@ -28,8 +26,7 @@ unsafe impl const Sup for () {
2826
2927unsafe impl const Sub for () {}
3028
31#[const_trait]
32pub trait A {
29pub const trait A {
3330 fn a() -> u32;
3431}
3532
tests/ui/specialization/const_trait_impl.stderr+6-6
......@@ -1,5 +1,5 @@
11error: `[const]` can only be applied to `const` traits
2 --> $DIR/const_trait_impl.rs:36:9
2 --> $DIR/const_trait_impl.rs:33:9
33 |
44LL | impl<T: [const] Debug> const A for T {
55 | ^^^^^^^ can't be applied to `Debug`
......@@ -8,7 +8,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const`
88 --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
99
1010error: `[const]` can only be applied to `const` traits
11 --> $DIR/const_trait_impl.rs:42:9
11 --> $DIR/const_trait_impl.rs:39:9
1212 |
1313LL | impl<T: [const] Debug + [const] Sup> const A for T {
1414 | ^^^^^^^ can't be applied to `Debug`
......@@ -17,7 +17,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const`
1717 --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
1818
1919error: `[const]` can only be applied to `const` traits
20 --> $DIR/const_trait_impl.rs:48:9
20 --> $DIR/const_trait_impl.rs:45:9
2121 |
2222LL | impl<T: [const] Debug + [const] Sub> const A for T {
2323 | ^^^^^^^ can't be applied to `Debug`
......@@ -26,7 +26,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const`
2626 --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
2727
2828error: `[const]` can only be applied to `const` traits
29 --> $DIR/const_trait_impl.rs:42:9
29 --> $DIR/const_trait_impl.rs:39:9
3030 |
3131LL | impl<T: [const] Debug + [const] Sup> const A for T {
3232 | ^^^^^^^ can't be applied to `Debug`
......@@ -36,7 +36,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const`
3636 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
3737
3838error: `[const]` can only be applied to `const` traits
39 --> $DIR/const_trait_impl.rs:36:9
39 --> $DIR/const_trait_impl.rs:33:9
4040 |
4141LL | impl<T: [const] Debug> const A for T {
4242 | ^^^^^^^ can't be applied to `Debug`
......@@ -46,7 +46,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const`
4646 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
4747
4848error: `[const]` can only be applied to `const` traits
49 --> $DIR/const_trait_impl.rs:48:9
49 --> $DIR/const_trait_impl.rs:45:9
5050 |
5151LL | impl<T: [const] Debug + [const] Sub> const A for T {
5252 | ^^^^^^^ can't be applied to `Debug`
tests/ui/structs/default-field-values/support.rs+1-1
......@@ -27,7 +27,7 @@ pub enum Bar {
2727 }
2828}
2929
30#[const_trait] pub trait ConstDefault {
30pub const trait ConstDefault {
3131 fn value() -> Self;
3232}
3333
tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs+1-2
......@@ -4,8 +4,7 @@
44
55#![feature(const_trait_impl)]
66
7#[const_trait]
8trait Trait {
7const trait Trait {
98 type Assoc: [const] Trait;
109 fn func() -> i32;
1110}
tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs+1-2
......@@ -3,8 +3,7 @@
33#![feature(const_trait_impl, generic_const_exprs)]
44#![allow(incomplete_features)]
55
6#[const_trait]
7trait Trait {
6const trait Trait {
87 type Assoc: [const] Trait;
98 fn func() -> i32;
109}
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr+2-2
......@@ -1,11 +1,11 @@
11error[E0277]: the trait bound `U: [const] Other` is not satisfied
2 --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5
2 --> $DIR/assoc-type-const-bound-usage-fail-2.rs:22:5
33 |
44LL | T::Assoc::<U>::func();
55 | ^^^^^^^^^^^^^
66
77error[E0277]: the trait bound `U: [const] Other` is not satisfied
8 --> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5
8 --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5
99 |
1010LL | <T as Trait>::Assoc::<U>::func();
1111 | ^^^^^^^^^^^^^^^^^^^^^^^^
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr+2-2
......@@ -1,11 +1,11 @@
11error[E0277]: the trait bound `U: [const] Other` is not satisfied
2 --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5
2 --> $DIR/assoc-type-const-bound-usage-fail-2.rs:22:5
33 |
44LL | T::Assoc::<U>::func();
55 | ^^^^^^^^^^^^^
66
77error[E0277]: the trait bound `U: [const] Other` is not satisfied
8 --> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5
8 --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5
99 |
1010LL | <T as Trait>::Assoc::<U>::func();
1111 | ^^^^^^^^^^^^^^^^^^^^^^^^
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs+2-4
......@@ -8,8 +8,7 @@
88
99#![feature(const_trait_impl)]
1010
11#[const_trait]
12trait Trait {
11const trait Trait {
1312 type Assoc<U>: [const] Trait
1413 where
1514 U: [const] Other;
......@@ -17,8 +16,7 @@ trait Trait {
1716 fn func();
1817}
1918
20#[const_trait]
21trait Other {}
19const trait Other {}
2220
2321const fn fails<T: [const] Trait, U: Other>() {
2422 T::Assoc::<U>::func();
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.current.stderr+2-2
......@@ -1,11 +1,11 @@
11error[E0277]: the trait bound `T: [const] Trait` is not satisfied
2 --> $DIR/assoc-type-const-bound-usage-fail.rs:17:5
2 --> $DIR/assoc-type-const-bound-usage-fail.rs:16:5
33 |
44LL | T::Assoc::func();
55 | ^^^^^^^^
66
77error[E0277]: the trait bound `T: [const] Trait` is not satisfied
8 --> $DIR/assoc-type-const-bound-usage-fail.rs:19:5
8 --> $DIR/assoc-type-const-bound-usage-fail.rs:18:5
99 |
1010LL | <T as Trait>::Assoc::func();
1111 | ^^^^^^^^^^^^^^^^^^^
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr+2-2
......@@ -1,11 +1,11 @@
11error[E0277]: the trait bound `T: [const] Trait` is not satisfied
2 --> $DIR/assoc-type-const-bound-usage-fail.rs:17:5
2 --> $DIR/assoc-type-const-bound-usage-fail.rs:16:5
33 |
44LL | T::Assoc::func();
55 | ^^^^^^^^
66
77error[E0277]: the trait bound `T: [const] Trait` is not satisfied
8 --> $DIR/assoc-type-const-bound-usage-fail.rs:19:5
8 --> $DIR/assoc-type-const-bound-usage-fail.rs:18:5
99 |
1010LL | <T as Trait>::Assoc::func();
1111 | ^^^^^^^^^^^^^^^^^^^
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs+1-2
......@@ -7,8 +7,7 @@
77
88#![feature(const_trait_impl)]
99
10#[const_trait]
11trait Trait {
10const trait Trait {
1211 type Assoc: [const] Trait;
1312 fn func();
1413}
tests/ui/traits/const-traits/assoc-type.current.stderr+2-2
......@@ -1,11 +1,11 @@
11error[E0277]: the trait bound `NonConstAdd: [const] Add` is not satisfied
2 --> $DIR/assoc-type.rs:37:16
2 --> $DIR/assoc-type.rs:35:16
33 |
44LL | type Bar = NonConstAdd;
55 | ^^^^^^^^^^^
66 |
77note: required by a bound in `Foo::Bar`
8 --> $DIR/assoc-type.rs:33:15
8 --> $DIR/assoc-type.rs:31:15
99 |
1010LL | type Bar: [const] Add;
1111 | ^^^^^^^^^^^ required by this bound in `Foo::Bar`
tests/ui/traits/const-traits/assoc-type.next.stderr+2-2
......@@ -1,11 +1,11 @@
11error[E0277]: the trait bound `NonConstAdd: [const] Add` is not satisfied
2 --> $DIR/assoc-type.rs:37:16
2 --> $DIR/assoc-type.rs:35:16
33 |
44LL | type Bar = NonConstAdd;
55 | ^^^^^^^^^^^
66 |
77note: required by a bound in `Foo::Bar`
8 --> $DIR/assoc-type.rs:33:15
8 --> $DIR/assoc-type.rs:31:15
99 |
1010LL | type Bar: [const] Add;
1111 | ^^^^^^^^^^^ required by this bound in `Foo::Bar`
tests/ui/traits/const-traits/assoc-type.rs+3-6
......@@ -3,8 +3,7 @@
33
44#![feature(const_trait_impl)]
55
6#[const_trait]
7trait Add<Rhs = Self> {
6const trait Add<Rhs = Self> {
87 type Output;
98
109 fn add(self, other: Rhs) -> Self::Output;
......@@ -28,8 +27,7 @@ impl Add for NonConstAdd {
2827 }
2928}
3029
31#[const_trait]
32trait Foo {
30const trait Foo {
3331 type Bar: [const] Add;
3432}
3533
......@@ -38,8 +36,7 @@ impl const Foo for NonConstAdd {
3836 //~^ ERROR the trait bound `NonConstAdd: [const] Add` is not satisfied
3937}
4038
41#[const_trait]
42trait Baz {
39const trait Baz {
4340 type Qux: Add;
4441}
4542
tests/ui/traits/const-traits/attr-misuse.rs deleted-10
......@@ -1,10 +0,0 @@
1#![feature(const_trait_impl)]
2
3#[const_trait]
4trait A {
5 #[const_trait] //~ ERROR attribute cannot be used on
6 fn foo(self);
7}
8
9#[const_trait] //~ ERROR attribute cannot be used on
10fn main() {}
tests/ui/traits/const-traits/attr-misuse.stderr deleted-18
......@@ -1,18 +0,0 @@
1error: `#[const_trait]` attribute cannot be used on required trait methods
2 --> $DIR/attr-misuse.rs:5:5
3 |
4LL | #[const_trait]
5 | ^^^^^^^^^^^^^^
6 |
7 = help: `#[const_trait]` can only be applied to traits
8
9error: `#[const_trait]` attribute cannot be used on functions
10 --> $DIR/attr-misuse.rs:9:1
11 |
12LL | #[const_trait]
13 | ^^^^^^^^^^^^^^
14 |
15 = help: `#[const_trait]` can only be applied to traits
16
17error: aborting due to 2 previous errors
18
tests/ui/traits/const-traits/auxiliary/cross-crate.rs+1-2
......@@ -1,8 +1,7 @@
11//@ compile-flags: -Znext-solver
22#![feature(const_trait_impl)]
33
4#[const_trait]
5pub trait MyTrait {
4pub const trait MyTrait {
65 fn defaulted_func(&self) {}
76 fn func(self);
87}
tests/ui/traits/const-traits/auxiliary/minicore.rs+17-34
......@@ -35,8 +35,7 @@ impl Copy for u8 {}
3535impl<T: PointeeSized> Copy for &T {}
3636
3737#[lang = "add"]
38#[const_trait]
39pub trait Add<Rhs = Self> {
38pub const trait Add<Rhs = Self> {
4039 type Output;
4140
4241 fn add(self, rhs: Rhs) -> Self::Output;
......@@ -58,8 +57,7 @@ const fn bar() {
5857}
5958
6059#[lang = "Try"]
61#[const_trait]
62pub trait Try: FromResidual<Self::Residual> {
60pub const trait Try: FromResidual<Self::Residual> {
6361 type Output;
6462 type Residual;
6563
......@@ -70,8 +68,7 @@ pub trait Try: FromResidual<Self::Residual> {
7068 fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
7169}
7270
73#[const_trait]
74pub trait FromResidual<R = <Self as Try>::Residual> {
71pub const trait FromResidual<R = <Self as Try>::Residual> {
7572 #[lang = "from_residual"]
7673 fn from_residual(residual: R) -> Self;
7774}
......@@ -83,24 +80,21 @@ enum ControlFlow<B, C = ()> {
8380 Break(B),
8481}
8582
86#[const_trait]
8783#[lang = "fn"]
8884#[rustc_paren_sugar]
89pub trait Fn<Args: Tuple>: [const] FnMut<Args> {
85pub const trait Fn<Args: Tuple>: [const] FnMut<Args> {
9086 extern "rust-call" fn call(&self, args: Args) -> Self::Output;
9187}
9288
93#[const_trait]
9489#[lang = "fn_mut"]
9590#[rustc_paren_sugar]
96pub trait FnMut<Args: Tuple>: [const] FnOnce<Args> {
91pub const trait FnMut<Args: Tuple>: [const] FnOnce<Args> {
9792 extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
9893}
9994
100#[const_trait]
10195#[lang = "fn_once"]
10296#[rustc_paren_sugar]
103pub trait FnOnce<Args: Tuple> {
97pub const trait FnOnce<Args: Tuple> {
10498 #[lang = "fn_once_output"]
10599 type Output;
106100
......@@ -128,20 +122,17 @@ impl<T: Deref + MetaSized> Receiver for T {
128122}
129123
130124#[lang = "destruct"]
131#[const_trait]
132pub trait Destruct {}
125pub const trait Destruct {}
133126
134127#[lang = "freeze"]
135128pub unsafe auto trait Freeze {}
136129
137130#[lang = "drop"]
138#[const_trait]
139pub trait Drop {
131pub const trait Drop {
140132 fn drop(&mut self);
141133}
142134
143#[const_trait]
144pub trait Residual<O> {
135pub const trait Residual<O> {
145136 type TryType: [const] Try<Output = O, Residual = Self> + Try<Output = O, Residual = Self>;
146137}
147138
......@@ -168,15 +159,13 @@ const fn panic_display() {
168159fn panic_fmt() {}
169160
170161#[lang = "index"]
171#[const_trait]
172pub trait Index<Idx: PointeeSized> {
162pub const trait Index<Idx: PointeeSized> {
173163 type Output: MetaSized;
174164
175165 fn index(&self, index: Idx) -> &Self::Output;
176166}
177167
178#[const_trait]
179pub unsafe trait SliceIndex<T: PointeeSized> {
168pub const unsafe trait SliceIndex<T: PointeeSized> {
180169 type Output: MetaSized;
181170 fn index(self, slice: &T) -> &Self::Output;
182171}
......@@ -214,8 +203,7 @@ pub trait CoerceUnsized<T: PointeeSized> {}
214203impl<'a, 'b: 'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {}
215204
216205#[lang = "deref"]
217#[const_trait]
218pub trait Deref {
206pub const trait Deref {
219207 #[lang = "deref_target"]
220208 type Target: MetaSized;
221209
......@@ -273,13 +261,11 @@ where
273261 }
274262}
275263
276#[const_trait]
277pub trait Into<T>: Sized {
264pub const trait Into<T>: Sized {
278265 fn into(self) -> T;
279266}
280267
281#[const_trait]
282pub trait From<T>: Sized {
268pub const trait From<T>: Sized {
283269 fn from(value: T) -> Self;
284270}
285271
......@@ -313,8 +299,7 @@ fn from_str(s: &str) -> Result<bool, ()> {
313299}
314300
315301#[lang = "eq"]
316#[const_trait]
317pub trait PartialEq<Rhs: PointeeSized = Self>: PointeeSized {
302pub const trait PartialEq<Rhs: PointeeSized = Self>: PointeeSized {
318303 fn eq(&self, other: &Rhs) -> bool;
319304 fn ne(&self, other: &Rhs) -> bool {
320305 !self.eq(other)
......@@ -337,8 +322,7 @@ impl PartialEq for str {
337322}
338323
339324#[lang = "not"]
340#[const_trait]
341pub trait Not {
325pub const trait Not {
342326 type Output;
343327 fn not(self) -> Self::Output;
344328}
......@@ -462,8 +446,7 @@ impl<T: MetaSized> Deref for Ref<'_, T> {
462446
463447#[lang = "clone"]
464448#[rustc_trivial_field_reads]
465#[const_trait]
466pub trait Clone: Sized {
449pub const trait Clone: Sized {
467450 fn clone(&self) -> Self;
468451 fn clone_from(&mut self, source: &Self)
469452 where
tests/ui/traits/const-traits/auxiliary/staged-api.rs+1-2
......@@ -5,8 +5,7 @@
55
66#[stable(feature = "rust1", since = "1.0.0")]
77#[rustc_const_unstable(feature = "unstable", issue = "none")]
8#[const_trait]
9pub trait MyTrait {
8pub const trait MyTrait {
109 #[stable(feature = "rust1", since = "1.0.0")]
1110 fn func();
1211}
tests/ui/traits/const-traits/call-const-closure.rs+1-2
......@@ -4,8 +4,7 @@
44#![feature(const_trait_impl, const_closures)]
55#![allow(incomplete_features)]
66
7#[const_trait]
8trait Bar {
7const trait Bar {
98 fn foo(&self);
109}
1110
tests/ui/traits/const-traits/call-const-closure.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `(): [const] Bar` is not satisfied
2 --> $DIR/call-const-closure.rs:17:18
2 --> $DIR/call-const-closure.rs:16:18
33 |
44LL | (const || ().foo())();
55 | ^^^
tests/ui/traits/const-traits/call-const-in-conditionally-const.rs+1-1
......@@ -1,7 +1,7 @@
11//@ compile-flags: -Znext-solver
22#![feature(const_trait_impl)]
33
4#[const_trait] trait Foo {
4const trait Foo {
55 fn foo();
66}
77
tests/ui/traits/const-traits/call-const-trait-method-fail.rs+1-2
......@@ -1,8 +1,7 @@
11//@ compile-flags: -Znext-solver
22#![feature(const_trait_impl)]
33
4#[const_trait]
5pub trait Plus {
4pub const trait Plus {
65 fn plus(self, rhs: Self) -> Self;
76}
87
tests/ui/traits/const-traits/call-const-trait-method-fail.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `u32: [const] Plus` is not satisfied
2 --> $DIR/call-const-trait-method-fail.rs:26:5
2 --> $DIR/call-const-trait-method-fail.rs:25:5
33 |
44LL | a.plus(b)
55 | ^
tests/ui/traits/const-traits/call-const-trait-method-pass.rs+1-2
......@@ -20,8 +20,7 @@ impl const PartialEq for Int {
2020 }
2121}
2222
23#[const_trait]
24pub trait Plus {
23pub const trait Plus {
2524 fn plus(self, rhs: Self) -> Self;
2625}
2726
tests/ui/traits/const-traits/call-generic-in-impl.rs+1-2
......@@ -1,8 +1,7 @@
11//@ check-pass
22#![feature(const_trait_impl, const_cmp)]
33
4#[const_trait]
5trait MyPartialEq {
4const trait MyPartialEq {
65 fn eq(&self, other: &Self) -> bool;
76}
87
tests/ui/traits/const-traits/call-generic-method-nonconst.rs+1-2
......@@ -3,8 +3,7 @@
33
44struct S;
55
6#[const_trait]
7trait Foo {
6const trait Foo {
87 fn eq(&self, _: &Self) -> bool;
98}
109
tests/ui/traits/const-traits/call-generic-method-nonconst.stderr+2-2
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `S: const Foo` is not satisfied
2 --> $DIR/call-generic-method-nonconst.rs:24:34
2 --> $DIR/call-generic-method-nonconst.rs:23:34
33 |
44LL | pub const EQ: bool = equals_self(&S);
55 | ----------- ^^
......@@ -7,7 +7,7 @@ LL | pub const EQ: bool = equals_self(&S);
77 | required by a bound introduced by this call
88 |
99note: required by a bound in `equals_self`
10 --> $DIR/call-generic-method-nonconst.rs:17:25
10 --> $DIR/call-generic-method-nonconst.rs:16:25
1111 |
1212LL | const fn equals_self<T: [const] Foo>(t: &T) -> bool {
1313 | ^^^^^^^^^^^ required by this bound in `equals_self`
tests/ui/traits/const-traits/conditionally-const-and-const-params.rs+1-2
......@@ -12,8 +12,7 @@ impl<const N: usize> Foo<N> {
1212 }
1313}
1414
15#[const_trait]
16trait Add42 {
15const trait Add42 {
1716 fn add(a: usize) -> usize;
1817}
1918
tests/ui/traits/const-traits/conditionally-const-and-const-params.stderr+3-3
......@@ -11,19 +11,19 @@ LL | fn add<A: [const] Add42>(self) -> Foo<{ A::add(N) }> {
1111 | ^^^
1212
1313error: `[const]` is not allowed here
14 --> $DIR/conditionally-const-and-const-params.rs:26:11
14 --> $DIR/conditionally-const-and-const-params.rs:25:11
1515 |
1616LL | fn bar<A: [const] Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
1717 | ^^^^^^^
1818 |
1919note: this function is not `const`, so it cannot have `[const]` trait bounds
20 --> $DIR/conditionally-const-and-const-params.rs:26:4
20 --> $DIR/conditionally-const-and-const-params.rs:25:4
2121 |
2222LL | fn bar<A: [const] Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
2323 | ^^^
2424
2525error[E0277]: the trait bound `A: const Add42` is not satisfied
26 --> $DIR/conditionally-const-and-const-params.rs:26:62
26 --> $DIR/conditionally-const-and-const-params.rs:25:62
2727 |
2828LL | fn bar<A: [const] Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
2929 | ^
tests/ui/traits/const-traits/conditionally-const-assoc-fn-in-trait-impl.rs+2-4
......@@ -3,8 +3,7 @@
33//@ compile-flags: -Znext-solver
44#![feature(const_trait_impl)]
55
6#[const_trait]
7trait Main {
6const trait Main {
87 fn compute<T: [const] Aux>() -> u32;
98}
109
......@@ -14,8 +13,7 @@ impl const Main for () {
1413 }
1514}
1615
17#[const_trait]
18trait Aux {
16const trait Aux {
1917 fn generate() -> u32;
2018}
2119
tests/ui/traits/const-traits/conditionally-const-in-anon-const.rs+1-2
......@@ -1,8 +1,7 @@
11#![feature(const_trait_impl, impl_trait_in_bindings)]
22
33struct S;
4#[const_trait]
5trait Trait<const N: u32> {}
4const trait Trait<const N: u32> {}
65
76impl const Trait<0> for () {}
87
tests/ui/traits/const-traits/conditionally-const-in-anon-const.stderr+4-4
......@@ -1,23 +1,23 @@
11error: `[const]` is not allowed here
2 --> $DIR/conditionally-const-in-anon-const.rs:14:25
2 --> $DIR/conditionally-const-in-anon-const.rs:13:25
33 |
44LL | struct I<U: [const] Trait<0>>(U);
55 | ^^^^^^^
66 |
77note: structs cannot have `[const]` trait bounds
8 --> $DIR/conditionally-const-in-anon-const.rs:14:13
8 --> $DIR/conditionally-const-in-anon-const.rs:13:13
99 |
1010LL | struct I<U: [const] Trait<0>>(U);
1111 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212
1313error: `[const]` is not allowed here
14 --> $DIR/conditionally-const-in-anon-const.rs:17:26
14 --> $DIR/conditionally-const-in-anon-const.rs:16:26
1515 |
1616LL | let x: &impl [const] Trait<0> = &();
1717 | ^^^^^^^
1818 |
1919note: anonymous constants cannot have `[const]` trait bounds
20 --> $DIR/conditionally-const-in-anon-const.rs:11:9
20 --> $DIR/conditionally-const-in-anon-const.rs:10:9
2121 |
2222LL | / {
2323LL | | const fn g<U: [const] Trait<0>>() {}
tests/ui/traits/const-traits/conditionally-const-inherent-assoc-const-fn.rs+1-2
......@@ -2,8 +2,7 @@
22//@ compile-flags: -Znext-solver
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait Foo {
5const trait Foo {
76 fn foo(&self) {}
87}
98
tests/ui/traits/const-traits/conditionally-const-invalid-places.rs+1-2
......@@ -1,7 +1,6 @@
11#![feature(const_trait_impl)]
22
3#[const_trait]
4trait Trait {}
3const trait Trait {}
54
65// Regression test for issue #90052.
76fn non_const_function<T: [const] Trait>() {} //~ ERROR `[const]` is not allowed
tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr+48-48
......@@ -1,77 +1,77 @@
11error: `[const]` is not allowed here
2 --> $DIR/conditionally-const-invalid-places.rs:7:26
2 --> $DIR/conditionally-const-invalid-places.rs:6:26
33 |
44LL | fn non_const_function<T: [const] Trait>() {}
55 | ^^^^^^^
66 |
77note: this function is not `const`, so it cannot have `[const]` trait bounds
8 --> $DIR/conditionally-const-invalid-places.rs:7:4
8 --> $DIR/conditionally-const-invalid-places.rs:6:4
99 |
1010LL | fn non_const_function<T: [const] Trait>() {}
1111 | ^^^^^^^^^^^^^^^^^^
1212
1313error: `[const]` is not allowed here
14 --> $DIR/conditionally-const-invalid-places.rs:9:18
14 --> $DIR/conditionally-const-invalid-places.rs:8:18
1515 |
1616LL | struct Struct<T: [const] Trait> { field: T }
1717 | ^^^^^^^
1818 |
1919note: structs cannot have `[const]` trait bounds
20 --> $DIR/conditionally-const-invalid-places.rs:9:1
20 --> $DIR/conditionally-const-invalid-places.rs:8:1
2121 |
2222LL | struct Struct<T: [const] Trait> { field: T }
2323 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2424
2525error: `[const]` is not allowed here
26 --> $DIR/conditionally-const-invalid-places.rs:10:23
26 --> $DIR/conditionally-const-invalid-places.rs:9:23
2727 |
2828LL | struct TupleStruct<T: [const] Trait>(T);
2929 | ^^^^^^^
3030 |
3131note: structs cannot have `[const]` trait bounds
32 --> $DIR/conditionally-const-invalid-places.rs:10:1
32 --> $DIR/conditionally-const-invalid-places.rs:9:1
3333 |
3434LL | struct TupleStruct<T: [const] Trait>(T);
3535 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3636
3737error: `[const]` is not allowed here
38 --> $DIR/conditionally-const-invalid-places.rs:11:22
38 --> $DIR/conditionally-const-invalid-places.rs:10:22
3939 |
4040LL | struct UnitStruct<T: [const] Trait>;
4141 | ^^^^^^^
4242 |
4343note: structs cannot have `[const]` trait bounds
44 --> $DIR/conditionally-const-invalid-places.rs:11:1
44 --> $DIR/conditionally-const-invalid-places.rs:10:1
4545 |
4646LL | struct UnitStruct<T: [const] Trait>;
4747 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4848
4949error: `[const]` is not allowed here
50 --> $DIR/conditionally-const-invalid-places.rs:14:14
50 --> $DIR/conditionally-const-invalid-places.rs:13:14
5151 |
5252LL | enum Enum<T: [const] Trait> { Variant(T) }
5353 | ^^^^^^^
5454 |
5555note: enums cannot have `[const]` trait bounds
56 --> $DIR/conditionally-const-invalid-places.rs:14:1
56 --> $DIR/conditionally-const-invalid-places.rs:13:1
5757 |
5858LL | enum Enum<T: [const] Trait> { Variant(T) }
5959 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6060
6161error: `[const]` is not allowed here
62 --> $DIR/conditionally-const-invalid-places.rs:16:16
62 --> $DIR/conditionally-const-invalid-places.rs:15:16
6363 |
6464LL | union Union<T: [const] Trait> { field: T }
6565 | ^^^^^^^
6666 |
6767note: unions cannot have `[const]` trait bounds
68 --> $DIR/conditionally-const-invalid-places.rs:16:1
68 --> $DIR/conditionally-const-invalid-places.rs:15:1
6969 |
7070LL | union Union<T: [const] Trait> { field: T }
7171 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7272
7373error: `[const]` is not allowed here
74 --> $DIR/conditionally-const-invalid-places.rs:19:14
74 --> $DIR/conditionally-const-invalid-places.rs:18:14
7575 |
7676LL | type Type<T: [const] Trait> = T;
7777 | ^^^^^^^
......@@ -79,7 +79,7 @@ LL | type Type<T: [const] Trait> = T;
7979 = note: this item cannot have `[const]` trait bounds
8080
8181error: `[const]` is not allowed here
82 --> $DIR/conditionally-const-invalid-places.rs:21:19
82 --> $DIR/conditionally-const-invalid-places.rs:20:19
8383 |
8484LL | const CONSTANT<T: [const] Trait>: () = ();
8585 | ^^^^^^^
......@@ -87,43 +87,43 @@ LL | const CONSTANT<T: [const] Trait>: () = ();
8787 = note: this item cannot have `[const]` trait bounds
8888
8989error: `[const]` is not allowed here
90 --> $DIR/conditionally-const-invalid-places.rs:25:18
90 --> $DIR/conditionally-const-invalid-places.rs:24:18
9191 |
9292LL | type Type<T: [const] Trait>: [const] Trait;
9393 | ^^^^^^^
9494 |
9595note: associated types in non-`const` traits cannot have `[const]` trait bounds
96 --> $DIR/conditionally-const-invalid-places.rs:25:5
96 --> $DIR/conditionally-const-invalid-places.rs:24:5
9797 |
9898LL | type Type<T: [const] Trait>: [const] Trait;
9999 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
100100
101101error: `[const]` is not allowed here
102 --> $DIR/conditionally-const-invalid-places.rs:25:34
102 --> $DIR/conditionally-const-invalid-places.rs:24:34
103103 |
104104LL | type Type<T: [const] Trait>: [const] Trait;
105105 | ^^^^^^^
106106 |
107107note: associated types in non-`const` traits cannot have `[const]` trait bounds
108 --> $DIR/conditionally-const-invalid-places.rs:25:5
108 --> $DIR/conditionally-const-invalid-places.rs:24:5
109109 |
110110LL | type Type<T: [const] Trait>: [const] Trait;
111111 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
112112
113113error: `[const]` is not allowed here
114 --> $DIR/conditionally-const-invalid-places.rs:28:30
114 --> $DIR/conditionally-const-invalid-places.rs:27:30
115115 |
116116LL | fn non_const_function<T: [const] Trait>();
117117 | ^^^^^^^
118118 |
119119note: this function is not `const`, so it cannot have `[const]` trait bounds
120 --> $DIR/conditionally-const-invalid-places.rs:28:8
120 --> $DIR/conditionally-const-invalid-places.rs:27:8
121121 |
122122LL | fn non_const_function<T: [const] Trait>();
123123 | ^^^^^^^^^^^^^^^^^^
124124
125125error: `[const]` is not allowed here
126 --> $DIR/conditionally-const-invalid-places.rs:29:23
126 --> $DIR/conditionally-const-invalid-places.rs:28:23
127127 |
128128LL | const CONSTANT<T: [const] Trait>: ();
129129 | ^^^^^^^
......@@ -131,31 +131,31 @@ LL | const CONSTANT<T: [const] Trait>: ();
131131 = note: this item cannot have `[const]` trait bounds
132132
133133error: `[const]` is not allowed here
134 --> $DIR/conditionally-const-invalid-places.rs:34:18
134 --> $DIR/conditionally-const-invalid-places.rs:33:18
135135 |
136136LL | type Type<T: [const] Trait> = ();
137137 | ^^^^^^^
138138 |
139139note: associated types in non-const impls cannot have `[const]` trait bounds
140 --> $DIR/conditionally-const-invalid-places.rs:34:5
140 --> $DIR/conditionally-const-invalid-places.rs:33:5
141141 |
142142LL | type Type<T: [const] Trait> = ();
143143 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
144144
145145error: `[const]` is not allowed here
146 --> $DIR/conditionally-const-invalid-places.rs:36:30
146 --> $DIR/conditionally-const-invalid-places.rs:35:30
147147 |
148148LL | fn non_const_function<T: [const] Trait>() {}
149149 | ^^^^^^^
150150 |
151151note: this function is not `const`, so it cannot have `[const]` trait bounds
152 --> $DIR/conditionally-const-invalid-places.rs:36:8
152 --> $DIR/conditionally-const-invalid-places.rs:35:8
153153 |
154154LL | fn non_const_function<T: [const] Trait>() {}
155155 | ^^^^^^^^^^^^^^^^^^
156156
157157error: `[const]` is not allowed here
158 --> $DIR/conditionally-const-invalid-places.rs:37:23
158 --> $DIR/conditionally-const-invalid-places.rs:36:23
159159 |
160160LL | const CONSTANT<T: [const] Trait>: () = ();
161161 | ^^^^^^^
......@@ -163,31 +163,31 @@ LL | const CONSTANT<T: [const] Trait>: () = ();
163163 = note: this item cannot have `[const]` trait bounds
164164
165165error: `[const]` is not allowed here
166 --> $DIR/conditionally-const-invalid-places.rs:44:18
166 --> $DIR/conditionally-const-invalid-places.rs:43:18
167167 |
168168LL | type Type<T: [const] Trait> = ();
169169 | ^^^^^^^
170170 |
171171note: inherent associated types cannot have `[const]` trait bounds
172 --> $DIR/conditionally-const-invalid-places.rs:44:5
172 --> $DIR/conditionally-const-invalid-places.rs:43:5
173173 |
174174LL | type Type<T: [const] Trait> = ();
175175 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
176176
177177error: `[const]` is not allowed here
178 --> $DIR/conditionally-const-invalid-places.rs:46:30
178 --> $DIR/conditionally-const-invalid-places.rs:45:30
179179 |
180180LL | fn non_const_function<T: [const] Trait>() {}
181181 | ^^^^^^^
182182 |
183183note: this function is not `const`, so it cannot have `[const]` trait bounds
184 --> $DIR/conditionally-const-invalid-places.rs:46:8
184 --> $DIR/conditionally-const-invalid-places.rs:45:8
185185 |
186186LL | fn non_const_function<T: [const] Trait>() {}
187187 | ^^^^^^^^^^^^^^^^^^
188188
189189error: `[const]` is not allowed here
190 --> $DIR/conditionally-const-invalid-places.rs:47:23
190 --> $DIR/conditionally-const-invalid-places.rs:46:23
191191 |
192192LL | const CONSTANT<T: [const] Trait>: () = ();
193193 | ^^^^^^^
......@@ -195,55 +195,55 @@ LL | const CONSTANT<T: [const] Trait>: () = ();
195195 = note: this item cannot have `[const]` trait bounds
196196
197197error: `[const]` is not allowed here
198 --> $DIR/conditionally-const-invalid-places.rs:52:15
198 --> $DIR/conditionally-const-invalid-places.rs:51:15
199199 |
200200LL | trait Child0: [const] Trait {}
201201 | ^^^^^^^
202202 |
203203note: this trait is not `const`, so it cannot have `[const]` trait bounds
204 --> $DIR/conditionally-const-invalid-places.rs:52:1
204 --> $DIR/conditionally-const-invalid-places.rs:51:1
205205 |
206206LL | trait Child0: [const] Trait {}
207207 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
208208
209209error: `[const]` is not allowed here
210 --> $DIR/conditionally-const-invalid-places.rs:53:26
210 --> $DIR/conditionally-const-invalid-places.rs:52:26
211211 |
212212LL | trait Child1 where Self: [const] Trait {}
213213 | ^^^^^^^
214214 |
215215note: this trait is not `const`, so it cannot have `[const]` trait bounds
216 --> $DIR/conditionally-const-invalid-places.rs:53:1
216 --> $DIR/conditionally-const-invalid-places.rs:52:1
217217 |
218218LL | trait Child1 where Self: [const] Trait {}
219219 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
220220
221221error: `[const]` is not allowed here
222 --> $DIR/conditionally-const-invalid-places.rs:56:9
222 --> $DIR/conditionally-const-invalid-places.rs:55:9
223223 |
224224LL | impl<T: [const] Trait> Trait for T {}
225225 | ^^^^^^^
226226 |
227227note: this impl is not `const`, so it cannot have `[const]` trait bounds
228 --> $DIR/conditionally-const-invalid-places.rs:56:1
228 --> $DIR/conditionally-const-invalid-places.rs:55:1
229229 |
230230LL | impl<T: [const] Trait> Trait for T {}
231231 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
232232
233233error: `[const]` is not allowed here
234 --> $DIR/conditionally-const-invalid-places.rs:59:9
234 --> $DIR/conditionally-const-invalid-places.rs:58:9
235235 |
236236LL | impl<T: [const] Trait> Struct<T> {}
237237 | ^^^^^^^
238238 |
239239note: inherent impls cannot have `[const]` trait bounds
240 --> $DIR/conditionally-const-invalid-places.rs:59:1
240 --> $DIR/conditionally-const-invalid-places.rs:58:1
241241 |
242242LL | impl<T: [const] Trait> Struct<T> {}
243243 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
244244
245245error[E0658]: generic const items are experimental
246 --> $DIR/conditionally-const-invalid-places.rs:21:15
246 --> $DIR/conditionally-const-invalid-places.rs:20:15
247247 |
248248LL | const CONSTANT<T: [const] Trait>: () = ();
249249 | ^^^^^^^^^^^^^^^^^^
......@@ -253,7 +253,7 @@ LL | const CONSTANT<T: [const] Trait>: () = ();
253253 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
254254
255255error[E0658]: generic const items are experimental
256 --> $DIR/conditionally-const-invalid-places.rs:29:19
256 --> $DIR/conditionally-const-invalid-places.rs:28:19
257257 |
258258LL | const CONSTANT<T: [const] Trait>: ();
259259 | ^^^^^^^^^^^^^^^^^^
......@@ -263,7 +263,7 @@ LL | const CONSTANT<T: [const] Trait>: ();
263263 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
264264
265265error[E0658]: generic const items are experimental
266 --> $DIR/conditionally-const-invalid-places.rs:37:19
266 --> $DIR/conditionally-const-invalid-places.rs:36:19
267267 |
268268LL | const CONSTANT<T: [const] Trait>: () = ();
269269 | ^^^^^^^^^^^^^^^^^^
......@@ -273,7 +273,7 @@ LL | const CONSTANT<T: [const] Trait>: () = ();
273273 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
274274
275275error[E0658]: generic const items are experimental
276 --> $DIR/conditionally-const-invalid-places.rs:47:19
276 --> $DIR/conditionally-const-invalid-places.rs:46:19
277277 |
278278LL | const CONSTANT<T: [const] Trait>: () = ();
279279 | ^^^^^^^^^^^^^^^^^^
......@@ -283,7 +283,7 @@ LL | const CONSTANT<T: [const] Trait>: () = ();
283283 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
284284
285285error[E0392]: type parameter `T` is never used
286 --> $DIR/conditionally-const-invalid-places.rs:11:19
286 --> $DIR/conditionally-const-invalid-places.rs:10:19
287287 |
288288LL | struct UnitStruct<T: [const] Trait>;
289289 | ^ unused type parameter
......@@ -291,7 +291,7 @@ LL | struct UnitStruct<T: [const] Trait>;
291291 = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
292292
293293error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
294 --> $DIR/conditionally-const-invalid-places.rs:16:33
294 --> $DIR/conditionally-const-invalid-places.rs:15:33
295295 |
296296LL | union Union<T: [const] Trait> { field: T }
297297 | ^^^^^^^^
......@@ -303,19 +303,19 @@ LL | union Union<T: [const] Trait> { field: std::mem::ManuallyDrop<T> }
303303 | +++++++++++++++++++++++ +
304304
305305error[E0275]: overflow evaluating the requirement `(): Trait`
306 --> $DIR/conditionally-const-invalid-places.rs:34:35
306 --> $DIR/conditionally-const-invalid-places.rs:33:35
307307 |
308308LL | type Type<T: [const] Trait> = ();
309309 | ^^
310310 |
311311note: required by a bound in `NonConstTrait::Type`
312 --> $DIR/conditionally-const-invalid-places.rs:25:34
312 --> $DIR/conditionally-const-invalid-places.rs:24:34
313313 |
314314LL | type Type<T: [const] Trait>: [const] Trait;
315315 | ^^^^^^^^^^^^^ required by this bound in `NonConstTrait::Type`
316316
317317error[E0658]: inherent associated types are unstable
318 --> $DIR/conditionally-const-invalid-places.rs:44:5
318 --> $DIR/conditionally-const-invalid-places.rs:43:5
319319 |
320320LL | type Type<T: [const] Trait> = ();
321321 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/ui/traits/const-traits/conditionally-const-trait-bound-assoc-tys.rs+2-4
......@@ -2,8 +2,7 @@
22//@ compile-flags: -Znext-solver
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait Trait {
5const trait Trait {
76 type Assoc<T: [const] Bound>;
87}
98
......@@ -11,7 +10,6 @@ impl const Trait for () {
1110 type Assoc<T: [const] Bound> = T;
1211}
1312
14#[const_trait]
15trait Bound {}
13const trait Bound {}
1614
1715fn main() {}
tests/ui/traits/const-traits/const-assoc-bound-in-trait-wc.rs+1-2
......@@ -3,8 +3,7 @@
33#![feature(const_clone)]
44#![feature(const_trait_impl)]
55
6#[const_trait]
7trait A where Self::Target: [const] Clone {
6const trait A where Self::Target: [const] Clone {
87 type Target;
98}
109
tests/ui/traits/const-traits/const-bound-in-host.rs+1-1
......@@ -3,7 +3,7 @@
33
44#![feature(const_trait_impl)]
55
6#[const_trait] trait Foo {
6const trait Foo {
77 fn foo();
88}
99
tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs+1-2
......@@ -2,8 +2,7 @@
22
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait MyTrait {
5const trait MyTrait {
76 fn do_something(&self);
87}
98
tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr+4-4
......@@ -1,23 +1,23 @@
11error: `[const]` is not allowed here
2 --> $DIR/const-bound-on-not-const-associated-fn.rs:11:40
2 --> $DIR/const-bound-on-not-const-associated-fn.rs:10:40
33 |
44LL | fn do_something_else() where Self: [const] MyTrait;
55 | ^^^^^^^
66 |
77note: this function is not `const`, so it cannot have `[const]` trait bounds
8 --> $DIR/const-bound-on-not-const-associated-fn.rs:11:8
8 --> $DIR/const-bound-on-not-const-associated-fn.rs:10:8
99 |
1010LL | fn do_something_else() where Self: [const] MyTrait;
1111 | ^^^^^^^^^^^^^^^^^
1212
1313error: `[const]` is not allowed here
14 --> $DIR/const-bound-on-not-const-associated-fn.rs:22:32
14 --> $DIR/const-bound-on-not-const-associated-fn.rs:21:32
1515 |
1616LL | pub fn foo(&self) where T: [const] MyTrait {
1717 | ^^^^^^^
1818 |
1919note: this function is not `const`, so it cannot have `[const]` trait bounds
20 --> $DIR/const-bound-on-not-const-associated-fn.rs:22:12
20 --> $DIR/const-bound-on-not-const-associated-fn.rs:21:12
2121 |
2222LL | pub fn foo(&self) where T: [const] MyTrait {
2323 | ^^^
tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr+6-6
......@@ -6,8 +6,8 @@ LL | const fn perform<T: [const] NonConst>() {}
66 |
77help: mark `NonConst` as `const` to allow it to have `const` implementations
88 |
9LL | #[const_trait] trait NonConst {}
10 | ++++++++++++++
9LL | const trait NonConst {}
10 | +++++
1111
1212error: `[const]` can only be applied to `const` traits
1313 --> $DIR/const-bounds-non-const-trait.rs:6:21
......@@ -18,8 +18,8 @@ LL | const fn perform<T: [const] NonConst>() {}
1818 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
1919help: mark `NonConst` as `const` to allow it to have `const` implementations
2020 |
21LL | #[const_trait] trait NonConst {}
22 | ++++++++++++++
21LL | const trait NonConst {}
22 | +++++
2323
2424error: `const` can only be applied to `const` traits
2525 --> $DIR/const-bounds-non-const-trait.rs:10:15
......@@ -29,8 +29,8 @@ LL | fn operate<T: const NonConst>() {}
2929 |
3030help: mark `NonConst` as `const` to allow it to have `const` implementations
3131 |
32LL | #[const_trait] trait NonConst {}
33 | ++++++++++++++
32LL | const trait NonConst {}
33 | +++++
3434
3535error: aborting due to 3 previous errors
3636
tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs+1-2
......@@ -3,8 +3,7 @@
33#![feature(const_trait_impl)]
44
55struct S;
6#[const_trait]
7trait T {
6const trait T {
87 fn foo();
98}
109
tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr+2-2
......@@ -1,11 +1,11 @@
11error[E0015]: cannot call non-const function `non_const` in constant functions
2 --> $DIR/const-check-fns-in-const-impl.rs:14:16
2 --> $DIR/const-check-fns-in-const-impl.rs:13:16
33 |
44LL | fn foo() { non_const() }
55 | ^^^^^^^^^^^
66 |
77note: function `non_const` is not const
8 --> $DIR/const-check-fns-in-const-impl.rs:11:1
8 --> $DIR/const-check-fns-in-const-impl.rs:10:1
99 |
1010LL | fn non_const() {}
1111 | ^^^^^^^^^^^^^^
tests/ui/traits/const-traits/const-closure-trait-method-fail.rs+1-2
......@@ -2,8 +2,7 @@
22
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait Tr {
5const trait Tr {
76 fn a(self) -> i32;
87}
98
tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `(): const Tr` is not satisfied
2 --> $DIR/const-closure-trait-method-fail.rs:18:23
2 --> $DIR/const-closure-trait-method-fail.rs:17:23
33 |
44LL | const _: () = assert!(need_const_closure(Tr::a) == 42);
55 | ^^^^^^^^^^^^^^^^^^^^^^^^^
tests/ui/traits/const-traits/const-closure-trait-method.rs+1-2
......@@ -3,8 +3,7 @@
33//@[next] compile-flags: -Znext-solver
44#![feature(const_trait_impl)]
55
6#[const_trait]
7trait Tr {
6const trait Tr {
87 fn a(self) -> i32;
98}
109
tests/ui/traits/const-traits/const-cond-for-rpitit.rs+2-4
......@@ -4,13 +4,11 @@
44#![feature(const_trait_impl)]
55#![allow(refining_impl_trait)]
66
7#[const_trait]
8pub trait Foo {
7pub const trait Foo {
98 fn method(self) -> impl [const] Bar;
109}
1110
12#[const_trait]
13pub trait Bar {}
11pub const trait Bar {}
1412
1513struct A<T>(T);
1614impl<T> const Foo for A<T> where A<T>: [const] Bar {
tests/ui/traits/const-traits/const-default-method-bodies.rs+1-2
......@@ -1,8 +1,7 @@
11//@ compile-flags: -Znext-solver
22#![feature(const_trait_impl)]
33
4#[const_trait]
5trait ConstDefaultFn: Sized {
4const trait ConstDefaultFn: Sized {
65 fn b(self);
76
87 fn a(self) {
tests/ui/traits/const-traits/const-default-method-bodies.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `NonConstImpl: [const] ConstDefaultFn` is not satisfied
2 --> $DIR/const-default-method-bodies.rs:25:18
2 --> $DIR/const-default-method-bodies.rs:24:18
33 |
44LL | NonConstImpl.a();
55 | ^
tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr+3-3
......@@ -1,18 +1,18 @@
11error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
2 --> $DIR/const-drop-fail-2.rs:31:23
2 --> $DIR/const-drop-fail-2.rs:30:23
33 |
44LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
55 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66 |
77note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `const Drop`
8 --> $DIR/const-drop-fail-2.rs:25:26
8 --> $DIR/const-drop-fail-2.rs:24:26
99 |
1010LL | impl<T: [const] A> const Drop for ConstDropImplWithBounds<T> {
1111 | --------- ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
1212 | |
1313 | unsatisfied trait bound introduced here
1414note: required by a bound in `check`
15 --> $DIR/const-drop-fail-2.rs:21:19
15 --> $DIR/const-drop-fail-2.rs:20:19
1616 |
1717LL | const fn check<T: [const] Destruct>(_: T) {}
1818 | ^^^^^^^^^^^^^^^^ required by this bound in `check`
tests/ui/traits/const-traits/const-drop-fail-2.rs+1-2
......@@ -13,8 +13,7 @@ impl Drop for NonTrivialDrop {
1313 }
1414}
1515
16#[const_trait]
17trait A { fn a() { } }
16const trait A { fn a() { } }
1817
1918impl A for NonTrivialDrop {}
2019
tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr+3-3
......@@ -1,18 +1,18 @@
11error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied
2 --> $DIR/const-drop-fail-2.rs:31:23
2 --> $DIR/const-drop-fail-2.rs:30:23
33 |
44LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
55 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66 |
77note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `const Drop`
8 --> $DIR/const-drop-fail-2.rs:25:26
8 --> $DIR/const-drop-fail-2.rs:24:26
99 |
1010LL | impl<T: [const] A> const Drop for ConstDropImplWithBounds<T> {
1111 | --------- ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
1212 | |
1313 | unsatisfied trait bound introduced here
1414note: required by a bound in `check`
15 --> $DIR/const-drop-fail-2.rs:21:19
15 --> $DIR/const-drop-fail-2.rs:20:19
1616 |
1717LL | const fn check<T: [const] Destruct>(_: T) {}
1818 | ^^^^^^^^^^^^^^^^ required by this bound in `check`
tests/ui/traits/const-traits/const-drop.rs+1-2
......@@ -49,8 +49,7 @@ mod t {
4949 pub struct HasConstDrop(pub ConstDrop);
5050 pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize);
5151
52 #[const_trait]
53 pub trait SomeTrait {
52 pub const trait SomeTrait {
5453 fn foo();
5554 }
5655 impl const SomeTrait for () {
tests/ui/traits/const-traits/const-impl-recovery.rs+2-4
......@@ -1,12 +1,10 @@
11#![feature(const_trait_impl)]
22
3#[const_trait]
4trait Foo {}
3const trait Foo {}
54
65const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword
76
8#[const_trait]
9trait Bar {}
7const trait Bar {}
108
119const impl<T: Foo> Bar for T {} //~ ERROR: expected identifier, found keyword
1210
tests/ui/traits/const-traits/const-impl-recovery.stderr+2-2
......@@ -1,5 +1,5 @@
11error: expected identifier, found keyword `impl`
2 --> $DIR/const-impl-recovery.rs:6:7
2 --> $DIR/const-impl-recovery.rs:5:7
33 |
44LL | const impl Foo for i32 {}
55 | ^^^^ expected identifier, found keyword
......@@ -11,7 +11,7 @@ LL + impl const Foo for i32 {}
1111 |
1212
1313error: expected identifier, found keyword `impl`
14 --> $DIR/const-impl-recovery.rs:11:7
14 --> $DIR/const-impl-recovery.rs:9:7
1515 |
1616LL | const impl<T: Foo> Bar for T {}
1717 | ^^^^ expected identifier, found keyword
tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr+2-2
......@@ -8,8 +8,8 @@ LL | impl const A for () {}
88 = note: adding a non-const method body in the future would be a breaking change
99help: mark `A` as `const` to allow it to have `const` implementations
1010 |
11LL | #[const_trait] pub trait A {}
12 | ++++++++++++++
11LL | pub const trait A {}
12 | +++++
1313
1414error: aborting due to 1 previous error
1515
tests/ui/traits/const-traits/const-impl-trait.rs+2-4
......@@ -16,8 +16,7 @@ const fn wrap(
1616 x
1717}
1818
19#[const_trait]
20trait Foo {
19const trait Foo {
2120 fn huh() -> impl [const] PartialEq + [const] Destruct + Copy;
2221}
2322
......@@ -36,8 +35,7 @@ const _: () = {
3635 assert!(x == x);
3736};
3837
39#[const_trait]
40trait T {}
38const trait T {}
4139struct S;
4240impl const T for S {}
4341
tests/ui/traits/const-traits/const-in-closure.rs+1-2
......@@ -3,8 +3,7 @@
33
44#![feature(const_trait_impl)]
55
6#[const_trait]
7trait Trait {
6const trait Trait {
87 fn method();
98}
109
tests/ui/traits/const-traits/const-opaque.no.stderr+3-3
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `(): const Foo` is not satisfied
2 --> $DIR/const-opaque.rs:31:22
2 --> $DIR/const-opaque.rs:30:22
33 |
44LL | let opaque = bar(());
55 | --- ^^
......@@ -7,7 +7,7 @@ LL | let opaque = bar(());
77 | required by a bound introduced by this call
88 |
99note: required by a bound in `bar`
10 --> $DIR/const-opaque.rs:26:17
10 --> $DIR/const-opaque.rs:25:17
1111 |
1212LL | const fn bar<T: [const] Foo>(t: T) -> impl [const] Foo {
1313 | ^^^^^^^^^^^ required by this bound in `bar`
......@@ -17,7 +17,7 @@ LL | impl const Foo for () {
1717 | +++++
1818
1919error[E0277]: the trait bound `(): const Foo` is not satisfied
20 --> $DIR/const-opaque.rs:33:12
20 --> $DIR/const-opaque.rs:32:12
2121 |
2222LL | opaque.method();
2323 | ^^^^^^
tests/ui/traits/const-traits/const-opaque.rs+1-2
......@@ -4,8 +4,7 @@
44
55#![feature(const_trait_impl)]
66
7#[const_trait]
8trait Foo {
7const trait Foo {
98 fn method(&self);
109}
1110
tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr+4-4
......@@ -34,8 +34,8 @@ LL | const fn handle(_: &dyn const NonConst) {}
3434 |
3535help: mark `NonConst` as `const` to allow it to have `const` implementations
3636 |
37LL | #[const_trait] trait NonConst {}
38 | ++++++++++++++
37LL | const trait NonConst {}
38 | +++++
3939
4040error: `[const]` can only be applied to `const` traits
4141 --> $DIR/const-trait-bounds-trait-objects.rs:16:23
......@@ -45,8 +45,8 @@ LL | const fn take(_: &dyn [const] NonConst) {}
4545 |
4646help: mark `NonConst` as `const` to allow it to have `const` implementations
4747 |
48LL | #[const_trait] trait NonConst {}
49 | ++++++++++++++
48LL | const trait NonConst {}
49 | +++++
5050
5151error: aborting due to 6 previous errors
5252
tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs+2-4
......@@ -10,8 +10,7 @@
1010#![feature(const_trait_impl, effects)]
1111//~^ ERROR feature has been removed
1212
13#[const_trait]
14trait Main {
13const trait Main {
1514 fn compute<T: [const] Aux>() -> u32;
1615}
1716
......@@ -22,8 +21,7 @@ impl const Main for () {
2221 }
2322}
2423
25#[const_trait]
26trait Aux {}
24const trait Aux {}
2725
2826impl const Aux for () {}
2927
tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr+1-1
......@@ -8,7 +8,7 @@ LL | #![feature(const_trait_impl, effects)]
88 = note: removed, redundant with `#![feature(const_trait_impl)]`
99
1010error[E0049]: associated function `compute` has 0 type parameters but its trait declaration has 1 type parameter
11 --> $DIR/const-trait-impl-parameter-mismatch.rs:19:16
11 --> $DIR/const-trait-impl-parameter-mismatch.rs:18:16
1212 |
1313LL | fn compute<T: [const] Aux>() -> u32;
1414 | - expected 1 type parameter
tests/ui/traits/const-traits/const-via-item-bound.rs+1-2
......@@ -5,8 +5,7 @@
55
66#![feature(const_trait_impl)]
77
8#[const_trait]
9trait Bar {}
8const trait Bar {}
109
1110trait Baz: const Bar {}
1211
tests/ui/traits/const-traits/cross-crate.gatednc.stderr+1-1
......@@ -5,7 +5,7 @@ LL | NonConst.func();
55 | ^^^^
66 |
77note: trait `MyTrait` is implemented but not `const`
8 --> $DIR/auxiliary/cross-crate.rs:12:1
8 --> $DIR/auxiliary/cross-crate.rs:11:1
99 |
1010LL | impl MyTrait for NonConst {
1111 | ^^^^^^^^^^^^^^^^^^^^^^^^^
tests/ui/traits/const-traits/default-method-body-is-const-body-checking.rs+2-4
......@@ -1,13 +1,11 @@
11#![feature(const_trait_impl)]
22
3#[const_trait]
4trait Tr {}
3const trait Tr {}
54impl Tr for () {}
65
76const fn foo<T>() where T: [const] Tr {}
87
9#[const_trait]
10pub trait Foo {
8pub const trait Foo {
119 fn foo() {
1210 foo::<()>();
1311 //~^ ERROR the trait bound `(): [const] Tr` is not satisfied
tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr+2-2
......@@ -1,11 +1,11 @@
11error[E0277]: the trait bound `(): [const] Tr` is not satisfied
2 --> $DIR/default-method-body-is-const-body-checking.rs:12:15
2 --> $DIR/default-method-body-is-const-body-checking.rs:10:15
33 |
44LL | foo::<()>();
55 | ^^
66 |
77note: required by a bound in `foo`
8 --> $DIR/default-method-body-is-const-body-checking.rs:7:28
8 --> $DIR/default-method-body-is-const-body-checking.rs:6:28
99 |
1010LL | const fn foo<T>() where T: [const] Tr {}
1111 | ^^^^^^^^^^ required by this bound in `foo`
tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs+1-2
......@@ -1,8 +1,7 @@
11//@ compile-flags: -Znext-solver
22#![feature(const_trait_impl)]
33
4#[const_trait]
5pub trait Tr {
4pub const trait Tr {
65 fn a(&self) {}
76
87 fn b(&self) {
tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `(): [const] Tr` is not satisfied
2 --> $DIR/default-method-body-is-const-same-trait-ck.rs:9:12
2 --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
33 |
44LL | ().a()
55 | ^
tests/ui/traits/const-traits/default-method-body-is-const-with-staged-api.rs+1-2
......@@ -9,8 +9,7 @@
99#![feature(const_trait_impl)]
1010#![stable(feature = "foo", since = "3.3.3")]
1111
12#[const_trait]
13trait Tr {
12const trait Tr {
1413 fn a() {}
1514}
1615
tests/ui/traits/const-traits/do-not-const-check-override.rs+1-2
......@@ -3,8 +3,7 @@
33#![allow(incomplete_features)]
44#![feature(const_trait_impl, rustc_attrs)]
55
6#[const_trait]
7trait Foo {
6const trait Foo {
87 #[rustc_do_not_const_check]
98 fn into_iter(&self) { println!("FEAR ME!") }
109}
tests/ui/traits/const-traits/do-not-const-check.rs+2-4
......@@ -1,13 +1,11 @@
11//@ check-pass
22#![feature(const_trait_impl, rustc_attrs)]
33
4#[const_trait]
5trait IntoIter {
4const trait IntoIter {
65 fn into_iter(self);
76}
87
9#[const_trait]
10trait Hmm: Sized {
8const trait Hmm: Sized {
119 #[rustc_do_not_const_check]
1210 fn chain<U>(self, other: U) where U: IntoIter,
1311 {
tests/ui/traits/const-traits/dont-ice-on-const-pred-for-bounds.rs+1-2
......@@ -8,8 +8,7 @@
88
99#![feature(const_trait_impl)]
1010
11#[const_trait]
12trait Trait {
11const trait Trait {
1312 type Assoc: const Trait;
1413}
1514
tests/ui/traits/const-traits/dont-observe-host.rs+1-2
......@@ -3,8 +3,7 @@
33
44#![feature(const_trait_impl)]
55
6#[const_trait]
7trait Trait {
6const trait Trait {
87 fn method() {}
98}
109
tests/ui/traits/const-traits/dont-prefer-param-env-for-infer-self-ty.rs+1-2
......@@ -2,8 +2,7 @@
22
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait Foo {}
5const trait Foo {}
76
87impl<T> const Foo for (T,) where T: [const] Foo {}
98
tests/ui/traits/const-traits/double-error-for-unimplemented-trait.rs+1-2
......@@ -2,8 +2,7 @@
22
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait Trait {
5const trait Trait {
76 type Out;
87}
98
tests/ui/traits/const-traits/double-error-for-unimplemented-trait.stderr+10-10
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `(): Trait` is not satisfied
2 --> $DIR/double-error-for-unimplemented-trait.rs:13:15
2 --> $DIR/double-error-for-unimplemented-trait.rs:12:15
33 |
44LL | needs_const(&());
55 | ----------- ^^^ the trait `Trait` is not implemented for `()`
......@@ -7,18 +7,18 @@ LL | needs_const(&());
77 | required by a bound introduced by this call
88 |
99help: this trait has no implementations, consider adding one
10 --> $DIR/double-error-for-unimplemented-trait.rs:6:1
10 --> $DIR/double-error-for-unimplemented-trait.rs:5:1
1111 |
12LL | trait Trait {
13 | ^^^^^^^^^^^
12LL | const trait Trait {
13 | ^^^^^^^^^^^^^^^^^
1414note: required by a bound in `needs_const`
15 --> $DIR/double-error-for-unimplemented-trait.rs:10:25
15 --> $DIR/double-error-for-unimplemented-trait.rs:9:25
1616 |
1717LL | const fn needs_const<T: [const] Trait>(_: &T) {}
1818 | ^^^^^^^^^^^^^ required by this bound in `needs_const`
1919
2020error[E0277]: the trait bound `(): Trait` is not satisfied
21 --> $DIR/double-error-for-unimplemented-trait.rs:18:15
21 --> $DIR/double-error-for-unimplemented-trait.rs:17:15
2222 |
2323LL | needs_const(&());
2424 | ----------- ^^^ the trait `Trait` is not implemented for `()`
......@@ -26,12 +26,12 @@ LL | needs_const(&());
2626 | required by a bound introduced by this call
2727 |
2828help: this trait has no implementations, consider adding one
29 --> $DIR/double-error-for-unimplemented-trait.rs:6:1
29 --> $DIR/double-error-for-unimplemented-trait.rs:5:1
3030 |
31LL | trait Trait {
32 | ^^^^^^^^^^^
31LL | const trait Trait {
32 | ^^^^^^^^^^^^^^^^^
3333note: required by a bound in `needs_const`
34 --> $DIR/double-error-for-unimplemented-trait.rs:10:25
34 --> $DIR/double-error-for-unimplemented-trait.rs:9:25
3535 |
3636LL | const fn needs_const<T: [const] Trait>(_: &T) {}
3737 | ^^^^^^^^^^^^^ required by this bound in `needs_const`
tests/ui/traits/const-traits/effect-param-infer.rs+1-2
......@@ -5,8 +5,7 @@
55//@ compile-flags: -Znext-solver
66#![feature(const_trait_impl)]
77
8#[const_trait]
9pub trait Foo<Rhs: ?Sized = Self> {
8pub const trait Foo<Rhs: ?Sized = Self> {
109 /* stuff */
1110}
1211
tests/ui/traits/const-traits/eval-bad-signature.rs+1-2
......@@ -2,8 +2,7 @@
22
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait Value {
5const trait Value {
76 fn value() -> u32;
87}
98
tests/ui/traits/const-traits/eval-bad-signature.stderr+2-2
......@@ -1,11 +1,11 @@
11error[E0053]: method `value` has an incompatible type for trait
2 --> $DIR/eval-bad-signature.rs:17:19
2 --> $DIR/eval-bad-signature.rs:16:19
33 |
44LL | fn value() -> i64 {
55 | ^^^ expected `u32`, found `i64`
66 |
77note: type in trait
8 --> $DIR/eval-bad-signature.rs:7:19
8 --> $DIR/eval-bad-signature.rs:6:19
99 |
1010LL | fn value() -> u32;
1111 | ^^^
tests/ui/traits/const-traits/feature-gate.rs+1-3
......@@ -5,15 +5,13 @@
55#![cfg_attr(gated, feature(const_trait_impl))]
66
77struct S;
8#[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder
9trait T {}
8const trait T {} //[stock]~ ERROR const trait impls are experimental
109impl const T for S {}
1110//[stock]~^ ERROR const trait impls are experimental
1211
1312const fn f<A: [const] T>() {} //[stock]~ ERROR const trait impls are experimental
1413fn g<A: const T>() {} //[stock]~ ERROR const trait impls are experimental
1514
16const trait Trait {} //[stock]~ ERROR const trait impls are experimental
1715#[cfg(false)] const trait Trait {} //[stock]~ ERROR const trait impls are experimental
1816
1917macro_rules! discard { ($ty:ty) => {} }
tests/ui/traits/const-traits/feature-gate.stock.stderr+16-26
......@@ -1,45 +1,45 @@
11error[E0658]: const trait impls are experimental
2 --> $DIR/feature-gate.rs:10:6
2 --> $DIR/feature-gate.rs:8:1
33 |
4LL | impl const T for S {}
5 | ^^^^^
4LL | const trait T {}
5 | ^^^^^
66 |
77 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
88 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
99 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1010
1111error[E0658]: const trait impls are experimental
12 --> $DIR/feature-gate.rs:13:15
12 --> $DIR/feature-gate.rs:9:6
1313 |
14LL | const fn f<A: [const] T>() {}
15 | ^^^^^^^
14LL | impl const T for S {}
15 | ^^^^^
1616 |
1717 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
1818 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
1919 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2020
2121error[E0658]: const trait impls are experimental
22 --> $DIR/feature-gate.rs:14:9
22 --> $DIR/feature-gate.rs:12:15
2323 |
24LL | fn g<A: const T>() {}
25 | ^^^^^
24LL | const fn f<A: [const] T>() {}
25 | ^^^^^^^
2626 |
2727 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
2828 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
2929 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
3030
3131error[E0658]: const trait impls are experimental
32 --> $DIR/feature-gate.rs:16:1
32 --> $DIR/feature-gate.rs:13:9
3333 |
34LL | const trait Trait {}
35 | ^^^^^
34LL | fn g<A: const T>() {}
35 | ^^^^^
3636 |
3737 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
3838 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
3939 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
4040
4141error[E0658]: const trait impls are experimental
42 --> $DIR/feature-gate.rs:17:15
42 --> $DIR/feature-gate.rs:15:15
4343 |
4444LL | #[cfg(false)] const trait Trait {}
4545 | ^^^^^
......@@ -49,7 +49,7 @@ LL | #[cfg(false)] const trait Trait {}
4949 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
5050
5151error[E0658]: const trait impls are experimental
52 --> $DIR/feature-gate.rs:21:17
52 --> $DIR/feature-gate.rs:19:17
5353 |
5454LL | discard! { impl [const] T }
5555 | ^^^^^^^
......@@ -59,7 +59,7 @@ LL | discard! { impl [const] T }
5959 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
6060
6161error[E0658]: const trait impls are experimental
62 --> $DIR/feature-gate.rs:22:17
62 --> $DIR/feature-gate.rs:20:17
6363 |
6464LL | discard! { impl const T }
6565 | ^^^^^
......@@ -68,16 +68,6 @@ LL | discard! { impl const T }
6868 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
6969 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
7070
71error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future.
72 --> $DIR/feature-gate.rs:8:1
73 |
74LL | #[const_trait]
75 | ^^^^^^^^^^^^^^
76 |
77 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
78 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
79 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
80
81error: aborting due to 8 previous errors
71error: aborting due to 7 previous errors
8272
8373For more information about this error, try `rustc --explain E0658`.
tests/ui/traits/const-traits/function-pointer-does-not-require-const.rs+1-2
......@@ -1,8 +1,7 @@
11//@ check-pass
22#![feature(const_trait_impl)]
33
4#[const_trait]
5pub trait Test {}
4pub const trait Test {}
65
76impl Test for () {}
87
tests/ui/traits/const-traits/hir-const-check.rs+1-2
......@@ -6,8 +6,7 @@
66#![feature(const_trait_impl)]
77#![feature(const_try)]
88
9#[const_trait]
10pub trait MyTrait {
9pub const trait MyTrait {
1110 fn method(&self) -> Option<()>;
1211}
1312
tests/ui/traits/const-traits/ice-121536-const-method.rs+1-2
......@@ -2,8 +2,7 @@
22
33pub struct Vec3;
44
5#[const_trait]
6pub trait Add {
5pub const trait Add {
76 fn add(self) -> Vec3;
87}
98
tests/ui/traits/const-traits/ice-121536-const-method.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0379]: functions in trait impls cannot be declared const
2 --> $DIR/ice-121536-const-method.rs:11:5
2 --> $DIR/ice-121536-const-method.rs:10:5
33 |
44LL | const fn add(self) -> Vec3 {
55 | ^^^^^ functions in trait impls cannot be const
tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs+1-2
......@@ -2,8 +2,7 @@
22
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait Foo {}
5const trait Foo {}
76
87impl const Foo for i32 {}
98
tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0119]: conflicting implementations of trait `Foo` for type `i32`
2 --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:10:1
2 --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:9:1
33 |
44LL | impl const Foo for i32 {}
55 | ---------------------- first implementation here
tests/ui/traits/const-traits/impl-with-default-fn-fail.rs+1-2
......@@ -1,7 +1,6 @@
11#![feature(const_trait_impl)]
22
3#[const_trait]
4trait Tr {
3const trait Tr {
54 fn req(&self);
65
76 fn default() {}
tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0046]: not all trait items implemented, missing: `req`
2 --> $DIR/impl-with-default-fn-fail.rs:12:1
2 --> $DIR/impl-with-default-fn-fail.rs:11:1
33 |
44LL | fn req(&self);
55 | -------------- `req` from trait
tests/ui/traits/const-traits/impl-with-default-fn-pass.rs+1-2
......@@ -2,8 +2,7 @@
22//@ compile-flags: -Znext-solver
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait Tr {
5const trait Tr {
76 fn req(&self);
87
98 fn default() {}
tests/ui/traits/const-traits/imply-always-const.rs+2-4
......@@ -2,13 +2,11 @@
22
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait A where Self::Assoc: const B {
5const trait A where Self::Assoc: const B {
76 type Assoc;
87}
98
10#[const_trait]
11trait B {}
9const trait B {}
1210
1311fn needs_b<T: const B>() {}
1412
tests/ui/traits/const-traits/inherent-impl-const-bounds.rs+2-4
......@@ -3,10 +3,8 @@
33
44struct S;
55
6#[const_trait]
7trait A {}
8#[const_trait]
9trait B {}
6const trait A {}
7const trait B {}
108
119impl const A for S {}
1210impl const B for S {}
tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr+2-3
......@@ -23,9 +23,8 @@ LL | fn foo(self);
2323 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
2424help: consider making trait `Trait` const
2525 |
26LL + #[const_trait]
27LL | trait Trait {
28 |
26LL | const trait Trait {
27 | +++++
2928
3029error: aborting due to 2 previous errors
3130
tests/ui/traits/const-traits/issue-100222.rs+12-4
......@@ -5,12 +5,20 @@
55#![allow(incomplete_features)]
66#![feature(const_trait_impl, associated_type_defaults)]
77
8#[cfg_attr(any(yn, yy), const_trait)]
9pub trait Index {
10 type Output;
8#[cfg(any(yn, yy))] pub const trait Index { type Output; }
9#[cfg(not(any(yn, yy)))] pub trait Index { type Output; }
10
11#[cfg(any(ny, yy))]
12pub const trait IndexMut
13where
14 Self: Index,
15{
16 const C: <Self as Index>::Output;
17 type Assoc = <Self as Index>::Output;
18 fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output;
1119}
1220
13#[cfg_attr(any(ny, yy), const_trait)]
21#[cfg(not(any(ny, yy)))]
1422pub trait IndexMut
1523where
1624 Self: Index,
tests/ui/traits/const-traits/issue-79450.rs+1-2
......@@ -1,8 +1,7 @@
11//@ compile-flags: -Znext-solver
22#![feature(const_trait_impl)]
33
4#[const_trait]
5trait Tr {
4const trait Tr {
65 fn req(&self);
76
87 fn prov(&self) {
tests/ui/traits/const-traits/issue-79450.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0015]: cannot call non-const function `_print` in constant functions
2 --> $DIR/issue-79450.rs:9:9
2 --> $DIR/issue-79450.rs:8:9
33 |
44LL | println!("lul");
55 | ^^^^^^^^^^^^^^^
tests/ui/traits/const-traits/issue-88155.stderr+2-3
......@@ -14,9 +14,8 @@ LL | fn assoc() -> bool;
1414 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
1515help: consider making trait `A` const
1616 |
17LL + #[const_trait]
18LL | pub trait A {
19 |
17LL | pub const trait A {
18 | +++++
2019
2120error: aborting due to 1 previous error
2221
tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs+2-4
......@@ -5,10 +5,8 @@
55
66#![feature(const_trait_impl)]
77
8#[const_trait]
9pub trait Super {}
10#[const_trait]
11pub trait Sub: Super {}
8pub const trait Super {}
9pub const trait Sub: Super {}
1210
1311impl<A> const Super for &A where A: [const] Super {}
1412impl<A> const Sub for &A where A: [const] Sub {}
tests/ui/traits/const-traits/item-bound-entailment-fails.rs+2-2
......@@ -1,13 +1,13 @@
11//@ compile-flags: -Znext-solver
22#![feature(const_trait_impl)]
33
4#[const_trait] trait Foo {
4const trait Foo {
55 type Assoc<T>: [const] Bar
66 where
77 T: [const] Bar;
88}
99
10#[const_trait] trait Bar {}
10const trait Bar {}
1111struct N<T>(T);
1212impl<T> Bar for N<T> where T: Bar {}
1313struct C<T>(T);
tests/ui/traits/const-traits/item-bound-entailment.rs+2-2
......@@ -3,13 +3,13 @@
33
44#![feature(const_trait_impl)]
55
6#[const_trait] trait Foo {
6const trait Foo {
77 type Assoc<T>: [const] Bar
88 where
99 T: [const] Bar;
1010}
1111
12#[const_trait] trait Bar {}
12const trait Bar {}
1313struct N<T>(T);
1414impl<T> Bar for N<T> where T: Bar {}
1515struct C<T>(T);
tests/ui/traits/const-traits/minicore-drop-fail.rs+1-1
......@@ -15,7 +15,7 @@ impl Drop for NotDropImpl {
1515 fn drop(&mut self) {}
1616}
1717
18#[const_trait] trait Foo {}
18const trait Foo {}
1919impl Foo for () {}
2020
2121struct Conditional<T: Foo>(T);
tests/ui/traits/const-traits/minicore-fn-fail.rs+1-2
......@@ -10,8 +10,7 @@ use minicore::*;
1010
1111const fn call_indirect<T: [const] Fn()>(t: &T) { t() }
1212
13#[const_trait]
14trait Foo {}
13const trait Foo {}
1514impl Foo for () {}
1615const fn foo<T: [const] Foo>() {}
1716
tests/ui/traits/const-traits/minicore-fn-fail.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `(): [const] Foo` is not satisfied
2 --> $DIR/minicore-fn-fail.rs:19:19
2 --> $DIR/minicore-fn-fail.rs:18:19
33 |
44LL | call_indirect(&foo::<()>);
55 | ------------- ^^^^^^^^^^
tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs+1-2
......@@ -17,7 +17,6 @@ fn const_negative<T: const !Trait>() {}
1717//~^ ERROR `const` trait not allowed with `!` trait polarity modifier
1818//~| ERROR negative bounds are not supported
1919
20#[const_trait]
21trait Trait {}
20const trait Trait {}
2221
2322fn main() {}
tests/ui/traits/const-traits/no-explicit-const-params.rs+1-2
......@@ -2,8 +2,7 @@
22
33const fn foo() {}
44
5#[const_trait]
6trait Bar {
5const trait Bar {
76 fn bar();
87}
98
tests/ui/traits/const-traits/no-explicit-const-params.stderr+11-11
......@@ -1,5 +1,5 @@
11error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
2 --> $DIR/no-explicit-const-params.rs:15:5
2 --> $DIR/no-explicit-const-params.rs:14:5
33 |
44LL | foo::<true>();
55 | ^^^-------- help: remove the unnecessary generics
......@@ -13,7 +13,7 @@ LL | const fn foo() {}
1313 | ^^^
1414
1515error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
16 --> $DIR/no-explicit-const-params.rs:17:12
16 --> $DIR/no-explicit-const-params.rs:16:12
1717 |
1818LL | <() as Bar<true>>::bar();
1919 | ^^^------ help: remove the unnecessary generics
......@@ -21,13 +21,13 @@ LL | <() as Bar<true>>::bar();
2121 | expected 0 generic arguments
2222 |
2323note: trait defined here, with 0 generic parameters
24 --> $DIR/no-explicit-const-params.rs:6:7
24 --> $DIR/no-explicit-const-params.rs:5:13
2525 |
26LL | trait Bar {
27 | ^^^
26LL | const trait Bar {
27 | ^^^
2828
2929error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
30 --> $DIR/no-explicit-const-params.rs:22:5
30 --> $DIR/no-explicit-const-params.rs:21:5
3131 |
3232LL | foo::<false>();
3333 | ^^^--------- help: remove the unnecessary generics
......@@ -41,7 +41,7 @@ LL | const fn foo() {}
4141 | ^^^
4242
4343error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
44 --> $DIR/no-explicit-const-params.rs:24:12
44 --> $DIR/no-explicit-const-params.rs:23:12
4545 |
4646LL | <() as Bar<false>>::bar();
4747 | ^^^------- help: remove the unnecessary generics
......@@ -49,13 +49,13 @@ LL | <() as Bar<false>>::bar();
4949 | expected 0 generic arguments
5050 |
5151note: trait defined here, with 0 generic parameters
52 --> $DIR/no-explicit-const-params.rs:6:7
52 --> $DIR/no-explicit-const-params.rs:5:13
5353 |
54LL | trait Bar {
55 | ^^^
54LL | const trait Bar {
55 | ^^^
5656
5757error[E0277]: the trait bound `(): const Bar` is not satisfied
58 --> $DIR/no-explicit-const-params.rs:24:6
58 --> $DIR/no-explicit-const-params.rs:23:6
5959 |
6060LL | <() as Bar<false>>::bar();
6161 | ^^
tests/ui/traits/const-traits/non-const-op-in-closure-in-const.rs+1-2
......@@ -2,8 +2,7 @@
22
33//@ check-pass
44
5#[const_trait]
6trait Convert<T> {
5const trait Convert<T> {
76 fn to(self) -> T;
87}
98
tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0119]: conflicting implementations of trait `Foo` for type `(_,)`
2 --> $DIR/overlap-const-with-nonconst.rs:23:1
2 --> $DIR/overlap-const-with-nonconst.rs:21:1
33 |
44LL | / impl<T> const Foo for T
55LL | | where
tests/ui/traits/const-traits/overlap-const-with-nonconst.rs+2-4
......@@ -5,12 +5,10 @@
55//[spec]~^ WARN the feature `specialization` is incomplete
66#![cfg_attr(min_spec, feature(min_specialization))]
77
8#[const_trait]
9trait Bar {}
8const trait Bar {}
109impl<T> const Bar for T {}
1110
12#[const_trait]
13trait Foo {
11const trait Foo {
1412 fn method(&self);
1513}
1614impl<T> const Foo for T
tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr+1-1
......@@ -9,7 +9,7 @@ LL | #![cfg_attr(spec, feature(specialization))]
99 = note: `#[warn(incomplete_features)]` on by default
1010
1111error[E0119]: conflicting implementations of trait `Foo` for type `(_,)`
12 --> $DIR/overlap-const-with-nonconst.rs:23:1
12 --> $DIR/overlap-const-with-nonconst.rs:21:1
1313 |
1414LL | / impl<T> const Foo for T
1515LL | | where
tests/ui/traits/const-traits/predicate-entailment-fails.rs+3-3
......@@ -1,11 +1,11 @@
11//@ compile-flags: -Znext-solver
22#![feature(const_trait_impl)]
33
4#[const_trait] trait Bar {}
4const trait Bar {}
55impl const Bar for () {}
66
77
8#[const_trait] trait TildeConst {
8const trait TildeConst {
99 type Bar<T> where T: [const] Bar;
1010
1111 fn foo<T>() where T: [const] Bar;
......@@ -19,7 +19,7 @@ impl TildeConst for () {
1919}
2020
2121
22#[const_trait] trait NeverConst {
22const trait NeverConst {
2323 type Bar<T> where T: Bar;
2424
2525 fn foo<T>() where T: Bar;
tests/ui/traits/const-traits/predicate-entailment-passes.rs+3-3
......@@ -3,10 +3,10 @@
33
44#![feature(const_trait_impl)]
55
6#[const_trait] trait Bar {}
6const trait Bar {}
77impl const Bar for () {}
88
9#[const_trait] trait TildeConst {
9const trait TildeConst {
1010 fn foo<T>() where T: [const] Bar;
1111}
1212impl TildeConst for () {
......@@ -14,7 +14,7 @@ impl TildeConst for () {
1414}
1515
1616
17#[const_trait] trait AlwaysConst {
17const trait AlwaysConst {
1818 fn foo<T>() where T: const Bar;
1919}
2020impl AlwaysConst for i32 {
tests/ui/traits/const-traits/project.rs+2-4
......@@ -2,11 +2,9 @@
22//@ compile-flags: -Znext-solver
33#![feature(const_trait_impl)]
44
5#[const_trait]
6pub trait Owo<X = <Self as Uwu>::T> {}
5pub const trait Owo<X = <Self as Uwu>::T> {}
76
8#[const_trait]
9pub trait Uwu: Owo {
7pub const trait Uwu: Owo {
108 type T;
119}
1210
tests/ui/traits/const-traits/spec-effectvar-ice.stderr+6-6
......@@ -8,8 +8,8 @@ LL | impl<T> const Foo for T {}
88 = note: adding a non-const method body in the future would be a breaking change
99help: mark `Foo` as `const` to allow it to have `const` implementations
1010 |
11LL | #[const_trait] trait Foo {}
12 | ++++++++++++++
11LL | const trait Foo {}
12 | +++++
1313
1414error: const `impl` for trait `Foo` which is not `const`
1515 --> $DIR/spec-effectvar-ice.rs:13:15
......@@ -21,8 +21,8 @@ LL | impl<T> const Foo for T where T: const Specialize {}
2121 = note: adding a non-const method body in the future would be a breaking change
2222help: mark `Foo` as `const` to allow it to have `const` implementations
2323 |
24LL | #[const_trait] trait Foo {}
25 | ++++++++++++++
24LL | const trait Foo {}
25 | +++++
2626
2727error: `const` can only be applied to `const` traits
2828 --> $DIR/spec-effectvar-ice.rs:13:34
......@@ -32,8 +32,8 @@ LL | impl<T> const Foo for T where T: const Specialize {}
3232 |
3333help: mark `Specialize` as `const` to allow it to have `const` implementations
3434 |
35LL | #[const_trait] trait Specialize {}
36 | ++++++++++++++
35LL | const trait Specialize {}
36 | +++++
3737
3838error: specialization impl does not specialize any associated items
3939 --> $DIR/spec-effectvar-ice.rs:13:1
tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs+3-6
......@@ -10,11 +10,9 @@
1010#[rustc_specialization_trait]
1111trait Specialize {}
1212
13#[const_trait]
14trait Foo {}
13const trait Foo {}
1514
16#[const_trait]
17trait Bar {
15const trait Bar {
1816 fn bar();
1917}
2018
......@@ -33,8 +31,7 @@ where
3331 fn bar() {}
3432}
3533
36#[const_trait]
37trait Baz {
34const trait Baz {
3835 fn baz();
3936}
4037
tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr+2-2
......@@ -1,5 +1,5 @@
11error[E0119]: conflicting implementations of trait `Bar`
2 --> $DIR/const-default-bound-non-const-specialized-bound.rs:28:1
2 --> $DIR/const-default-bound-non-const-specialized-bound.rs:26:1
33 |
44LL | / impl<T> const Bar for T
55LL | | where
......@@ -13,7 +13,7 @@ LL | | T: Specialize,
1313 | |__________________^ conflicting implementation
1414
1515error[E0119]: conflicting implementations of trait `Baz`
16 --> $DIR/const-default-bound-non-const-specialized-bound.rs:48:1
16 --> $DIR/const-default-bound-non-const-specialized-bound.rs:45:1
1717 |
1818LL | / impl<T> const Baz for T
1919LL | | where
tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs+1-2
......@@ -6,8 +6,7 @@
66#![feature(const_trait_impl)]
77#![feature(min_specialization)]
88
9#[const_trait]
10trait Value {
9const trait Value {
1110 fn value() -> u32;
1211}
1312
tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo`
2 --> $DIR/const-default-impl-non-const-specialized-impl.rs:22:1
2 --> $DIR/const-default-impl-non-const-specialized-impl.rs:21:1
33 |
44LL | impl<T> const Value for T {
55 | ------------------------- first implementation here
tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs+1-2
......@@ -6,8 +6,7 @@
66//[spec]~^ WARN the feature `specialization` is incomplete
77#![cfg_attr(min_spec, feature(min_specialization))]
88
9#[const_trait]
10trait Value {
9const trait Value {
1110 fn value() -> u32;
1211}
1312
tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr+1-1
......@@ -9,7 +9,7 @@ LL | #![cfg_attr(spec, feature(specialization))]
99 = note: `#[warn(incomplete_features)]` on by default
1010
1111error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo`
12 --> $DIR/const-default-impl-non-const-specialized-impl.rs:22:1
12 --> $DIR/const-default-impl-non-const-specialized-impl.rs:21:1
1313 |
1414LL | impl<T> const Value for T {
1515 | ------------------------- first implementation here
tests/ui/traits/const-traits/specialization/default-keyword.rs+1-2
......@@ -3,8 +3,7 @@
33#![feature(const_trait_impl)]
44#![feature(min_specialization)]
55
6#[const_trait]
7trait Foo {
6const trait Foo {
87 fn foo();
98}
109
tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs+3-6
......@@ -11,11 +11,9 @@
1111#[rustc_specialization_trait]
1212trait Specialize {}
1313
14#[const_trait]
15trait Foo {}
14const trait Foo {}
1615
17#[const_trait]
18trait Bar {
16const trait Bar {
1917 fn bar();
2018}
2119
......@@ -34,8 +32,7 @@ where
3432 fn bar() {}
3533}
3634
37#[const_trait]
38trait Baz {
35const trait Baz {
3936 fn baz();
4037}
4138
tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs+1-2
......@@ -6,8 +6,7 @@
66#![feature(const_trait_impl)]
77#![feature(min_specialization)]
88
9#[const_trait]
10trait Value {
9const trait Value {
1110 fn value() -> u32;
1211}
1312
tests/ui/traits/const-traits/specialization/specialize-on-conditionally-const.rs+3-6
......@@ -7,12 +7,10 @@
77#![feature(rustc_attrs)]
88#![feature(min_specialization)]
99
10#[const_trait]
1110#[rustc_specialization_trait]
12trait Specialize {}
11const trait Specialize {}
1312
14#[const_trait]
15trait Foo {
13const trait Foo {
1614 fn foo();
1715}
1816
......@@ -27,8 +25,7 @@ where
2725 fn foo() {}
2826}
2927
30#[const_trait]
31trait Bar {
28const trait Bar {
3229 fn bar() {}
3330}
3431
tests/ui/traits/const-traits/specializing-constness-2.rs+2-4
......@@ -1,13 +1,11 @@
11#![feature(const_trait_impl, min_specialization, rustc_attrs)]
22//@ known-bug: #110395
33#[rustc_specialization_trait]
4#[const_trait]
5pub trait Sup {}
4pub const trait Sup {}
65
76impl const Sup for () {}
87
9#[const_trait]
10pub trait A {
8pub const trait A {
119 fn a() -> u32;
1210}
1311
tests/ui/traits/const-traits/specializing-constness-2.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `T: [const] A` is not satisfied
2 --> $DIR/specializing-constness-2.rs:27:6
2 --> $DIR/specializing-constness-2.rs:25:6
33 |
44LL | <T as A>::a();
55 | ^
tests/ui/traits/const-traits/specializing-constness.rs+3-6
......@@ -1,18 +1,15 @@
11#![feature(const_trait_impl, min_specialization, rustc_attrs)]
22
33#[rustc_specialization_trait]
4#[const_trait]
5pub trait Sup {}
4pub const trait Sup {}
65
76impl const Sup for () {}
87
9#[const_trait]
10pub trait A {
8pub const trait A {
119 fn a() -> u32;
1210}
1311
14#[const_trait]
15pub trait Spec {}
12pub const trait Spec {}
1613
1714impl<T: [const] Spec> const A for T {
1815 default fn a() -> u32 {
tests/ui/traits/const-traits/specializing-constness.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0119]: conflicting implementations of trait `A`
2 --> $DIR/specializing-constness.rs:23:1
2 --> $DIR/specializing-constness.rs:20:1
33 |
44LL | impl<T: [const] Spec> const A for T {
55 | ----------------------------------- first implementation here
tests/ui/traits/const-traits/staged-api.rs+2-4
......@@ -86,13 +86,11 @@ const fn implicitly_stable_const_context() {
8686}
8787
8888// check that const stability of impls and traits must match
89#[const_trait]
9089#[rustc_const_unstable(feature = "beef", issue = "none")]
91trait U {}
90const trait U {}
9291
93#[const_trait]
9492#[rustc_const_stable(since = "0.0.0", feature = "beef2")]
95trait S {}
93const trait S {}
9694
9795// implied stable
9896impl const U for u8 {}
tests/ui/traits/const-traits/staged-api.stderr+17-17
......@@ -1,22 +1,22 @@
11error: const stability on the impl does not match the const stability on the trait
2 --> $DIR/staged-api.rs:98:1
2 --> $DIR/staged-api.rs:96:1
33 |
44LL | impl const U for u8 {}
55 | ^^^^^^^^^^^^^^^^^^^^^^
66 |
77note: this impl is (implicitly) stable...
8 --> $DIR/staged-api.rs:98:1
8 --> $DIR/staged-api.rs:96:1
99 |
1010LL | impl const U for u8 {}
1111 | ^^^^^^^^^^^^^^^^^^^^^^
1212note: ...but the trait is unstable
13 --> $DIR/staged-api.rs:91:7
13 --> $DIR/staged-api.rs:90:13
1414 |
15LL | trait U {}
16 | ^
15LL | const trait U {}
16 | ^
1717
1818error: trait implementations cannot be const stable yet
19 --> $DIR/staged-api.rs:102:1
19 --> $DIR/staged-api.rs:100:1
2020 |
2121LL | impl const U for u16 {}
2222 | ^^^^^^^^^^^^^^^^^^^^^^^
......@@ -24,24 +24,24 @@ LL | impl const U for u16 {}
2424 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
2525
2626error: const stability on the impl does not match the const stability on the trait
27 --> $DIR/staged-api.rs:102:1
27 --> $DIR/staged-api.rs:100:1
2828 |
2929LL | impl const U for u16 {}
3030 | ^^^^^^^^^^^^^^^^^^^^^^^
3131 |
3232note: this impl is (implicitly) stable...
33 --> $DIR/staged-api.rs:102:1
33 --> $DIR/staged-api.rs:100:1
3434 |
3535LL | impl const U for u16 {}
3636 | ^^^^^^^^^^^^^^^^^^^^^^^
3737note: ...but the trait is unstable
38 --> $DIR/staged-api.rs:91:7
38 --> $DIR/staged-api.rs:90:13
3939 |
40LL | trait U {}
41 | ^
40LL | const trait U {}
41 | ^
4242
4343error: trait implementations cannot be const stable yet
44 --> $DIR/staged-api.rs:113:1
44 --> $DIR/staged-api.rs:111:1
4545 |
4646LL | impl const S for u16 {}
4747 | ^^^^^^^^^^^^^^^^^^^^^^^
......@@ -49,21 +49,21 @@ LL | impl const S for u16 {}
4949 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
5050
5151error: const stability on the impl does not match the const stability on the trait
52 --> $DIR/staged-api.rs:117:1
52 --> $DIR/staged-api.rs:115:1
5353 |
5454LL | impl const S for u32 {}
5555 | ^^^^^^^^^^^^^^^^^^^^^^^
5656 |
5757note: this impl is unstable...
58 --> $DIR/staged-api.rs:117:1
58 --> $DIR/staged-api.rs:115:1
5959 |
6060LL | impl const S for u32 {}
6161 | ^^^^^^^^^^^^^^^^^^^^^^^
6262note: ...but the trait is stable
63 --> $DIR/staged-api.rs:95:7
63 --> $DIR/staged-api.rs:93:13
6464 |
65LL | trait S {}
66 | ^
65LL | const trait S {}
66 | ^
6767
6868error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
6969 --> $DIR/staged-api.rs:38:5
tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr+29-30
......@@ -1,69 +1,68 @@
11error: `[const]` is not allowed here
2 --> $DIR/super-traits-fail-2.rs:11:12
2 --> $DIR/super-traits-fail-2.rs:14:32
33 |
4LL | trait Bar: [const] Foo {}
5 | ^^^^^^^
4LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {}
5 | ^^^^^^^
66 |
77note: this trait is not `const`, so it cannot have `[const]` trait bounds
8 --> $DIR/super-traits-fail-2.rs:11:1
8 --> $DIR/super-traits-fail-2.rs:14:21
99 |
10LL | trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
10LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
1212
1313error: `[const]` can only be applied to `const` traits
14 --> $DIR/super-traits-fail-2.rs:11:12
14 --> $DIR/super-traits-fail-2.rs:14:32
1515 |
16LL | trait Bar: [const] Foo {}
17 | ^^^^^^^ can't be applied to `Foo`
16LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {}
17 | ^^^^^^^ can't be applied to `Foo`
1818 |
1919help: mark `Foo` as `const` to allow it to have `const` implementations
2020 |
21LL | #[const_trait] trait Foo {
22 | ++++++++++++++
21LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); }
22 | +++++
2323
2424error: `[const]` can only be applied to `const` traits
25 --> $DIR/super-traits-fail-2.rs:11:12
25 --> $DIR/super-traits-fail-2.rs:14:32
2626 |
27LL | trait Bar: [const] Foo {}
28 | ^^^^^^^ can't be applied to `Foo`
27LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {}
28 | ^^^^^^^ can't be applied to `Foo`
2929 |
3030 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
3131help: mark `Foo` as `const` to allow it to have `const` implementations
3232 |
33LL | #[const_trait] trait Foo {
34 | ++++++++++++++
33LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); }
34 | +++++
3535
3636error: `[const]` can only be applied to `const` traits
37 --> $DIR/super-traits-fail-2.rs:11:12
37 --> $DIR/super-traits-fail-2.rs:14:32
3838 |
39LL | trait Bar: [const] Foo {}
40 | ^^^^^^^ can't be applied to `Foo`
39LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {}
40 | ^^^^^^^ can't be applied to `Foo`
4141 |
4242 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
4343help: mark `Foo` as `const` to allow it to have `const` implementations
4444 |
45LL | #[const_trait] trait Foo {
46 | ++++++++++++++
45LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); }
46 | +++++
4747
4848error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
49 --> $DIR/super-traits-fail-2.rs:20:7
49 --> $DIR/super-traits-fail-2.rs:21:7
5050 |
5151LL | x.a();
5252 | ^^^
5353 |
5454note: method `a` is not const because trait `Foo` is not const
55 --> $DIR/super-traits-fail-2.rs:6:1
55 --> $DIR/super-traits-fail-2.rs:6:21
5656 |
57LL | trait Foo {
58 | ^^^^^^^^^ this trait is not const
59LL | fn a(&self);
60 | ------------ this method is not const
57LL | #[cfg(any(ny, nn))] trait Foo { fn a(&self); }
58 | ^^^^^^^^^ ------------ this method is not const
59 | |
60 | this trait is not const
6161 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
6262help: consider making trait `Foo` const
6363 |
64LL + #[const_trait]
65LL | trait Foo {
66 |
64LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); }
65 | +++++
6766
6867error: aborting due to 5 previous errors
6968
tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr+33-34
......@@ -1,81 +1,80 @@
11error: `[const]` can only be applied to `const` traits
2 --> $DIR/super-traits-fail-2.rs:11:12
2 --> $DIR/super-traits-fail-2.rs:8:38
33 |
4LL | trait Bar: [const] Foo {}
5 | ^^^^^^^ can't be applied to `Foo`
4LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {}
5 | ^^^^^^^ can't be applied to `Foo`
66 |
77help: mark `Foo` as `const` to allow it to have `const` implementations
88 |
9LL | #[const_trait] trait Foo {
10 | ++++++++++++++
9LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); }
10 | +++++
1111
1212error: `[const]` can only be applied to `const` traits
13 --> $DIR/super-traits-fail-2.rs:11:12
13 --> $DIR/super-traits-fail-2.rs:8:38
1414 |
15LL | trait Bar: [const] Foo {}
16 | ^^^^^^^ can't be applied to `Foo`
15LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {}
16 | ^^^^^^^ can't be applied to `Foo`
1717 |
1818 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
1919help: mark `Foo` as `const` to allow it to have `const` implementations
2020 |
21LL | #[const_trait] trait Foo {
22 | ++++++++++++++
21LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); }
22 | +++++
2323
2424error: `[const]` can only be applied to `const` traits
25 --> $DIR/super-traits-fail-2.rs:11:12
25 --> $DIR/super-traits-fail-2.rs:8:38
2626 |
27LL | trait Bar: [const] Foo {}
28 | ^^^^^^^ can't be applied to `Foo`
27LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {}
28 | ^^^^^^^ can't be applied to `Foo`
2929 |
3030 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
3131help: mark `Foo` as `const` to allow it to have `const` implementations
3232 |
33LL | #[const_trait] trait Foo {
34 | ++++++++++++++
33LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); }
34 | +++++
3535
3636error: `[const]` can only be applied to `const` traits
37 --> $DIR/super-traits-fail-2.rs:11:12
37 --> $DIR/super-traits-fail-2.rs:8:38
3838 |
39LL | trait Bar: [const] Foo {}
40 | ^^^^^^^ can't be applied to `Foo`
39LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {}
40 | ^^^^^^^ can't be applied to `Foo`
4141 |
4242 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
4343help: mark `Foo` as `const` to allow it to have `const` implementations
4444 |
45LL | #[const_trait] trait Foo {
46 | ++++++++++++++
45LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); }
46 | +++++
4747
4848error: `[const]` can only be applied to `const` traits
49 --> $DIR/super-traits-fail-2.rs:11:12
49 --> $DIR/super-traits-fail-2.rs:8:38
5050 |
51LL | trait Bar: [const] Foo {}
52 | ^^^^^^^ can't be applied to `Foo`
51LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {}
52 | ^^^^^^^ can't be applied to `Foo`
5353 |
5454 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
5555help: mark `Foo` as `const` to allow it to have `const` implementations
5656 |
57LL | #[const_trait] trait Foo {
58 | ++++++++++++++
57LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); }
58 | +++++
5959
6060error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
61 --> $DIR/super-traits-fail-2.rs:20:7
61 --> $DIR/super-traits-fail-2.rs:21:7
6262 |
6363LL | x.a();
6464 | ^^^
6565 |
6666note: method `a` is not const because trait `Foo` is not const
67 --> $DIR/super-traits-fail-2.rs:6:1
67 --> $DIR/super-traits-fail-2.rs:6:21
6868 |
69LL | trait Foo {
70 | ^^^^^^^^^ this trait is not const
71LL | fn a(&self);
72 | ------------ this method is not const
69LL | #[cfg(any(ny, nn))] trait Foo { fn a(&self); }
70 | ^^^^^^^^^ ------------ this method is not const
71 | |
72 | this trait is not const
7373 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
7474help: consider making trait `Foo` const
7575 |
76LL + #[const_trait]
77LL | trait Foo {
78 |
76LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); }
77 | +++++
7978
8079error: aborting due to 6 previous errors
8180
tests/ui/traits/const-traits/super-traits-fail-2.rs+11-10
......@@ -2,19 +2,20 @@
22#![feature(const_trait_impl)]
33//@ revisions: yy yn ny nn
44
5#[cfg_attr(any(yy, yn), const_trait)]
6trait Foo {
7 fn a(&self);
8}
5#[cfg(any(yy, yn))] const trait Foo { fn a(&self); }
6#[cfg(any(ny, nn))] trait Foo { fn a(&self); }
97
10#[cfg_attr(any(yy, ny), const_trait)]
11trait Bar: [const] Foo {}
12//[ny,nn]~^ ERROR: `[const]` can only be applied to `const` traits
13//[ny,nn]~| ERROR: `[const]` can only be applied to `const` traits
14//[ny,nn]~| ERROR: `[const]` can only be applied to `const` traits
8#[cfg(any(yy, ny))] const trait Bar: [const] Foo {}
9//[ny]~^ ERROR: `[const]` can only be applied to `const` traits
10//[ny]~| ERROR: `[const]` can only be applied to `const` traits
11//[ny]~| ERROR: `[const]` can only be applied to `const` traits
1512//[ny]~| ERROR: `[const]` can only be applied to `const` traits
1613//[ny]~| ERROR: `[const]` can only be applied to `const` traits
17//[yn,nn]~^^^^^^ ERROR: `[const]` is not allowed here
14#[cfg(any(yn, nn))] trait Bar: [const] Foo {}
15//[yn,nn]~^ ERROR: `[const]` is not allowed here
16//[nn]~^^ ERROR: `[const]` can only be applied to `const` traits
17//[nn]~| ERROR: `[const]` can only be applied to `const` traits
18//[nn]~| ERROR: `[const]` can only be applied to `const` traits
1819
1920const fn foo<T: Bar>(x: &T) {
2021 x.a();
tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr+7-7
......@@ -1,17 +1,17 @@
11error: `[const]` is not allowed here
2 --> $DIR/super-traits-fail-2.rs:11:12
2 --> $DIR/super-traits-fail-2.rs:14:32
33 |
4LL | trait Bar: [const] Foo {}
5 | ^^^^^^^
4LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {}
5 | ^^^^^^^
66 |
77note: this trait is not `const`, so it cannot have `[const]` trait bounds
8 --> $DIR/super-traits-fail-2.rs:11:1
8 --> $DIR/super-traits-fail-2.rs:14:21
99 |
10LL | trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
10LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
1212
1313error[E0277]: the trait bound `T: [const] Foo` is not satisfied
14 --> $DIR/super-traits-fail-2.rs:20:7
14 --> $DIR/super-traits-fail-2.rs:21:7
1515 |
1616LL | x.a();
1717 | ^
tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `T: [const] Foo` is not satisfied
2 --> $DIR/super-traits-fail-2.rs:20:7
2 --> $DIR/super-traits-fail-2.rs:21:7
33 |
44LL | x.a();
55 | ^
tests/ui/traits/const-traits/super-traits-fail-3.nnn.stderr+71-42
......@@ -1,27 +1,57 @@
11error: `[const]` is not allowed here
2 --> $DIR/super-traits-fail-3.rs:23:12
2 --> $DIR/super-traits-fail-3.rs:27:44
33 |
4LL | trait Bar: [const] Foo {}
5 | ^^^^^^^
4LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
5 | ^^^^^^^
66 |
77note: this trait is not `const`, so it cannot have `[const]` trait bounds
8 --> $DIR/super-traits-fail-3.rs:23:1
8 --> $DIR/super-traits-fail-3.rs:27:33
99 |
10LL | trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
10LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
1212
1313error[E0658]: const trait impls are experimental
14 --> $DIR/super-traits-fail-3.rs:23:12
14 --> $DIR/super-traits-fail-3.rs:15:33
1515 |
16LL | trait Bar: [const] Foo {}
17 | ^^^^^^^
16LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); }
17 | ^^^^^
1818 |
1919 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
2020 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
2121 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2222
2323error[E0658]: const trait impls are experimental
24 --> $DIR/super-traits-fail-3.rs:32:17
24 --> $DIR/super-traits-fail-3.rs:19:33
25 |
26LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
27 | ^^^^^
28 |
29 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
30 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
31 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
32
33error[E0658]: const trait impls are experimental
34 --> $DIR/super-traits-fail-3.rs:19:50
35 |
36LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
37 | ^^^^^^^
38 |
39 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
40 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
41 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
42
43error[E0658]: const trait impls are experimental
44 --> $DIR/super-traits-fail-3.rs:27:44
45 |
46LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
47 | ^^^^^^^
48 |
49 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
50 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
51 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
52
53error[E0658]: const trait impls are experimental
54 --> $DIR/super-traits-fail-3.rs:34:17
2555 |
2656LL | const fn foo<T: [const] Bar>(x: &T) {
2757 | ^^^^^^^
......@@ -31,53 +61,53 @@ LL | const fn foo<T: [const] Bar>(x: &T) {
3161 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
3262
3363error: `[const]` can only be applied to `const` traits
34 --> $DIR/super-traits-fail-3.rs:23:12
64 --> $DIR/super-traits-fail-3.rs:27:44
3565 |
36LL | trait Bar: [const] Foo {}
37 | ^^^^^^^ can't be applied to `Foo`
66LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
67 | ^^^^^^^ can't be applied to `Foo`
3868 |
3969help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations
4070 |
41LL | #[const_trait] trait Foo {
42 | ++++++++++++++
71LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
72 | +++++
4373
4474error: `[const]` can only be applied to `const` traits
45 --> $DIR/super-traits-fail-3.rs:23:12
75 --> $DIR/super-traits-fail-3.rs:27:44
4676 |
47LL | trait Bar: [const] Foo {}
48 | ^^^^^^^ can't be applied to `Foo`
77LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
78 | ^^^^^^^ can't be applied to `Foo`
4979 |
5080 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
5181help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations
5282 |
53LL | #[const_trait] trait Foo {
54 | ++++++++++++++
83LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
84 | +++++
5585
5686error: `[const]` can only be applied to `const` traits
57 --> $DIR/super-traits-fail-3.rs:23:12
87 --> $DIR/super-traits-fail-3.rs:27:44
5888 |
59LL | trait Bar: [const] Foo {}
60 | ^^^^^^^ can't be applied to `Foo`
89LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
90 | ^^^^^^^ can't be applied to `Foo`
6191 |
6292 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
6393help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations
6494 |
65LL | #[const_trait] trait Foo {
66 | ++++++++++++++
95LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
96 | +++++
6797
6898error: `[const]` can only be applied to `const` traits
69 --> $DIR/super-traits-fail-3.rs:32:17
99 --> $DIR/super-traits-fail-3.rs:34:17
70100 |
71101LL | const fn foo<T: [const] Bar>(x: &T) {
72102 | ^^^^^^^ can't be applied to `Bar`
73103 |
74104help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations
75105 |
76LL | #[const_trait] trait Bar: [const] Foo {}
77 | ++++++++++++++
106LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {}
107 | +++++
78108
79109error: `[const]` can only be applied to `const` traits
80 --> $DIR/super-traits-fail-3.rs:32:17
110 --> $DIR/super-traits-fail-3.rs:34:17
81111 |
82112LL | const fn foo<T: [const] Bar>(x: &T) {
83113 | ^^^^^^^ can't be applied to `Bar`
......@@ -85,31 +115,30 @@ LL | const fn foo<T: [const] Bar>(x: &T) {
85115 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
86116help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations
87117 |
88LL | #[const_trait] trait Bar: [const] Foo {}
89 | ++++++++++++++
118LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {}
119 | +++++
90120
91121error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
92 --> $DIR/super-traits-fail-3.rs:36:7
122 --> $DIR/super-traits-fail-3.rs:38:7
93123 |
94124LL | x.a();
95125 | ^^^
96126 |
97127note: method `a` is not const because trait `Foo` is not const
98 --> $DIR/super-traits-fail-3.rs:17:1
128 --> $DIR/super-traits-fail-3.rs:17:33
99129 |
100LL | trait Foo {
101 | ^^^^^^^^^ this trait is not const
102LL | fn a(&self);
103 | ------------ this method is not const
104 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]`
130LL | #[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); }
131 | ^^^^^^^^^ ------------ this method is not const
132 | |
133 | this trait is not const
134 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable const traits
105135 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
106136help: consider making trait `Foo` const
107137 |
108LL + #[const_trait]
109LL | trait Foo {
110 |
138LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
139 | +++++
111140
112error: aborting due to 9 previous errors
141error: aborting due to 12 previous errors
113142
114143Some errors have detailed explanations: E0015, E0658.
115144For more information about an error, try `rustc --explain E0015`.
tests/ui/traits/const-traits/super-traits-fail-3.nny.stderr+68-50
......@@ -1,27 +1,45 @@
1error: `[const]` is not allowed here
2 --> $DIR/super-traits-fail-3.rs:23:12
1error[E0658]: const trait impls are experimental
2 --> $DIR/super-traits-fail-3.rs:15:33
3 |
4LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); }
5 | ^^^^^
36 |
4LL | trait Bar: [const] Foo {}
5 | ^^^^^^^
7 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
8 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
9 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
10
11error[E0658]: const trait impls are experimental
12 --> $DIR/super-traits-fail-3.rs:19:33
613 |
7note: this trait is not `const`, so it cannot have `[const]` trait bounds
8 --> $DIR/super-traits-fail-3.rs:23:1
14LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
15 | ^^^^^
916 |
10LL | trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
17 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
18 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
19 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1220
1321error[E0658]: const trait impls are experimental
14 --> $DIR/super-traits-fail-3.rs:23:12
22 --> $DIR/super-traits-fail-3.rs:19:50
1523 |
16LL | trait Bar: [const] Foo {}
17 | ^^^^^^^
24LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
25 | ^^^^^^^
1826 |
1927 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
2028 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
2129 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2230
2331error[E0658]: const trait impls are experimental
24 --> $DIR/super-traits-fail-3.rs:32:17
32 --> $DIR/super-traits-fail-3.rs:27:44
33 |
34LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
35 | ^^^^^^^
36 |
37 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
38 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
39 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
40
41error[E0658]: const trait impls are experimental
42 --> $DIR/super-traits-fail-3.rs:34:17
2543 |
2644LL | const fn foo<T: [const] Bar>(x: &T) {
2745 | ^^^^^^^
......@@ -31,85 +49,85 @@ LL | const fn foo<T: [const] Bar>(x: &T) {
3149 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
3250
3351error: `[const]` can only be applied to `const` traits
34 --> $DIR/super-traits-fail-3.rs:23:12
52 --> $DIR/super-traits-fail-3.rs:19:50
3553 |
36LL | trait Bar: [const] Foo {}
37 | ^^^^^^^ can't be applied to `Foo`
54LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
55 | ^^^^^^^ can't be applied to `Foo`
3856 |
3957help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations
4058 |
41LL | #[const_trait] trait Foo {
42 | ++++++++++++++
59LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
60 | +++++
4361
4462error: `[const]` can only be applied to `const` traits
45 --> $DIR/super-traits-fail-3.rs:23:12
63 --> $DIR/super-traits-fail-3.rs:19:50
4664 |
47LL | trait Bar: [const] Foo {}
48 | ^^^^^^^ can't be applied to `Foo`
65LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
66 | ^^^^^^^ can't be applied to `Foo`
4967 |
5068 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
5169help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations
5270 |
53LL | #[const_trait] trait Foo {
54 | ++++++++++++++
71LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
72 | +++++
5573
5674error: `[const]` can only be applied to `const` traits
57 --> $DIR/super-traits-fail-3.rs:23:12
75 --> $DIR/super-traits-fail-3.rs:19:50
5876 |
59LL | trait Bar: [const] Foo {}
60 | ^^^^^^^ can't be applied to `Foo`
77LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
78 | ^^^^^^^ can't be applied to `Foo`
6179 |
6280 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
6381help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations
6482 |
65LL | #[const_trait] trait Foo {
66 | ++++++++++++++
83LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
84 | +++++
6785
6886error: `[const]` can only be applied to `const` traits
69 --> $DIR/super-traits-fail-3.rs:32:17
87 --> $DIR/super-traits-fail-3.rs:19:50
7088 |
71LL | const fn foo<T: [const] Bar>(x: &T) {
72 | ^^^^^^^ can't be applied to `Bar`
89LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
90 | ^^^^^^^ can't be applied to `Foo`
7391 |
74help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations
92 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
93help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations
7594 |
76LL | #[const_trait] trait Bar: [const] Foo {}
77 | ++++++++++++++
95LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
96 | +++++
7897
7998error: `[const]` can only be applied to `const` traits
80 --> $DIR/super-traits-fail-3.rs:32:17
99 --> $DIR/super-traits-fail-3.rs:19:50
81100 |
82LL | const fn foo<T: [const] Bar>(x: &T) {
83 | ^^^^^^^ can't be applied to `Bar`
101LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
102 | ^^^^^^^ can't be applied to `Foo`
84103 |
85104 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
86help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations
105help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations
87106 |
88LL | #[const_trait] trait Bar: [const] Foo {}
89 | ++++++++++++++
107LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
108 | +++++
90109
91110error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
92 --> $DIR/super-traits-fail-3.rs:36:7
111 --> $DIR/super-traits-fail-3.rs:38:7
93112 |
94113LL | x.a();
95114 | ^^^
96115 |
97116note: method `a` is not const because trait `Foo` is not const
98 --> $DIR/super-traits-fail-3.rs:17:1
117 --> $DIR/super-traits-fail-3.rs:17:33
99118 |
100LL | trait Foo {
101 | ^^^^^^^^^ this trait is not const
102LL | fn a(&self);
103 | ------------ this method is not const
104 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]`
119LL | #[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); }
120 | ^^^^^^^^^ ------------ this method is not const
121 | |
122 | this trait is not const
123 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable const traits
105124 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
106125help: consider making trait `Foo` const
107126 |
108LL + #[const_trait]
109LL | trait Foo {
110 |
127LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
128 | +++++
111129
112error: aborting due to 9 previous errors
130error: aborting due to 11 previous errors
113131
114132Some errors have detailed explanations: E0015, E0658.
115133For more information about an error, try `rustc --explain E0015`.
tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr+64-21
......@@ -1,54 +1,97 @@
1error: `[const]` is not allowed here
2 --> $DIR/super-traits-fail-3.rs:27:44
3 |
4LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
5 | ^^^^^^^
6 |
7note: this trait is not `const`, so it cannot have `[const]` trait bounds
8 --> $DIR/super-traits-fail-3.rs:27:33
9 |
10LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
12
113error[E0658]: const trait impls are experimental
2 --> $DIR/super-traits-fail-3.rs:23:12
14 --> $DIR/super-traits-fail-3.rs:15:33
315 |
4LL | trait Bar: [const] Foo {}
5 | ^^^^^^^
16LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); }
17 | ^^^^^
618 |
719 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
820 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
921 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1022
1123error[E0658]: const trait impls are experimental
12 --> $DIR/super-traits-fail-3.rs:32:17
24 --> $DIR/super-traits-fail-3.rs:19:33
1325 |
14LL | const fn foo<T: [const] Bar>(x: &T) {
15 | ^^^^^^^
26LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
27 | ^^^^^
1628 |
1729 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
1830 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
1931 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2032
21error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future.
22 --> $DIR/super-traits-fail-3.rs:15:37
33error[E0658]: const trait impls are experimental
34 --> $DIR/super-traits-fail-3.rs:19:50
2335 |
24LL | #[cfg_attr(any(yyy, yyn, nyy, nyn), const_trait)]
25 | ^^^^^^^^^^^
36LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
37 | ^^^^^^^
2638 |
2739 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
2840 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
2941 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
3042
31error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future.
32 --> $DIR/super-traits-fail-3.rs:21:37
43error[E0658]: const trait impls are experimental
44 --> $DIR/super-traits-fail-3.rs:27:44
3345 |
34LL | #[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)]
35 | ^^^^^^^^^^^
46LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
47 | ^^^^^^^
3648 |
3749 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
3850 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
3951 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
4052
41error[E0658]: cannot call conditionally-const method `<T as Foo>::a` in constant functions
42 --> $DIR/super-traits-fail-3.rs:36:7
53error[E0658]: const trait impls are experimental
54 --> $DIR/super-traits-fail-3.rs:34:17
4355 |
44LL | x.a();
45 | ^^^
56LL | const fn foo<T: [const] Bar>(x: &T) {
57 | ^^^^^^^
4658 |
47 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
4859 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
4960 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
5061 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
5162
52error: aborting due to 5 previous errors
63error: `[const]` can only be applied to `const` traits
64 --> $DIR/super-traits-fail-3.rs:34:17
65 |
66LL | const fn foo<T: [const] Bar>(x: &T) {
67 | ^^^^^^^ can't be applied to `Bar`
68 |
69help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations
70 |
71LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {}
72 | +++++
73
74error: `[const]` can only be applied to `const` traits
75 --> $DIR/super-traits-fail-3.rs:34:17
76 |
77LL | const fn foo<T: [const] Bar>(x: &T) {
78 | ^^^^^^^ can't be applied to `Bar`
79 |
80 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
81help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations
82 |
83LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {}
84 | +++++
85
86error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
87 --> $DIR/super-traits-fail-3.rs:38:7
88 |
89LL | x.a();
90 | ^^^
91 |
92 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
93
94error: aborting due to 9 previous errors
5395
54For more information about this error, try `rustc --explain E0658`.
96Some errors have detailed explanations: E0015, E0658.
97For more information about an error, try `rustc --explain E0015`.
tests/ui/traits/const-traits/super-traits-fail-3.nyy.stderr+26-16
......@@ -1,45 +1,55 @@
11error[E0658]: const trait impls are experimental
2 --> $DIR/super-traits-fail-3.rs:23:12
2 --> $DIR/super-traits-fail-3.rs:15:33
33 |
4LL | trait Bar: [const] Foo {}
5 | ^^^^^^^
4LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); }
5 | ^^^^^
66 |
77 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
88 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
99 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1010
1111error[E0658]: const trait impls are experimental
12 --> $DIR/super-traits-fail-3.rs:32:17
12 --> $DIR/super-traits-fail-3.rs:19:33
1313 |
14LL | const fn foo<T: [const] Bar>(x: &T) {
15 | ^^^^^^^
14LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
15 | ^^^^^
1616 |
1717 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
1818 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
1919 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2020
21error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future.
22 --> $DIR/super-traits-fail-3.rs:15:37
21error[E0658]: const trait impls are experimental
22 --> $DIR/super-traits-fail-3.rs:19:50
2323 |
24LL | #[cfg_attr(any(yyy, yyn, nyy, nyn), const_trait)]
25 | ^^^^^^^^^^^
24LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
25 | ^^^^^^^
2626 |
2727 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
2828 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
2929 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
3030
31error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future.
32 --> $DIR/super-traits-fail-3.rs:21:37
31error[E0658]: const trait impls are experimental
32 --> $DIR/super-traits-fail-3.rs:27:44
3333 |
34LL | #[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)]
35 | ^^^^^^^^^^^
34LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
35 | ^^^^^^^
36 |
37 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
38 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
39 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
40
41error[E0658]: const trait impls are experimental
42 --> $DIR/super-traits-fail-3.rs:34:17
43 |
44LL | const fn foo<T: [const] Bar>(x: &T) {
45 | ^^^^^^^
3646 |
3747 = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
3848 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
3949 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
4050
4151error[E0658]: cannot call conditionally-const method `<T as Foo>::a` in constant functions
42 --> $DIR/super-traits-fail-3.rs:36:7
52 --> $DIR/super-traits-fail-3.rs:38:7
4353 |
4454LL | x.a();
4555 | ^^^
......@@ -49,6 +59,6 @@ LL | x.a();
4959 = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
5060 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
5161
52error: aborting due to 5 previous errors
62error: aborting due to 6 previous errors
5363
5464For more information about this error, try `rustc --explain E0658`.
tests/ui/traits/const-traits/super-traits-fail-3.rs+21-19
......@@ -12,31 +12,33 @@
1212/// nny: feature not enabled, Foo is not const, Bar is const
1313/// nnn: feature not enabled, Foo is not const, Bar is not const
1414
15#[cfg_attr(any(yyy, yyn, nyy, nyn), const_trait)]
16//[nyy,nyn]~^ ERROR: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future
17trait Foo {
18 fn a(&self);
19}
15#[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); }
16//[nyy,nyn,nny,nnn]~^ ERROR: const trait impls are experimental
17#[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); }
2018
21#[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)]
22//[nyy,nyn]~^ ERROR: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future
23trait Bar: [const] Foo {}
24//[yny,ynn,nny,nnn]~^ ERROR: `[const]` can only be applied to `const` traits
25//[yny,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `const` traits
26//[yny,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `const` traits
27//[yny]~^^^^ ERROR: `[const]` can only be applied to `const` traits
28//[yny]~| ERROR: `[const]` can only be applied to `const` traits
29//[yyn,ynn,nny,nnn]~^^^^^^ ERROR: `[const]` is not allowed here
30//[nyy,nyn,nny,nnn]~^^^^^^^ ERROR: const trait impls are experimental
19#[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
20//[nyy,nyn,nny,nnn]~^ ERROR: const trait impls are experimental
21//[nyy,nyn,nny,nnn]~| ERROR: const trait impls are experimental
22//[yny,nny]~^^^ ERROR: `[const]` can only be applied to `const` traits
23//[yny,nny]~| ERROR: `[const]` can only be applied to `const` traits
24//[yny,nny]~| ERROR: `[const]` can only be applied to `const` traits
25//[yny,nny]~| ERROR: `[const]` can only be applied to `const` traits
26//[yny,nny]~| ERROR: `[const]` can only be applied to `const` traits
27#[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
28//[yyn,ynn,nyn,nnn]~^ ERROR: `[const]` is not allowed here
29//[nyy,nyn,nny,nnn]~^^ ERROR: const trait impls are experimental
30//[ynn,nnn]~^^^ ERROR: `[const]` can only be applied to `const` traits
31//[ynn,nnn]~| ERROR: `[const]` can only be applied to `const` traits
32//[ynn,nnn]~| ERROR: `[const]` can only be applied to `const` traits
3133
3234const fn foo<T: [const] Bar>(x: &T) {
33 //[yyn,ynn,nny,nnn]~^ ERROR: `[const]` can only be applied to `const` traits
34 //[yyn,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `const` traits
35 //[yyn,ynn,nyn,nnn]~^ ERROR: `[const]` can only be applied to `const` traits
36 //[yyn,ynn,nyn,nnn]~| ERROR: `[const]` can only be applied to `const` traits
3537 //[nyy,nyn,nny,nnn]~^^^ ERROR: const trait impls are experimental
3638 x.a();
3739 //[yyn]~^ ERROR: the trait bound `T: [const] Foo` is not satisfied
38 //[ynn,yny,nny,nnn]~^^ ERROR: cannot call non-const method `<T as Foo>::a` in constant functions
39 //[nyy,nyn]~^^^ ERROR: cannot call conditionally-const method `<T as Foo>::a` in constant functions
40 //[ynn,yny,nny,nnn,nyn]~^^ ERROR: cannot call non-const method `<T as Foo>::a` in constant functions
41 //[nyy]~^^^ ERROR: cannot call conditionally-const method `<T as Foo>::a` in constant functions
4042}
4143
4244fn main() {}
tests/ui/traits/const-traits/super-traits-fail-3.ynn.stderr+35-36
......@@ -1,63 +1,63 @@
11error: `[const]` is not allowed here
2 --> $DIR/super-traits-fail-3.rs:23:12
2 --> $DIR/super-traits-fail-3.rs:27:44
33 |
4LL | trait Bar: [const] Foo {}
5 | ^^^^^^^
4LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
5 | ^^^^^^^
66 |
77note: this trait is not `const`, so it cannot have `[const]` trait bounds
8 --> $DIR/super-traits-fail-3.rs:23:1
8 --> $DIR/super-traits-fail-3.rs:27:33
99 |
10LL | trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
10LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
1212
1313error: `[const]` can only be applied to `const` traits
14 --> $DIR/super-traits-fail-3.rs:23:12
14 --> $DIR/super-traits-fail-3.rs:27:44
1515 |
16LL | trait Bar: [const] Foo {}
17 | ^^^^^^^ can't be applied to `Foo`
16LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
17 | ^^^^^^^ can't be applied to `Foo`
1818 |
1919help: mark `Foo` as `const` to allow it to have `const` implementations
2020 |
21LL | #[const_trait] trait Foo {
22 | ++++++++++++++
21LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
22 | +++++
2323
2424error: `[const]` can only be applied to `const` traits
25 --> $DIR/super-traits-fail-3.rs:23:12
25 --> $DIR/super-traits-fail-3.rs:27:44
2626 |
27LL | trait Bar: [const] Foo {}
28 | ^^^^^^^ can't be applied to `Foo`
27LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
28 | ^^^^^^^ can't be applied to `Foo`
2929 |
3030 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
3131help: mark `Foo` as `const` to allow it to have `const` implementations
3232 |
33LL | #[const_trait] trait Foo {
34 | ++++++++++++++
33LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
34 | +++++
3535
3636error: `[const]` can only be applied to `const` traits
37 --> $DIR/super-traits-fail-3.rs:23:12
37 --> $DIR/super-traits-fail-3.rs:27:44
3838 |
39LL | trait Bar: [const] Foo {}
40 | ^^^^^^^ can't be applied to `Foo`
39LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
40 | ^^^^^^^ can't be applied to `Foo`
4141 |
4242 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
4343help: mark `Foo` as `const` to allow it to have `const` implementations
4444 |
45LL | #[const_trait] trait Foo {
46 | ++++++++++++++
45LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
46 | +++++
4747
4848error: `[const]` can only be applied to `const` traits
49 --> $DIR/super-traits-fail-3.rs:32:17
49 --> $DIR/super-traits-fail-3.rs:34:17
5050 |
5151LL | const fn foo<T: [const] Bar>(x: &T) {
5252 | ^^^^^^^ can't be applied to `Bar`
5353 |
5454help: mark `Bar` as `const` to allow it to have `const` implementations
5555 |
56LL | #[const_trait] trait Bar: [const] Foo {}
57 | ++++++++++++++
56LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {}
57 | +++++
5858
5959error: `[const]` can only be applied to `const` traits
60 --> $DIR/super-traits-fail-3.rs:32:17
60 --> $DIR/super-traits-fail-3.rs:34:17
6161 |
6262LL | const fn foo<T: [const] Bar>(x: &T) {
6363 | ^^^^^^^ can't be applied to `Bar`
......@@ -65,28 +65,27 @@ LL | const fn foo<T: [const] Bar>(x: &T) {
6565 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
6666help: mark `Bar` as `const` to allow it to have `const` implementations
6767 |
68LL | #[const_trait] trait Bar: [const] Foo {}
69 | ++++++++++++++
68LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {}
69 | +++++
7070
7171error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
72 --> $DIR/super-traits-fail-3.rs:36:7
72 --> $DIR/super-traits-fail-3.rs:38:7
7373 |
7474LL | x.a();
7575 | ^^^
7676 |
7777note: method `a` is not const because trait `Foo` is not const
78 --> $DIR/super-traits-fail-3.rs:17:1
78 --> $DIR/super-traits-fail-3.rs:17:33
7979 |
80LL | trait Foo {
81 | ^^^^^^^^^ this trait is not const
82LL | fn a(&self);
83 | ------------ this method is not const
80LL | #[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); }
81 | ^^^^^^^^^ ------------ this method is not const
82 | |
83 | this trait is not const
8484 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
8585help: consider making trait `Foo` const
8686 |
87LL + #[const_trait]
88LL | trait Foo {
89 |
87LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
88 | +++++
9089
9190error: aborting due to 7 previous errors
9291
tests/ui/traits/const-traits/super-traits-fail-3.yny.stderr+33-34
......@@ -1,81 +1,80 @@
11error: `[const]` can only be applied to `const` traits
2 --> $DIR/super-traits-fail-3.rs:23:12
2 --> $DIR/super-traits-fail-3.rs:19:50
33 |
4LL | trait Bar: [const] Foo {}
5 | ^^^^^^^ can't be applied to `Foo`
4LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
5 | ^^^^^^^ can't be applied to `Foo`
66 |
77help: mark `Foo` as `const` to allow it to have `const` implementations
88 |
9LL | #[const_trait] trait Foo {
10 | ++++++++++++++
9LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
10 | +++++
1111
1212error: `[const]` can only be applied to `const` traits
13 --> $DIR/super-traits-fail-3.rs:23:12
13 --> $DIR/super-traits-fail-3.rs:19:50
1414 |
15LL | trait Bar: [const] Foo {}
16 | ^^^^^^^ can't be applied to `Foo`
15LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
16 | ^^^^^^^ can't be applied to `Foo`
1717 |
1818 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
1919help: mark `Foo` as `const` to allow it to have `const` implementations
2020 |
21LL | #[const_trait] trait Foo {
22 | ++++++++++++++
21LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
22 | +++++
2323
2424error: `[const]` can only be applied to `const` traits
25 --> $DIR/super-traits-fail-3.rs:23:12
25 --> $DIR/super-traits-fail-3.rs:19:50
2626 |
27LL | trait Bar: [const] Foo {}
28 | ^^^^^^^ can't be applied to `Foo`
27LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
28 | ^^^^^^^ can't be applied to `Foo`
2929 |
3030 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
3131help: mark `Foo` as `const` to allow it to have `const` implementations
3232 |
33LL | #[const_trait] trait Foo {
34 | ++++++++++++++
33LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
34 | +++++
3535
3636error: `[const]` can only be applied to `const` traits
37 --> $DIR/super-traits-fail-3.rs:23:12
37 --> $DIR/super-traits-fail-3.rs:19:50
3838 |
39LL | trait Bar: [const] Foo {}
40 | ^^^^^^^ can't be applied to `Foo`
39LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
40 | ^^^^^^^ can't be applied to `Foo`
4141 |
4242 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
4343help: mark `Foo` as `const` to allow it to have `const` implementations
4444 |
45LL | #[const_trait] trait Foo {
46 | ++++++++++++++
45LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
46 | +++++
4747
4848error: `[const]` can only be applied to `const` traits
49 --> $DIR/super-traits-fail-3.rs:23:12
49 --> $DIR/super-traits-fail-3.rs:19:50
5050 |
51LL | trait Bar: [const] Foo {}
52 | ^^^^^^^ can't be applied to `Foo`
51LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {}
52 | ^^^^^^^ can't be applied to `Foo`
5353 |
5454 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
5555help: mark `Foo` as `const` to allow it to have `const` implementations
5656 |
57LL | #[const_trait] trait Foo {
58 | ++++++++++++++
57LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
58 | +++++
5959
6060error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions
61 --> $DIR/super-traits-fail-3.rs:36:7
61 --> $DIR/super-traits-fail-3.rs:38:7
6262 |
6363LL | x.a();
6464 | ^^^
6565 |
6666note: method `a` is not const because trait `Foo` is not const
67 --> $DIR/super-traits-fail-3.rs:17:1
67 --> $DIR/super-traits-fail-3.rs:17:33
6868 |
69LL | trait Foo {
70 | ^^^^^^^^^ this trait is not const
71LL | fn a(&self);
72 | ------------ this method is not const
69LL | #[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); }
70 | ^^^^^^^^^ ------------ this method is not const
71 | |
72 | this trait is not const
7373 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
7474help: consider making trait `Foo` const
7575 |
76LL + #[const_trait]
77LL | trait Foo {
78 |
76LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); }
77 | +++++
7978
8079error: aborting due to 6 previous errors
8180
tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr+13-13
......@@ -1,28 +1,28 @@
11error: `[const]` is not allowed here
2 --> $DIR/super-traits-fail-3.rs:23:12
2 --> $DIR/super-traits-fail-3.rs:27:44
33 |
4LL | trait Bar: [const] Foo {}
5 | ^^^^^^^
4LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
5 | ^^^^^^^
66 |
77note: this trait is not `const`, so it cannot have `[const]` trait bounds
8 --> $DIR/super-traits-fail-3.rs:23:1
8 --> $DIR/super-traits-fail-3.rs:27:33
99 |
10LL | trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
10LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {}
11 | ^^^^^^^^^^^^^^^^^^^^^^^^^
1212
1313error: `[const]` can only be applied to `const` traits
14 --> $DIR/super-traits-fail-3.rs:32:17
14 --> $DIR/super-traits-fail-3.rs:34:17
1515 |
1616LL | const fn foo<T: [const] Bar>(x: &T) {
1717 | ^^^^^^^ can't be applied to `Bar`
1818 |
1919help: mark `Bar` as `const` to allow it to have `const` implementations
2020 |
21LL | #[const_trait] trait Bar: [const] Foo {}
22 | ++++++++++++++
21LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {}
22 | +++++
2323
2424error: `[const]` can only be applied to `const` traits
25 --> $DIR/super-traits-fail-3.rs:32:17
25 --> $DIR/super-traits-fail-3.rs:34:17
2626 |
2727LL | const fn foo<T: [const] Bar>(x: &T) {
2828 | ^^^^^^^ can't be applied to `Bar`
......@@ -30,11 +30,11 @@ LL | const fn foo<T: [const] Bar>(x: &T) {
3030 = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
3131help: mark `Bar` as `const` to allow it to have `const` implementations
3232 |
33LL | #[const_trait] trait Bar: [const] Foo {}
34 | ++++++++++++++
33LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {}
34 | +++++
3535
3636error[E0277]: the trait bound `T: [const] Foo` is not satisfied
37 --> $DIR/super-traits-fail-3.rs:36:7
37 --> $DIR/super-traits-fail-3.rs:38:7
3838 |
3939LL | x.a();
4040 | ^
tests/ui/traits/const-traits/super-traits-fail.rs+2-4
......@@ -2,12 +2,10 @@
22
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait Foo {
5const trait Foo {
76 fn a(&self);
87}
9#[const_trait]
10trait Bar: [const] Foo {}
8const trait Bar: [const] Foo {}
119
1210struct S;
1311impl Foo for S {
tests/ui/traits/const-traits/super-traits-fail.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0277]: the trait bound `S: [const] Foo` is not satisfied
2 --> $DIR/super-traits-fail.rs:17:20
2 --> $DIR/super-traits-fail.rs:15:20
33 |
44LL | impl const Bar for S {}
55 | ^
tests/ui/traits/const-traits/super-traits.rs+2-4
......@@ -2,13 +2,11 @@
22//@ compile-flags: -Znext-solver
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait Foo {
5const trait Foo {
76 fn a(&self);
87}
98
10#[const_trait]
11trait Bar: [const] Foo {}
9const trait Bar: [const] Foo {}
1210
1311struct S;
1412impl const Foo for S {
tests/ui/traits/const-traits/syntactical-unstable.rs+1-2
......@@ -9,8 +9,7 @@ use std::ops::Deref;
99extern crate staged_api;
1010use staged_api::MyTrait;
1111
12#[const_trait]
13trait Foo: [const] MyTrait {
12const trait Foo: [const] MyTrait {
1413 //~^ ERROR use of unstable const library feature `unstable`
1514 type Item: [const] MyTrait;
1615 //~^ ERROR use of unstable const library feature `unstable`
tests/ui/traits/const-traits/syntactical-unstable.stderr+10-10
......@@ -1,16 +1,16 @@
11error[E0658]: use of unstable const library feature `unstable`
2 --> $DIR/syntactical-unstable.rs:13:20
2 --> $DIR/syntactical-unstable.rs:12:26
33 |
4LL | trait Foo: [const] MyTrait {
5 | ------- ^^^^^^^
6 | |
7 | trait is not stable as const yet
4LL | const trait Foo: [const] MyTrait {
5 | ------- ^^^^^^^
6 | |
7 | trait is not stable as const yet
88 |
99 = help: add `#![feature(unstable)]` to the crate attributes to enable
1010 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1111
1212error[E0658]: use of unstable const library feature `unstable`
13 --> $DIR/syntactical-unstable.rs:19:45
13 --> $DIR/syntactical-unstable.rs:18:45
1414 |
1515LL | const fn where_clause<T>() where T: [const] MyTrait {}
1616 | ------- ^^^^^^^
......@@ -21,7 +21,7 @@ LL | const fn where_clause<T>() where T: [const] MyTrait {}
2121 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2222
2323error[E0658]: use of unstable const library feature `unstable`
24 --> $DIR/syntactical-unstable.rs:22:53
24 --> $DIR/syntactical-unstable.rs:21:53
2525 |
2626LL | const fn nested<T>() where T: Deref<Target: [const] MyTrait> {}
2727 | ------- ^^^^^^^
......@@ -32,7 +32,7 @@ LL | const fn nested<T>() where T: Deref<Target: [const] MyTrait> {}
3232 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
3333
3434error[E0658]: use of unstable const library feature `unstable`
35 --> $DIR/syntactical-unstable.rs:25:33
35 --> $DIR/syntactical-unstable.rs:24:33
3636 |
3737LL | const fn rpit() -> impl [const] MyTrait { Local }
3838 | ------- ^^^^^^^
......@@ -43,7 +43,7 @@ LL | const fn rpit() -> impl [const] MyTrait { Local }
4343 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
4444
4545error[E0658]: use of unstable const library feature `unstable`
46 --> $DIR/syntactical-unstable.rs:29:12
46 --> $DIR/syntactical-unstable.rs:28:12
4747 |
4848LL | impl const MyTrait for Local {
4949 | ^^^^^^^ trait is not stable as const yet
......@@ -52,7 +52,7 @@ LL | impl const MyTrait for Local {
5252 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
5353
5454error[E0658]: use of unstable const library feature `unstable`
55 --> $DIR/syntactical-unstable.rs:15:24
55 --> $DIR/syntactical-unstable.rs:14:24
5656 |
5757LL | type Item: [const] MyTrait;
5858 | ------- ^^^^^^^
tests/ui/traits/const-traits/trait-default-body-stability.rs+1-2
......@@ -39,8 +39,7 @@ impl const FromResidual for T {
3939
4040#[stable(feature = "foo", since = "1.0")]
4141#[rustc_const_unstable(feature = "const_tr", issue = "none")]
42#[const_trait]
43pub trait Tr {
42pub const trait Tr {
4443 #[stable(feature = "foo", since = "1.0")]
4544 fn bar() -> T {
4645 T?
tests/ui/traits/const-traits/trait-fn-const.rs+1-2
......@@ -1,8 +1,7 @@
11// Regression test for issue #113378.
22#![feature(const_trait_impl)]
33
4#[const_trait]
5trait Trait {
4const trait Trait {
65 const fn fun(); //~ ERROR functions in traits cannot be declared const
76}
87
tests/ui/traits/const-traits/trait-fn-const.stderr+9-11
......@@ -1,9 +1,8 @@
11error[E0379]: functions in traits cannot be declared const
2 --> $DIR/trait-fn-const.rs:6:5
2 --> $DIR/trait-fn-const.rs:5:5
33 |
4LL | #[const_trait]
5 | -------------- this declares all associated functions implicitly const
6LL | trait Trait {
4LL | const trait Trait {
5 | ----- this declares all associated functions implicitly const
76LL | const fn fun();
87 | ^^^^^-
98 | |
......@@ -11,7 +10,7 @@ LL | const fn fun();
1110 | help: remove the `const`
1211
1312error[E0379]: functions in trait impls cannot be declared const
14 --> $DIR/trait-fn-const.rs:10:5
13 --> $DIR/trait-fn-const.rs:9:5
1514 |
1615LL | impl const Trait for () {
1716 | ----- this declares all associated functions implicitly const
......@@ -22,7 +21,7 @@ LL | const fn fun() {}
2221 | help: remove the `const`
2322
2423error[E0379]: functions in trait impls cannot be declared const
25 --> $DIR/trait-fn-const.rs:14:5
24 --> $DIR/trait-fn-const.rs:13:5
2625 |
2726LL | const fn fun() {}
2827 | ^^^^^ functions in trait impls cannot be const
......@@ -38,7 +37,7 @@ LL | impl const Trait for u32 {
3837 | +++++
3938
4039error[E0379]: functions in traits cannot be declared const
41 --> $DIR/trait-fn-const.rs:18:5
40 --> $DIR/trait-fn-const.rs:17:5
4241 |
4342LL | const fn fun();
4443 | ^^^^^ functions in traits cannot be const
......@@ -48,11 +47,10 @@ help: remove the `const` ...
4847LL - const fn fun();
4948LL + fn fun();
5049 |
51help: ... and declare the trait to be a `#[const_trait]` instead
52 |
53LL + #[const_trait]
54LL | trait NonConst {
50help: ... and declare the trait to be const instead
5551 |
52LL | const trait NonConst {
53 | +++++
5654
5755error: aborting due to 4 previous errors
5856
tests/ui/traits/const-traits/trait-where-clause-const.rs+2-4
......@@ -6,11 +6,9 @@
66
77#![feature(const_trait_impl)]
88
9#[const_trait]
10trait Bar {}
9const trait Bar {}
1110
12#[const_trait]
13trait Foo {
11const trait Foo {
1412 fn a();
1513 fn b() where Self: [const] Bar;
1614 fn c<T: [const] Bar>();
tests/ui/traits/const-traits/trait-where-clause-const.stderr+4-4
......@@ -1,23 +1,23 @@
11error[E0277]: the trait bound `T: [const] Bar` is not satisfied
2 --> $DIR/trait-where-clause-const.rs:21:5
2 --> $DIR/trait-where-clause-const.rs:19:5
33 |
44LL | T::b();
55 | ^
66 |
77note: required by a bound in `Foo::b`
8 --> $DIR/trait-where-clause-const.rs:15:24
8 --> $DIR/trait-where-clause-const.rs:13:24
99 |
1010LL | fn b() where Self: [const] Bar;
1111 | ^^^^^^^^^^^ required by this bound in `Foo::b`
1212
1313error[E0277]: the trait bound `T: [const] Bar` is not satisfied
14 --> $DIR/trait-where-clause-const.rs:23:12
14 --> $DIR/trait-where-clause-const.rs:21:12
1515 |
1616LL | T::c::<T>();
1717 | ^
1818 |
1919note: required by a bound in `Foo::c`
20 --> $DIR/trait-where-clause-const.rs:16:13
20 --> $DIR/trait-where-clause-const.rs:14:13
2121 |
2222LL | fn c<T: [const] Bar>();
2323 | ^^^^^^^^^^^ required by this bound in `Foo::c`
tests/ui/traits/const-traits/trait-where-clause-run.rs+2-4
......@@ -3,13 +3,11 @@
33
44#![feature(const_trait_impl)]
55
6#[const_trait]
7trait Bar {
6const trait Bar {
87 fn bar() -> u8;
98}
109
11#[const_trait]
12trait Foo {
10const trait Foo {
1311 fn foo() -> u8 where Self: [const] Bar {
1412 <Self as Bar>::bar() * 6
1513 }
tests/ui/traits/const-traits/trait-where-clause-self-referential.rs+1-2
......@@ -2,8 +2,7 @@
22//@ compile-flags: -Znext-solver
33#![feature(const_trait_impl)]
44
5#[const_trait]
6trait Foo {
5const trait Foo {
76 fn bar() where Self: [const] Foo;
87}
98
tests/ui/traits/const-traits/trait-where-clause.rs+1-2
......@@ -1,7 +1,6 @@
11#![feature(const_trait_impl)]
22
3#[const_trait]
4trait Bar {}
3const trait Bar {}
54
65trait Foo {
76 fn a();
tests/ui/traits/const-traits/trait-where-clause.stderr+8-8
......@@ -1,35 +1,35 @@
11error: `[const]` is not allowed here
2 --> $DIR/trait-where-clause.rs:8:24
2 --> $DIR/trait-where-clause.rs:7:24
33 |
44LL | fn b() where Self: [const] Bar;
55 | ^^^^^^^
66 |
77note: this function is not `const`, so it cannot have `[const]` trait bounds
8 --> $DIR/trait-where-clause.rs:8:8
8 --> $DIR/trait-where-clause.rs:7:8
99 |
1010LL | fn b() where Self: [const] Bar;
1111 | ^
1212
1313error: `[const]` is not allowed here
14 --> $DIR/trait-where-clause.rs:10:13
14 --> $DIR/trait-where-clause.rs:9:13
1515 |
1616LL | fn c<T: [const] Bar>();
1717 | ^^^^^^^
1818 |
1919note: this function is not `const`, so it cannot have `[const]` trait bounds
20 --> $DIR/trait-where-clause.rs:10:8
20 --> $DIR/trait-where-clause.rs:9:8
2121 |
2222LL | fn c<T: [const] Bar>();
2323 | ^
2424
2525error[E0277]: the trait bound `T: Bar` is not satisfied
26 --> $DIR/trait-where-clause.rs:16:5
26 --> $DIR/trait-where-clause.rs:15:5
2727 |
2828LL | T::b();
2929 | ^ the trait `Bar` is not implemented for `T`
3030 |
3131note: required by a bound in `Foo::b`
32 --> $DIR/trait-where-clause.rs:8:24
32 --> $DIR/trait-where-clause.rs:7:24
3333 |
3434LL | fn b() where Self: [const] Bar;
3535 | ^^^^^^^^^^^ required by this bound in `Foo::b`
......@@ -39,13 +39,13 @@ LL | fn test1<T: Foo + Bar>() {
3939 | +++++
4040
4141error[E0277]: the trait bound `T: Bar` is not satisfied
42 --> $DIR/trait-where-clause.rs:18:12
42 --> $DIR/trait-where-clause.rs:17:12
4343 |
4444LL | T::c::<T>();
4545 | ^ the trait `Bar` is not implemented for `T`
4646 |
4747note: required by a bound in `Foo::c`
48 --> $DIR/trait-where-clause.rs:10:13
48 --> $DIR/trait-where-clause.rs:9:13
4949 |
5050LL | fn c<T: [const] Bar>();
5151 | ^^^^^^^^^^^ required by this bound in `Foo::c`
tests/ui/traits/const-traits/unconstrained-var-specialization.rs+1-2
......@@ -7,8 +7,7 @@
77// In the default impl below, `A` is constrained by the projection predicate, and if the host effect
88// predicate for `const Foo` doesn't resolve vars, then specialization will fail.
99
10#[const_trait]
11trait Foo {}
10const trait Foo {}
1211
1312pub trait Iterator {
1413 type Item;
tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs+1-2
......@@ -7,8 +7,7 @@
77
88fn require<T: const Trait>() {}
99
10#[const_trait]
11trait Trait {
10const trait Trait {
1211 fn make() -> u32;
1312}
1413
tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr+16-16
......@@ -7,88 +7,88 @@ LL | #![feature(const_trait_impl, generic_const_exprs)]
77 = help: remove one of these features
88
99error[E0391]: cycle detected when evaluating type-level constant
10 --> $DIR/unsatisfied-const-trait-bound.rs:29:35
10 --> $DIR/unsatisfied-const-trait-bound.rs:28:35
1111 |
1212LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
1313 | ^^^^^^^^^^^^^
1414 |
1515note: ...which requires const-evaluating + checking `accept0::{constant#0}`...
16 --> $DIR/unsatisfied-const-trait-bound.rs:29:35
16 --> $DIR/unsatisfied-const-trait-bound.rs:28:35
1717 |
1818LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
1919 | ^^^^^^^^^^^^^
2020note: ...which requires checking if `accept0::{constant#0}` is a trivial const...
21 --> $DIR/unsatisfied-const-trait-bound.rs:29:35
21 --> $DIR/unsatisfied-const-trait-bound.rs:28:35
2222 |
2323LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
2424 | ^^^^^^^^^^^^^
2525note: ...which requires building MIR for `accept0::{constant#0}`...
26 --> $DIR/unsatisfied-const-trait-bound.rs:29:35
26 --> $DIR/unsatisfied-const-trait-bound.rs:28:35
2727 |
2828LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
2929 | ^^^^^^^^^^^^^
3030note: ...which requires building an abstract representation for `accept0::{constant#0}`...
31 --> $DIR/unsatisfied-const-trait-bound.rs:29:35
31 --> $DIR/unsatisfied-const-trait-bound.rs:28:35
3232 |
3333LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
3434 | ^^^^^^^^^^^^^
3535note: ...which requires building THIR for `accept0::{constant#0}`...
36 --> $DIR/unsatisfied-const-trait-bound.rs:29:35
36 --> $DIR/unsatisfied-const-trait-bound.rs:28:35
3737 |
3838LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
3939 | ^^^^^^^^^^^^^
4040note: ...which requires type-checking `accept0::{constant#0}`...
41 --> $DIR/unsatisfied-const-trait-bound.rs:29:35
41 --> $DIR/unsatisfied-const-trait-bound.rs:28:35
4242 |
4343LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
4444 | ^^^^^^^^^^^^^
4545 = note: ...which again requires evaluating type-level constant, completing the cycle
4646note: cycle used when checking that `accept0` is well-formed
47 --> $DIR/unsatisfied-const-trait-bound.rs:29:35
47 --> $DIR/unsatisfied-const-trait-bound.rs:28:35
4848 |
4949LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
5050 | ^^^^^^^^^^^^^
5151 = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
5252
5353error[E0391]: cycle detected when checking if `accept1::{constant#0}` is a trivial const
54 --> $DIR/unsatisfied-const-trait-bound.rs:33:49
54 --> $DIR/unsatisfied-const-trait-bound.rs:32:49
5555 |
5656LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
5757 | ^^^^^^^^^^^^^
5858 |
5959note: ...which requires building MIR for `accept1::{constant#0}`...
60 --> $DIR/unsatisfied-const-trait-bound.rs:33:49
60 --> $DIR/unsatisfied-const-trait-bound.rs:32:49
6161 |
6262LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
6363 | ^^^^^^^^^^^^^
6464note: ...which requires building an abstract representation for `accept1::{constant#0}`...
65 --> $DIR/unsatisfied-const-trait-bound.rs:33:49
65 --> $DIR/unsatisfied-const-trait-bound.rs:32:49
6666 |
6767LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
6868 | ^^^^^^^^^^^^^
6969note: ...which requires building THIR for `accept1::{constant#0}`...
70 --> $DIR/unsatisfied-const-trait-bound.rs:33:49
70 --> $DIR/unsatisfied-const-trait-bound.rs:32:49
7171 |
7272LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
7373 | ^^^^^^^^^^^^^
7474note: ...which requires type-checking `accept1::{constant#0}`...
75 --> $DIR/unsatisfied-const-trait-bound.rs:33:49
75 --> $DIR/unsatisfied-const-trait-bound.rs:32:49
7676 |
7777LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
7878 | ^^^^^^^^^^^^^
7979note: ...which requires evaluating type-level constant...
80 --> $DIR/unsatisfied-const-trait-bound.rs:33:49
80 --> $DIR/unsatisfied-const-trait-bound.rs:32:49
8181 |
8282LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
8383 | ^^^^^^^^^^^^^
8484note: ...which requires const-evaluating + checking `accept1::{constant#0}`...
85 --> $DIR/unsatisfied-const-trait-bound.rs:33:49
85 --> $DIR/unsatisfied-const-trait-bound.rs:32:49
8686 |
8787LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
8888 | ^^^^^^^^^^^^^
8989 = note: ...which again requires checking if `accept1::{constant#0}` is a trivial const, completing the cycle
9090note: cycle used when const-evaluating + checking `accept1::{constant#0}`
91 --> $DIR/unsatisfied-const-trait-bound.rs:33:49
91 --> $DIR/unsatisfied-const-trait-bound.rs:32:49
9292 |
9393LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {}
9494 | ^^^^^^^^^^^^^
tests/ui/traits/const-traits/variance.rs+1-2
......@@ -2,8 +2,7 @@
22#![allow(internal_features)]
33#![rustc_variance_of_opaques]
44
5#[const_trait]
6trait Foo {}
5const trait Foo {}
76
87impl const Foo for () {}
98
tests/ui/traits/const-traits/variance.stderr+1-1
......@@ -1,5 +1,5 @@
11error: ['a: *]
2 --> $DIR/variance.rs:10:21
2 --> $DIR/variance.rs:9:21
33 |
44LL | fn foo<'a: 'a>() -> impl const Foo {}
55 | ^^^^^^^^^^^^^^
tests/ui/traits/next-solver/canonical/effect-var.rs+1-2
......@@ -3,8 +3,7 @@
33
44#![feature(const_trait_impl)]
55
6#[const_trait]
7trait Foo {
6const trait Foo {
87 fn foo();
98}
109
triagebot.toml+1
......@@ -1419,6 +1419,7 @@ compiler_leads = [
14191419]
14201420compiler = [
14211421 "@BoxyUwU",
1422 "@chenyukang",
14221423 "@compiler-errors",
14231424 "@davidtwco",
14241425 "@eholk",