| author | bors <bors@rust-lang.org> 2025-11-09 16:44:31 UTC |
| committer | bors <bors@rust-lang.org> 2025-11-09 16:44:31 UTC |
| log | 86b95ebc24092acac75e205d95e84e6d4539601f |
| tree | 7e1edc325286496710bca9507eff67b5aa977649 |
| parent | ab67c37c6dbea849aa3425146bfe99fb1f1d117a |
| parent | a2c4f03ea79e2e7807d403efb6da5dacc97ddd6a |
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: rollup306 files changed, 2362 insertions(+), 1968 deletions(-)
.mailmap+1-1| ... | ... | @@ -139,7 +139,6 @@ Christian Poveda <git@pvdrz.com> <31802960+christianpoveda@users.noreply.github. |
| 139 | 139 | Christian Poveda <git@pvdrz.com> <christianpoveda@uhura.edef.eu> |
| 140 | 140 | Christian Vallentin <vallentinsource@gmail.com> |
| 141 | 141 | Christoffer Buchholz <chris@chrisbuchholz.me> |
| 142 | Christopher Durham <cad97@cad97.com> | |
| 143 | 142 | Clark Gaebel <cg.wowus.cg@gmail.com> <cgaebel@mozilla.com> |
| 144 | 143 | Clement Miao <clementmiao@gmail.com> |
| 145 | 144 | Clément Renault <renault.cle@gmail.com> |
| ... | ... | @@ -148,6 +147,7 @@ Clinton Ryan <clint.ryan3@gmail.com> |
| 148 | 147 | Taylor Cramer <cramertaylorj@gmail.com> <cramertj@google.com> |
| 149 | 148 | ember arlynx <ember@lunar.town> <corey@octayn.net> |
| 150 | 149 | Crazycolorz5 <Crazycolorz5@gmail.com> |
| 150 | Crystal Durham <cad97@cad97.com> | |
| 151 | 151 | csmoe <35686186+csmoe@users.noreply.github.com> |
| 152 | 152 | Cyryl Płotnicki <cyplo@cyplo.net> |
| 153 | 153 | Damien Schoof <damien.schoof@gmail.com> |
compiler/rustc_ast_passes/messages.ftl+1-1| ... | ... | @@ -290,7 +290,7 @@ ast_passes_trait_fn_const = |
| 290 | 290 | *[false] {""} |
| 291 | 291 | } |
| 292 | 292 | .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 | |
| 294 | 294 | |
| 295 | 295 | ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted |
| 296 | 296 |
compiler/rustc_ast_passes/src/ast_validation.rs+9-14| ... | ... | @@ -48,7 +48,7 @@ enum SelfSemantic { |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 50 | enum TraitOrTraitImpl { |
| 51 | Trait { span: Span, constness: Const }, | |
| 51 | Trait { vis: Span, constness: Const }, | |
| 52 | 52 | TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span }, |
| 53 | 53 | } |
| 54 | 54 | |
| ... | ... | @@ -109,10 +109,10 @@ impl<'a> AstValidator<'a> { |
| 109 | 109 | self.outer_trait_or_trait_impl = old; |
| 110 | 110 | } |
| 111 | 111 | |
| 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)) { | |
| 113 | 113 | let old = mem::replace( |
| 114 | 114 | &mut self.outer_trait_or_trait_impl, |
| 115 | Some(TraitOrTraitImpl::Trait { span, constness }), | |
| 115 | Some(TraitOrTraitImpl::Trait { vis, constness }), | |
| 116 | 116 | ); |
| 117 | 117 | f(self); |
| 118 | 118 | self.outer_trait_or_trait_impl = old; |
| ... | ... | @@ -265,10 +265,12 @@ impl<'a> AstValidator<'a> { |
| 265 | 265 | None |
| 266 | 266 | }; |
| 267 | 267 | |
| 268 | let map = self.sess.source_map(); | |
| 269 | ||
| 268 | 270 | 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 | |
| 270 | 272 | { |
| 271 | Some(span.shrink_to_lo()) | |
| 273 | Some(map.span_extend_while_whitespace(vis).shrink_to_hi()) | |
| 272 | 274 | } else { |
| 273 | 275 | None |
| 274 | 276 | }; |
| ... | ... | @@ -279,7 +281,7 @@ impl<'a> AstValidator<'a> { |
| 279 | 281 | in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }), |
| 280 | 282 | const_context_label: parent_constness, |
| 281 | 283 | remove_const_sugg: ( |
| 282 | self.sess.source_map().span_extend_while_whitespace(span), | |
| 284 | map.span_extend_while_whitespace(span), | |
| 283 | 285 | match parent_constness { |
| 284 | 286 | Some(_) => rustc_errors::Applicability::MachineApplicable, |
| 285 | 287 | None => rustc_errors::Applicability::MaybeIncorrect, |
| ... | ... | @@ -1165,13 +1167,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |
| 1165 | 1167 | .. |
| 1166 | 1168 | }) => { |
| 1167 | 1169 | 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 | }; | |
| 1175 | 1170 | if *is_auto == IsAuto::Yes { |
| 1176 | 1171 | // Auto traits cannot have generics, super traits nor contain items. |
| 1177 | 1172 | self.deny_generic_params(generics, ident.span); |
| ... | ... | @@ -1188,7 +1183,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |
| 1188 | 1183 | this.visit_generics(generics); |
| 1189 | 1184 | walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) |
| 1190 | 1185 | }); |
| 1191 | self.with_in_trait(item.span, constness, |this| { | |
| 1186 | self.with_in_trait(item.vis.span, *constness, |this| { | |
| 1192 | 1187 | walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait); |
| 1193 | 1188 | }); |
| 1194 | 1189 | } |
compiler/rustc_ast_passes/src/errors.rs+1-1| ... | ... | @@ -56,7 +56,7 @@ pub(crate) struct TraitFnConst { |
| 56 | 56 | pub make_impl_const_sugg: Option<Span>, |
| 57 | 57 | #[suggestion( |
| 58 | 58 | ast_passes_make_trait_const_sugg, |
| 59 | code = "#[const_trait]\n", | |
| 59 | code = "const ", | |
| 60 | 60 | applicability = "maybe-incorrect" |
| 61 | 61 | )] |
| 62 | 62 | 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; |
| 66 | 66 | impl<S: Stage> NoArgsAttributeParser<S> for TypeConstParser { |
| 67 | 67 | const PATH: &[Symbol] = &[sym::type_const]; |
| 68 | 68 | 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)]); | |
| 70 | 71 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst; |
| 71 | 72 | } |
| 72 | 73 | |
| ... | ... | @@ -101,17 +102,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser { |
| 101 | 102 | const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject; |
| 102 | 103 | } |
| 103 | 104 | |
| 104 | // FIXME(const_trait_impl): remove this | |
| 105 | // Const traits | |
| 106 | ||
| 107 | pub(crate) struct ConstTraitParser; | |
| 108 | impl<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 | ||
| 115 | 105 | // Specialization |
| 116 | 106 | |
| 117 | 107 | pub(crate) struct SpecializationTraitParser; |
compiler/rustc_attr_parsing/src/context.rs+1-2| ... | ... | @@ -64,7 +64,7 @@ use crate::attributes::stability::{ |
| 64 | 64 | }; |
| 65 | 65 | use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser}; |
| 66 | 66 | use crate::attributes::traits::{ |
| 67 | AllowIncoherentImplParser, CoinductiveParser, ConstTraitParser, DenyExplicitImplParser, | |
| 67 | AllowIncoherentImplParser, CoinductiveParser, DenyExplicitImplParser, | |
| 68 | 68 | DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, ParenSugarParser, |
| 69 | 69 | PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser, |
| 70 | 70 | UnsafeSpecializationMarkerParser, |
| ... | ... | @@ -218,7 +218,6 @@ attribute_parsers!( |
| 218 | 218 | Single<WithoutArgs<ColdParser>>, |
| 219 | 219 | Single<WithoutArgs<ConstContinueParser>>, |
| 220 | 220 | Single<WithoutArgs<ConstStabilityIndirectParser>>, |
| 221 | Single<WithoutArgs<ConstTraitParser>>, | |
| 222 | 221 | Single<WithoutArgs<CoroutineParser>>, |
| 223 | 222 | Single<WithoutArgs<DenyExplicitImplParser>>, |
| 224 | 223 | 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>( |
| 381 | 381 | `{trait_name}` is not const", |
| 382 | 382 | ), |
| 383 | 383 | ); |
| 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 | { | |
| 385 | 387 | if !ccx.tcx.features().const_trait_impl() { |
| 386 | 388 | err.help( |
| 387 | 389 | "add `#![feature(const_trait_impl)]` to the crate attributes to \ |
| 388 | enable `#[const_trait]`", | |
| 390 | enable const traits", | |
| 389 | 391 | ); |
| 390 | 392 | } |
| 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); | |
| 397 | 395 | err.span_suggestion_verbose( |
| 398 | trait_span.shrink_to_lo(), | |
| 396 | span.shrink_to_hi(), | |
| 399 | 397 | format!("consider making trait `{trait_name}` const"), |
| 400 | format!("#[const_trait]\n{indentation}"), | |
| 398 | "const ".to_owned(), | |
| 401 | 399 | Applicability::MaybeIncorrect, |
| 402 | 400 | ); |
| 403 | 401 | } 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] = &[ |
| 846 | 846 | EncodeCrossCrate::No, experimental!(register_tool), |
| 847 | 847 | ), |
| 848 | 848 | |
| 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 | ), | |
| 857 | 849 | // lang-team MCP 147 |
| 858 | 850 | gated!( |
| 859 | 851 | 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 { |
| 499 | 499 | /// Represents `#[rustc_const_stable_indirect]`. |
| 500 | 500 | ConstStabilityIndirect, |
| 501 | 501 | |
| 502 | /// Represents `#[const_trait]`. | |
| 503 | ConstTrait(Span), | |
| 504 | ||
| 505 | 502 | /// Represents `#[coroutine]`. |
| 506 | 503 | Coroutine(Span), |
| 507 | 504 |
compiler/rustc_hir/src/attrs/encode_cross_crate.rs-1| ... | ... | @@ -32,7 +32,6 @@ impl AttributeKind { |
| 32 | 32 | ConstContinue(..) => No, |
| 33 | 33 | ConstStability { .. } => Yes, |
| 34 | 34 | ConstStabilityIndirect => No, |
| 35 | ConstTrait(..) => No, | |
| 36 | 35 | Coroutine(..) => No, |
| 37 | 36 | Coverage(..) => No, |
| 38 | 37 | CrateName { .. } => No, |
compiler/rustc_hir/src/hir.rs+7-2| ... | ... | @@ -3065,7 +3065,7 @@ macro_rules! expect_methods_self_kind { |
| 3065 | 3065 | $( |
| 3066 | 3066 | #[track_caller] |
| 3067 | 3067 | 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) }; | |
| 3069 | 3069 | $ret_val |
| 3070 | 3070 | } |
| 3071 | 3071 | )* |
| ... | ... | @@ -3077,7 +3077,7 @@ macro_rules! expect_methods_self { |
| 3077 | 3077 | $( |
| 3078 | 3078 | #[track_caller] |
| 3079 | 3079 | 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) }; | |
| 3081 | 3081 | $ret_val |
| 3082 | 3082 | } |
| 3083 | 3083 | )* |
| ... | ... | @@ -4790,6 +4790,11 @@ impl<'hir> Node<'hir> { |
| 4790 | 4790 | ForeignItemKind::Static(ty, ..) => Some(ty), |
| 4791 | 4791 | _ => None, |
| 4792 | 4792 | }, |
| 4793 | Node::GenericParam(param) => match param.kind { | |
| 4794 | GenericParamKind::Lifetime { .. } => None, | |
| 4795 | GenericParamKind::Type { default, .. } => default, | |
| 4796 | GenericParamKind::Const { ty, .. } => Some(ty), | |
| 4797 | }, | |
| 4793 | 4798 | _ => None, |
| 4794 | 4799 | } |
| 4795 | 4800 | } |
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<(), |
| 757 | 757 | } |
| 758 | 758 | |
| 759 | 759 | match tcx.def_kind(def_id) { |
| 760 | def_kind @ (DefKind::Static { .. } | DefKind::Const) => { | |
| 760 | DefKind::Static { .. } => { | |
| 761 | 761 | tcx.ensure_ok().generics_of(def_id); |
| 762 | 762 | tcx.ensure_ok().type_of(def_id); |
| 763 | 763 | 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 | ||
| 776 | 772 | // Only `Node::Item` and `Node::ForeignItem` still have HIR based |
| 777 | 773 | // checks. Returning early here does not miss any checks and |
| 778 | 774 | // 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<(), |
| 900 | 896 | // avoids this query from having a direct dependency edge on the HIR |
| 901 | 897 | return res; |
| 902 | 898 | } |
| 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 | } | |
| 903 | 932 | DefKind::TyAlias => { |
| 904 | 933 | tcx.ensure_ok().generics_of(def_id); |
| 905 | 934 | tcx.ensure_ok().type_of(def_id); |
| ... | ... | @@ -920,6 +949,11 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), |
| 920 | 949 | })); |
| 921 | 950 | check_variances_for_type_defn(tcx, def_id); |
| 922 | 951 | } |
| 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; | |
| 923 | 957 | } |
| 924 | 958 | DefKind::ForeignMod => { |
| 925 | 959 | 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}; |
| 6 | 6 | use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; |
| 7 | 7 | use rustc_errors::codes::*; |
| 8 | 8 | use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err}; |
| 9 | use rustc_hir::attrs::AttributeKind; | |
| 9 | 10 | use rustc_hir::def::{DefKind, Res}; |
| 10 | 11 | use rustc_hir::intravisit::VisitorExt; |
| 11 | use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; | |
| 12 | use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, find_attr, intravisit}; | |
| 12 | 13 | use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt}; |
| 13 | 14 | use rustc_infer::traits::util; |
| 14 | 15 | use rustc_middle::ty::error::{ExpectedFound, TypeError}; |
| ... | ... | @@ -1984,12 +1985,46 @@ fn compare_impl_const<'tcx>( |
| 1984 | 1985 | trait_const_item: ty::AssocItem, |
| 1985 | 1986 | impl_trait_ref: ty::TraitRef<'tcx>, |
| 1986 | 1987 | ) -> Result<(), ErrorGuaranteed> { |
| 1988 | compare_type_const(tcx, impl_const_item, trait_const_item)?; | |
| 1987 | 1989 | compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?; |
| 1988 | 1990 | compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?; |
| 1989 | 1991 | check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?; |
| 1990 | 1992 | compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref) |
| 1991 | 1993 | } |
| 1992 | 1994 | |
| 1995 | fn 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 | ||
| 1993 | 2028 | /// The equivalent of [compare_method_predicate_entailment], but for associated constants |
| 1994 | 2029 | /// instead of associated functions. |
| 1995 | 2030 | // 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; |
| 6 | 6 | use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; |
| 7 | 7 | use rustc_errors::codes::*; |
| 8 | 8 | use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; |
| 9 | use rustc_hir::attrs::AttributeKind; | |
| 9 | 10 | use rustc_hir::def::{DefKind, Res}; |
| 10 | 11 | use rustc_hir::def_id::{DefId, LocalDefId}; |
| 11 | 12 | use rustc_hir::lang_items::LangItem; |
| 12 | use rustc_hir::{AmbigArg, ItemKind}; | |
| 13 | use rustc_hir::{AmbigArg, ItemKind, find_attr}; | |
| 13 | 14 | use rustc_infer::infer::outlives::env::OutlivesEnvironment; |
| 14 | 15 | use rustc_infer::infer::{self, InferCtxt, SubregionOrigin, TyCtxtInferExt}; |
| 15 | 16 | use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION; |
| ... | ... | @@ -925,11 +926,11 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er |
| 925 | 926 | #[instrument(level = "debug", skip(tcx))] |
| 926 | 927 | pub(crate) fn check_associated_item( |
| 927 | 928 | tcx: TyCtxt<'_>, |
| 928 | item_id: LocalDefId, | |
| 929 | def_id: LocalDefId, | |
| 929 | 930 | ) -> 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); | |
| 933 | 934 | |
| 934 | 935 | // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case |
| 935 | 936 | // other `Foo` impls are incoherent. |
| ... | ... | @@ -942,27 +943,36 @@ pub(crate) fn check_associated_item( |
| 942 | 943 | } |
| 943 | 944 | }; |
| 944 | 945 | |
| 945 | let span = tcx.def_span(item_id); | |
| 946 | let span = tcx.def_span(def_id); | |
| 946 | 947 | |
| 947 | 948 | match item.kind { |
| 948 | 949 | 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); | |
| 951 | 952 | 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 | ||
| 959 | 969 | Ok(()) |
| 960 | 970 | } |
| 961 | 971 | ty::AssocKind::Fn { .. } => { |
| 962 | let sig = tcx.fn_sig(item.def_id).instantiate_identity(); | |
| 972 | let sig = tcx.fn_sig(def_id).instantiate_identity(); | |
| 963 | 973 | 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); | |
| 966 | 976 | check_method_receiver(wfcx, hir_sig, item, self_ty) |
| 967 | 977 | } |
| 968 | 978 | ty::AssocKind::Type { .. } => { |
| ... | ... | @@ -970,8 +980,8 @@ pub(crate) fn check_associated_item( |
| 970 | 980 | check_associated_type_bounds(wfcx, item, span) |
| 971 | 981 | } |
| 972 | 982 | 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); | |
| 975 | 985 | wfcx.register_wf_obligation(span, loc, ty.into()); |
| 976 | 986 | } |
| 977 | 987 | Ok(()) |
| ... | ... | @@ -1222,28 +1232,36 @@ pub(crate) fn check_static_item<'tcx>( |
| 1222 | 1232 | }) |
| 1223 | 1233 | } |
| 1224 | 1234 | |
| 1225 | pub(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))] | |
| 1236 | pub(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); | |
| 1230 | 1244 | |
| 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 | ); | |
| 1242 | 1251 | |
| 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()); | |
| 1244 | 1256 | |
| 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(()) | |
| 1247 | 1265 | } |
| 1248 | 1266 | |
| 1249 | 1267 | #[instrument(level = "debug", skip(tcx, impl_))] |
| ... | ... | @@ -1583,33 +1601,16 @@ fn check_fn_or_method<'tcx>( |
| 1583 | 1601 | } |
| 1584 | 1602 | |
| 1585 | 1603 | // 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 | ||
| 1598 | fn 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(); | |
| 1606 | 1604 | 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 | }; | |
| 1608 | 1609 | |
| 1609 | 1610 | wfcx.register_bound( |
| 1610 | ObligationCause::new(span, def_id, code), | |
| 1611 | ObligationCause::new(span, def_id, ObligationCauseCode::SizedReturnType), | |
| 1611 | 1612 | wfcx.param_env, |
| 1612 | ty, | |
| 1613 | sig.output(), | |
| 1613 | 1614 | tcx.require_lang_item(LangItem::Sized, span), |
| 1614 | 1615 | ); |
| 1615 | 1616 | } |
compiler/rustc_hir_analysis/src/collect.rs+19-19| ... | ... | @@ -891,15 +891,6 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { |
| 891 | 891 | }; |
| 892 | 892 | |
| 893 | 893 | 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 | }; | |
| 903 | 894 | |
| 904 | 895 | let paren_sugar = find_attr!(attrs, AttributeKind::ParenSugar(_)); |
| 905 | 896 | if paren_sugar && !tcx.features().unboxed_closures() { |
| ... | ... | @@ -1382,22 +1373,27 @@ fn check_impl_constness( |
| 1382 | 1373 | } |
| 1383 | 1374 | |
| 1384 | 1375 | 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()), | |
| 1389 | 1384 | if tcx.features().const_trait_impl() { |
| 1390 | 1385 | "" |
| 1391 | 1386 | } else { |
| 1392 | 1387 | "enable `#![feature(const_trait_impl)]` in your crate and " |
| 1393 | 1388 | }, |
| 1394 | ), | |
| 1395 | (false, _) | (_, false) => (None, ""), | |
| 1396 | }; | |
| 1389 | ) | |
| 1390 | } | |
| 1391 | (None, _) | (_, false) => (None, ""), | |
| 1392 | }; | |
| 1397 | 1393 | tcx.dcx().emit_err(errors::ConstImplForNonConstTrait { |
| 1398 | 1394 | trait_ref_span: hir_trait_ref.path.span, |
| 1399 | 1395 | trait_name, |
| 1400 | local_trait_span, | |
| 1396 | suggestion, | |
| 1401 | 1397 | suggestion_pre, |
| 1402 | 1398 | marking: (), |
| 1403 | 1399 | adding: (), |
| ... | ... | @@ -1615,8 +1611,12 @@ fn const_of_item<'tcx>( |
| 1615 | 1611 | }; |
| 1616 | 1612 | let ct_arg = match ct_rhs { |
| 1617 | 1613 | 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)); | |
| 1620 | 1620 | } |
| 1621 | 1621 | }; |
| 1622 | 1622 | let icx = ItemCtxt::new(tcx, def_id); |
compiler/rustc_hir_analysis/src/errors.rs+4-14| ... | ... | @@ -500,13 +500,8 @@ pub(crate) struct ConstImplForNonConstTrait { |
| 500 | 500 | #[label] |
| 501 | 501 | pub trait_ref_span: Span, |
| 502 | 502 | 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>, | |
| 510 | 505 | pub suggestion_pre: &'static str, |
| 511 | 506 | #[note] |
| 512 | 507 | pub marking: (), |
| ... | ... | @@ -523,14 +518,9 @@ pub(crate) struct ConstBoundForNonConstTrait { |
| 523 | 518 | pub modifier: &'static str, |
| 524 | 519 | #[note] |
| 525 | 520 | 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")] | |
| 533 | 522 | pub suggestion: Option<Span>, |
| 523 | pub suggestion_pre: &'static str, | |
| 534 | 524 | pub trait_name: String, |
| 535 | 525 | } |
| 536 | 526 |
compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs+19-14| ... | ... | @@ -881,28 +881,33 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { |
| 881 | 881 | } |
| 882 | 882 | |
| 883 | 883 | 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) | |
| 885 | 885 | { |
| 886 | 886 | 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, ""), | |
| 898 | 903 | }; |
| 899 | 904 | self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait { |
| 900 | 905 | span, |
| 901 | 906 | modifier: constness.as_str(), |
| 902 | 907 | 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), | |
| 905 | 909 | suggestion, |
| 910 | suggestion_pre, | |
| 906 | 911 | }); |
| 907 | 912 | } else { |
| 908 | 913 | match predicate_filter { |
compiler/rustc_passes/src/check_attr.rs+1-14| ... | ... | @@ -150,9 +150,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 150 | 150 | Attribute::Parsed(AttributeKind::ProcMacroDerive { .. }) => { |
| 151 | 151 | self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) |
| 152 | 152 | } |
| 153 | &Attribute::Parsed(AttributeKind::TypeConst(attr_span)) => { | |
| 154 | self.check_type_const(hir_id, attr_span, target) | |
| 155 | } | |
| 156 | 153 | Attribute::Parsed( |
| 157 | 154 | AttributeKind::Stability { |
| 158 | 155 | span: attr_span, |
| ... | ... | @@ -235,7 +232,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 235 | 232 | | AttributeKind::Marker(..) |
| 236 | 233 | | AttributeKind::SkipDuringMethodDispatch { .. } |
| 237 | 234 | | AttributeKind::Coinductive(..) |
| 238 | | AttributeKind::ConstTrait(..) | |
| 239 | 235 | | AttributeKind::DenyExplicitImpl(..) |
| 240 | 236 | | AttributeKind::DoNotImplementViaObject(..) |
| 241 | 237 | | AttributeKind::SpecializationTrait(..) |
| ... | ... | @@ -243,6 +239,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 243 | 239 | | AttributeKind::ParenSugar(..) |
| 244 | 240 | | AttributeKind::AllowIncoherentImpl(..) |
| 245 | 241 | | AttributeKind::Confusables { .. } |
| 242 | | AttributeKind::TypeConst{..} | |
| 246 | 243 | // `#[doc]` is actually a lot more than just doc comments, so is checked below |
| 247 | 244 | | AttributeKind::DocComment {..} |
| 248 | 245 | // handled below this loop and elsewhere |
| ... | ... | @@ -2115,16 +2112,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 2115 | 2112 | } |
| 2116 | 2113 | } |
| 2117 | 2114 | |
| 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 | ||
| 2128 | 2115 | fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) { |
| 2129 | 2116 | if !find_attr!(attrs, AttributeKind::Repr { reprs, .. } => reprs.iter().any(|(r, _)| r == &ReprAttr::ReprTransparent)) |
| 2130 | 2117 | .unwrap_or(false) |
compiler/rustc_span/src/symbol.rs-1| ... | ... | @@ -750,7 +750,6 @@ symbols! { |
| 750 | 750 | const_raw_ptr_to_usize_cast, |
| 751 | 751 | const_refs_to_cell, |
| 752 | 752 | const_refs_to_static, |
| 753 | const_trait, | |
| 754 | 753 | const_trait_bound_opt_out, |
| 755 | 754 | const_trait_impl, |
| 756 | 755 | 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> { |
| 1286 | 1286 | ty: Ty<'tcx>, |
| 1287 | 1287 | obligation: &PredicateObligation<'tcx>, |
| 1288 | 1288 | ) -> 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); | |
| 1295 | 1291 | |
| 1296 | 1292 | let mut file = None; |
| 1297 | 1293 | let ty_str = self.tcx.short_string(ty, &mut file); |
library/core/src/array/equality.rs+1-2| ... | ... | @@ -132,9 +132,8 @@ where |
| 132 | 132 | #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] |
| 133 | 133 | impl<T: [const] Eq, const N: usize> const Eq for [T; N] {} |
| 134 | 134 | |
| 135 | #[const_trait] | |
| 136 | 135 | #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] |
| 137 | trait SpecArrayEq<Other, const N: usize>: Sized { | |
| 136 | const trait SpecArrayEq<Other, const N: usize>: Sized { | |
| 138 | 137 | fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool; |
| 139 | 138 | fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool; |
| 140 | 139 | } |
library/core/src/cmp/bytewise.rs+1-2| ... | ... | @@ -17,8 +17,7 @@ use crate::num::NonZero; |
| 17 | 17 | /// - Neither `Self` nor `Rhs` have provenance, so integer comparisons are correct. |
| 18 | 18 | /// - `<Self as PartialEq<Rhs>>::{eq,ne}` are equivalent to comparing the bytes. |
| 19 | 19 | #[rustc_specialization_trait] |
| 20 | #[const_trait] // FIXME(const_trait_impl): Migrate to `const unsafe trait` once #146122 is fixed. | |
| 21 | pub(crate) unsafe trait BytewiseEq<Rhs = Self>: | |
| 20 | pub(crate) const unsafe trait BytewiseEq<Rhs = Self>: | |
| 22 | 21 | [const] PartialEq<Rhs> + Sized |
| 23 | 22 | { |
| 24 | 23 | } |
library/core/src/ops/range.rs+3-6| ... | ... | @@ -816,9 +816,8 @@ impl<T: Clone> Bound<&T> { |
| 816 | 816 | /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. |
| 817 | 817 | #[stable(feature = "collections_range", since = "1.28.0")] |
| 818 | 818 | #[rustc_diagnostic_item = "RangeBounds"] |
| 819 | #[const_trait] | |
| 820 | 819 | #[rustc_const_unstable(feature = "const_range", issue = "none")] |
| 821 | pub trait RangeBounds<T: ?Sized> { | |
| 820 | pub const trait RangeBounds<T: ?Sized> { | |
| 822 | 821 | /// Start index bound. |
| 823 | 822 | /// |
| 824 | 823 | /// Returns the start value as a `Bound`. |
| ... | ... | @@ -954,9 +953,8 @@ pub trait RangeBounds<T: ?Sized> { |
| 954 | 953 | /// `IntoBounds` is implemented by Rust’s built-in range types, produced |
| 955 | 954 | /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. |
| 956 | 955 | #[unstable(feature = "range_into_bounds", issue = "136903")] |
| 957 | #[const_trait] | |
| 958 | 956 | #[rustc_const_unstable(feature = "const_range", issue = "none")] |
| 959 | pub trait IntoBounds<T>: [const] RangeBounds<T> { | |
| 957 | pub const trait IntoBounds<T>: [const] RangeBounds<T> { | |
| 960 | 958 | /// Convert this range into the start and end bounds. |
| 961 | 959 | /// Returns `(start_bound, end_bound)`. |
| 962 | 960 | /// |
| ... | ... | @@ -1319,9 +1317,8 @@ pub enum OneSidedRangeBound { |
| 1319 | 1317 | /// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded` |
| 1320 | 1318 | /// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`. |
| 1321 | 1319 | #[unstable(feature = "one_sided_range", issue = "69780")] |
| 1322 | #[const_trait] | |
| 1323 | 1320 | #[rustc_const_unstable(feature = "const_range", issue = "none")] |
| 1324 | pub trait OneSidedRange<T>: RangeBounds<T> { | |
| 1321 | pub const trait OneSidedRange<T>: RangeBounds<T> { | |
| 1325 | 1322 | /// An internal-only helper function for `split_off` and |
| 1326 | 1323 | /// `split_off_mut` that returns the bound of the one-sided range. |
| 1327 | 1324 | fn bound(self) -> (OneSidedRangeBound, T); |
library/core/src/slice/cmp.rs+5-10| ... | ... | @@ -155,18 +155,16 @@ where |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | 157 | #[doc(hidden)] |
| 158 | #[const_trait] | |
| 159 | 158 | #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] |
| 160 | 159 | // intermediate trait for specialization of slice's PartialOrd |
| 161 | trait SlicePartialOrd: Sized { | |
| 160 | const trait SlicePartialOrd: Sized { | |
| 162 | 161 | fn partial_compare(left: &[Self], right: &[Self]) -> Option<Ordering>; |
| 163 | 162 | } |
| 164 | 163 | |
| 165 | 164 | #[doc(hidden)] |
| 166 | #[const_trait] | |
| 167 | 165 | #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] |
| 168 | 166 | // intermediate trait for specialization of slice's PartialOrd chaining methods |
| 169 | trait SliceChain: Sized { | |
| 167 | const trait SliceChain: Sized { | |
| 170 | 168 | fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow<bool>; |
| 171 | 169 | fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow<bool>; |
| 172 | 170 | fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow<bool>; |
| ... | ... | @@ -244,9 +242,8 @@ impl<A: [const] AlwaysApplicableOrd> const SlicePartialOrd for A { |
| 244 | 242 | } |
| 245 | 243 | |
| 246 | 244 | #[rustc_specialization_trait] |
| 247 | #[const_trait] | |
| 248 | 245 | #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] |
| 249 | trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {} | |
| 246 | const trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {} | |
| 250 | 247 | |
| 251 | 248 | macro_rules! always_applicable_ord { |
| 252 | 249 | ($([$($p:tt)*] $t:ty,)*) => { |
| ... | ... | @@ -265,10 +262,9 @@ always_applicable_ord! { |
| 265 | 262 | } |
| 266 | 263 | |
| 267 | 264 | #[doc(hidden)] |
| 268 | #[const_trait] | |
| 269 | 265 | #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] |
| 270 | 266 | // intermediate trait for specialization of slice's Ord |
| 271 | trait SliceOrd: Sized { | |
| 267 | const trait SliceOrd: Sized { | |
| 272 | 268 | fn compare(left: &[Self], right: &[Self]) -> Ordering; |
| 273 | 269 | } |
| 274 | 270 | |
| ... | ... | @@ -292,8 +288,7 @@ impl<A: Ord> SliceOrd for A { |
| 292 | 288 | /// * For every `x` and `y` of this type, `Ord(x, y)` must return the same |
| 293 | 289 | /// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`. |
| 294 | 290 | #[rustc_specialization_trait] |
| 295 | #[const_trait] | |
| 296 | unsafe trait UnsignedBytewiseOrd: [const] Ord {} | |
| 291 | const unsafe trait UnsignedBytewiseOrd: [const] Ord {} | |
| 297 | 292 | |
| 298 | 293 | #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] |
| 299 | 294 | unsafe impl const UnsignedBytewiseOrd for bool {} |
library/core/src/slice/index.rs+1-2| ... | ... | @@ -159,9 +159,8 @@ mod private_slice_index { |
| 159 | 159 | message = "the type `{T}` cannot be indexed by `{Self}`", |
| 160 | 160 | label = "slice indices are of type `usize` or ranges of `usize`" |
| 161 | 161 | )] |
| 162 | #[const_trait] // FIXME(const_trait_impl): Migrate to `const unsafe trait` once #146122 is fixed. | |
| 163 | 162 | #[rustc_const_unstable(feature = "const_index", issue = "143775")] |
| 164 | pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed { | |
| 163 | pub const unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed { | |
| 165 | 164 | /// The output type returned by methods. |
| 166 | 165 | #[stable(feature = "slice_get_slice", since = "1.28.0")] |
| 167 | 166 | type Output: ?Sized; |
library/std/src/panicking.rs+7-15| ... | ... | @@ -22,7 +22,7 @@ use crate::io::try_set_output_capture; |
| 22 | 22 | use crate::mem::{self, ManuallyDrop}; |
| 23 | 23 | use crate::panic::{BacktraceStyle, PanicHookInfo}; |
| 24 | 24 | use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; |
| 25 | use crate::sync::{PoisonError, RwLock}; | |
| 25 | use crate::sync::nonpoison::RwLock; | |
| 26 | 26 | use crate::sys::backtrace; |
| 27 | 27 | use crate::sys::stdio::panic_output; |
| 28 | 28 | use crate::{fmt, intrinsics, process, thread}; |
| ... | ... | @@ -144,13 +144,9 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicHookInfo<'_>) + 'static + Sync + Send>) { |
| 144 | 144 | panic!("cannot modify the panic hook from a panicking thread"); |
| 145 | 145 | } |
| 146 | 146 | |
| 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))); | |
| 154 | 150 | } |
| 155 | 151 | |
| 156 | 152 | /// 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> { |
| 188 | 184 | panic!("cannot modify the panic hook from a panicking thread"); |
| 189 | 185 | } |
| 190 | 186 | |
| 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() | |
| 196 | 188 | } |
| 197 | 189 | |
| 198 | 190 | /// Atomic combination of [`take_hook`] and [`set_hook`]. Use this to replace the panic handler with |
| ... | ... | @@ -238,7 +230,7 @@ where |
| 238 | 230 | panic!("cannot modify the panic hook from a panicking thread"); |
| 239 | 231 | } |
| 240 | 232 | |
| 241 | let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner); | |
| 233 | let mut hook = HOOK.write(); | |
| 242 | 234 | let prev = mem::take(&mut *hook).into_box(); |
| 243 | 235 | *hook = Hook::Custom(Box::new(move |info| hook_fn(&prev, info))); |
| 244 | 236 | } |
| ... | ... | @@ -822,7 +814,7 @@ fn panic_with_hook( |
| 822 | 814 | crate::process::abort(); |
| 823 | 815 | } |
| 824 | 816 | |
| 825 | match *HOOK.read().unwrap_or_else(PoisonError::into_inner) { | |
| 817 | match *HOOK.read() { | |
| 826 | 818 | // Some platforms (like wasm) know that printing to stderr won't ever actually |
| 827 | 819 | // print anything, and if that's the case we can skip the default |
| 828 | 820 | // hook. Since string formatting happens lazily when calling `payload` |
src/bootstrap/src/utils/helpers.rs+1| ... | ... | @@ -430,6 +430,7 @@ pub fn linker_flags( |
| 430 | 430 | match builder.config.bootstrap_override_lld { |
| 431 | 431 | BootstrapOverrideLld::External => { |
| 432 | 432 | args.push("-Clinker-features=+lld".to_string()); |
| 433 | args.push("-Clink-self-contained=-linker".to_string()); | |
| 433 | 434 | args.push("-Zunstable-options".to_string()); |
| 434 | 435 | } |
| 435 | 436 | BootstrapOverrideLld::SelfContained => { |
src/bootstrap/src/utils/render_tests.rs+19| ... | ... | @@ -306,6 +306,14 @@ impl<'a> Renderer<'a> { |
| 306 | 306 | ); |
| 307 | 307 | } |
| 308 | 308 | |
| 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 | ||
| 309 | 317 | fn render_message(&mut self, message: Message) { |
| 310 | 318 | match message { |
| 311 | 319 | Message::Suite(SuiteMessage::Started { test_count }) => { |
| ... | ... | @@ -323,6 +331,9 @@ impl<'a> Renderer<'a> { |
| 323 | 331 | Message::Suite(SuiteMessage::Failed(outcome)) => { |
| 324 | 332 | self.render_suite_outcome(Outcome::Failed, &outcome); |
| 325 | 333 | } |
| 334 | Message::Report(report) => { | |
| 335 | self.render_report(&report); | |
| 336 | } | |
| 326 | 337 | Message::Bench(outcome) => { |
| 327 | 338 | // The formatting for benchmarks doesn't replicate 1:1 the formatting libtest |
| 328 | 339 | // outputs, mostly because libtest's formatting is broken in terse mode, which is |
| ... | ... | @@ -435,6 +446,7 @@ enum Message { |
| 435 | 446 | Suite(SuiteMessage), |
| 436 | 447 | Test(TestMessage), |
| 437 | 448 | Bench(BenchOutcome), |
| 449 | Report(Report), | |
| 438 | 450 | } |
| 439 | 451 | |
| 440 | 452 | #[derive(serde_derive::Deserialize)] |
| ... | ... | @@ -481,3 +493,10 @@ struct TestOutcome { |
| 481 | 493 | stdout: Option<String>, |
| 482 | 494 | message: Option<String>, |
| 483 | 495 | } |
| 496 | ||
| 497 | /// Emitted when running doctests. | |
| 498 | #[derive(serde_derive::Deserialize)] | |
| 499 | struct 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 |
| 993 | 993 | [clang-kcfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-kcfi |
| 994 | 994 | [clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html |
| 995 | 995 | [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 | |
| 997 | 997 | [clang-safestack]: https://clang.llvm.org/docs/SafeStack.html |
| 998 | 998 | [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html |
| 999 | 999 | [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() { |
| 52 | 52 | println!(); |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | fn 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 | ||
| 67 | 55 | pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) { |
| 68 | 56 | // Require a subcommand before any flags. |
| 69 | 57 | // We cannot know which of those flags take arguments and which do not, |
| ... | ... | @@ -276,7 +264,7 @@ pub enum RustcPhase { |
| 276 | 264 | Rustdoc, |
| 277 | 265 | } |
| 278 | 266 | |
| 279 | pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) { | |
| 267 | pub fn phase_rustc(args: impl Iterator<Item = String>, phase: RustcPhase) { | |
| 280 | 268 | /// Determines if we are being invoked (as rustc) to build a crate for |
| 281 | 269 | /// the "target" architecture, in contrast to the "host" architecture. |
| 282 | 270 | /// 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) { |
| 444 | 432 | } |
| 445 | 433 | |
| 446 | 434 | let mut cmd = miri(); |
| 447 | let mut emit_link_hack = false; | |
| 448 | 435 | // Arguments are treated very differently depending on whether this crate is |
| 449 | 436 | // for interpretation by Miri, or for use by a build script / proc macro. |
| 450 | 437 | if target_crate { |
| ... | ... | @@ -455,7 +442,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) { |
| 455 | 442 | } |
| 456 | 443 | |
| 457 | 444 | // Forward arguments, but patched. |
| 458 | let emit_flag = "--emit"; | |
| 445 | ||
| 459 | 446 | // This hack helps bootstrap run standard library tests in Miri. The issue is as follows: |
| 460 | 447 | // when running `cargo miri test` on libcore, cargo builds a local copy of core and makes it |
| 461 | 448 | // 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) { |
| 471 | 458 | let replace_librs = env::var_os("MIRI_REPLACE_LIBRS_IF_NOT_TEST").is_some() |
| 472 | 459 | && !runnable_crate |
| 473 | 460 | && 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 { | |
| 498 | 462 | // If the REPLACE_LIBRS hack is enabled and we are building a `lib.rs` file, and a |
| 499 | 463 | // `lib.miri.rs` file exists, then build that instead. |
| 500 | 464 | if replace_librs { |
| ... | ... | @@ -543,17 +507,6 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) { |
| 543 | 507 | eprintln!("[cargo-miri rustc] target_crate={target_crate} runnable_crate={runnable_crate}"); |
| 544 | 508 | } |
| 545 | 509 | |
| 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 | ||
| 557 | 510 | debug_cmd("[cargo-miri rustc]", verbose, &cmd); |
| 558 | 511 | exec(cmd); |
| 559 | 512 | } |
| ... | ... | @@ -624,17 +577,11 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner |
| 624 | 577 | cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap()); |
| 625 | 578 | } |
| 626 | 579 | // 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, | |
| 631 | 581 | // but when we run here, cargo does not interpret the JSON any more. `--json` |
| 632 | 582 | // 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") { | |
| 638 | 585 | assert!(suffix.starts_with('=')); |
| 639 | 586 | // Drop this argument. |
| 640 | 587 | } 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 |
| 668 | 615 | } |
| 669 | 616 | } |
| 670 | 617 | |
| 671 | pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) { | |
| 618 | pub fn phase_rustdoc(args: impl Iterator<Item = String>) { | |
| 672 | 619 | let verbose = env::var("MIRI_VERBOSE") |
| 673 | 620 | .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer")); |
| 674 | 621 | |
| ... | ... | @@ -676,15 +623,7 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) { |
| 676 | 623 | // of the old value into MIRI_ORIG_RUSTDOC. So that's what we have to invoke now. |
| 677 | 624 | let rustdoc = env::var("MIRI_ORIG_RUSTDOC").unwrap_or("rustdoc".to_string()); |
| 678 | 625 | 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); | |
| 688 | 627 | |
| 689 | 628 | // Doctests of `proc-macro` crates (and their dependencies) are always built for the host, |
| 690 | 629 | // 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( |
| 160 | 160 | |
| 161 | 161 | // Do the build. |
| 162 | 162 | 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 | |
| 164 | 164 | .rustc_version(rustc_version.clone()) |
| 165 | 165 | .sysroot_config(sysroot_config) |
| 166 | 166 | .rustflags(rustflags) |
src/tools/miri/miri-script/src/commands.rs+9-7| ... | ... | @@ -57,7 +57,9 @@ impl MiriEnv { |
| 57 | 57 | .arg("--") |
| 58 | 58 | .args(&["miri", "setup", "--print-sysroot"]) |
| 59 | 59 | .args(target_flag); |
| 60 | cmd.set_quiet(quiet); | |
| 60 | if quiet { | |
| 61 | cmd = cmd.arg("--quiet"); | |
| 62 | } | |
| 61 | 63 | let output = cmd.read()?; |
| 62 | 64 | self.sh.set_var("MIRI_SYSROOT", &output); |
| 63 | 65 | Ok(output.into()) |
| ... | ... | @@ -112,8 +114,8 @@ impl Command { |
| 112 | 114 | Command::Check { features, flags } => Self::check(features, flags), |
| 113 | 115 | Command::Test { bless, target, coverage, features, flags } => |
| 114 | 116 | 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), | |
| 117 | 119 | Command::Doc { features, flags } => Self::doc(features, flags), |
| 118 | 120 | Command::Fmt { flags } => Self::fmt(flags), |
| 119 | 121 | Command::Clippy { features, flags } => Self::clippy(features, flags), |
| ... | ... | @@ -458,7 +460,7 @@ impl Command { |
| 458 | 460 | |
| 459 | 461 | fn run( |
| 460 | 462 | dep: bool, |
| 461 | verbose: bool, | |
| 463 | quiet: bool, | |
| 462 | 464 | target: Option<String>, |
| 463 | 465 | edition: Option<String>, |
| 464 | 466 | features: Vec<String>, |
| ... | ... | @@ -468,7 +470,7 @@ impl Command { |
| 468 | 470 | |
| 469 | 471 | // Preparation: get a sysroot, and get the miri binary. |
| 470 | 472 | 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)?; | |
| 472 | 474 | let miri_bin = e |
| 473 | 475 | .build_get_binary(".", &features) |
| 474 | 476 | .context("failed to get filename of miri executable")?; |
| ... | ... | @@ -492,7 +494,7 @@ impl Command { |
| 492 | 494 | // Compute flags. |
| 493 | 495 | let miri_flags = e.sh.var("MIRIFLAGS").unwrap_or_default(); |
| 494 | 496 | 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 }; | |
| 496 | 498 | |
| 497 | 499 | // Run Miri. |
| 498 | 500 | // The basic command that executes the Miri driver. |
| ... | ... | @@ -506,7 +508,7 @@ impl Command { |
| 506 | 508 | } else { |
| 507 | 509 | cmd!(e.sh, "{miri_bin}") |
| 508 | 510 | }; |
| 509 | cmd.set_quiet(!verbose); | |
| 511 | cmd.set_quiet(quiet); | |
| 510 | 512 | // Add Miri flags |
| 511 | 513 | let mut cmd = cmd.args(&miri_flags).args(&early_flags).args(&flags); |
| 512 | 514 | // 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 { |
| 78 | 78 | /// Build the program with the dependencies declared in `tests/deps/Cargo.toml`. |
| 79 | 79 | #[arg(long)] |
| 80 | 80 | dep: bool, |
| 81 | /// Show build progress. | |
| 81 | /// Hide build progress. | |
| 82 | 82 | #[arg(long, short)] |
| 83 | verbose: bool, | |
| 83 | quiet: bool, | |
| 84 | 84 | /// The cross-interpretation target. |
| 85 | 85 | #[arg(long)] |
| 86 | 86 | target: Option<String>, |
src/tools/miri/rust-version+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | 5f9dd05862d2e4bceb3be1031b6c936e35671501 | |
| 1 | ceb7df7e6f17c92c7d49f7e4f02df0e68bc9b38b |
src/tools/miri/src/bin/miri.rs+17-23| ... | ... | @@ -16,7 +16,6 @@ extern crate rustc_hir; |
| 16 | 16 | extern crate rustc_hir_analysis; |
| 17 | 17 | extern crate rustc_interface; |
| 18 | 18 | extern crate rustc_log; |
| 19 | extern crate rustc_metadata; | |
| 20 | 19 | extern crate rustc_middle; |
| 21 | 20 | extern crate rustc_session; |
| 22 | 21 | extern crate rustc_span; |
| ... | ... | @@ -26,10 +25,8 @@ mod log; |
| 26 | 25 | use std::env; |
| 27 | 26 | use std::num::NonZero; |
| 28 | 27 | use std::ops::Range; |
| 29 | use std::path::PathBuf; | |
| 30 | 28 | use std::rc::Rc; |
| 31 | 29 | use std::str::FromStr; |
| 32 | use std::sync::Arc; | |
| 33 | 30 | use std::sync::atomic::{AtomicI32, AtomicU32, Ordering}; |
| 34 | 31 | |
| 35 | 32 | use miri::{ |
| ... | ... | @@ -51,10 +48,8 @@ use rustc_middle::middle::exported_symbols::{ |
| 51 | 48 | use rustc_middle::query::LocalCrate; |
| 52 | 49 | use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; |
| 53 | 50 | use rustc_middle::ty::{self, Ty, TyCtxt}; |
| 54 | use rustc_middle::util::Providers; | |
| 55 | 51 | use rustc_session::EarlyDiagCtxt; |
| 56 | 52 | use rustc_session::config::{CrateType, ErrorOutputType, OptLevel}; |
| 57 | use rustc_session::search_paths::PathKind; | |
| 58 | 53 | use rustc_span::def_id::DefId; |
| 59 | 54 | |
| 60 | 55 | use crate::log::setup::{deinit_loggers, init_early_loggers, init_late_loggers}; |
| ... | ... | @@ -126,21 +121,6 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) { |
| 126 | 121 | } |
| 127 | 122 | |
| 128 | 123 | impl 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 | ||
| 144 | 124 | fn after_analysis<'tcx>( |
| 145 | 125 | &mut self, |
| 146 | 126 | _: &rustc_interface::interface::Compiler, |
| ... | ... | @@ -253,12 +233,26 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls { |
| 253 | 233 | #[allow(rustc::potential_query_instability)] // rustc_codegen_ssa (where this code is copied from) also allows this lint |
| 254 | 234 | fn config(&mut self, config: &mut Config) { |
| 255 | 235 | 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 | ||
| 256 | 251 | // Queries overridden here affect the data stored in `rmeta` files of dependencies, |
| 257 | 252 | // which will be used later in non-`MIRI_BE_RUSTC` mode. |
| 258 | 253 | 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. | |
| 262 | 256 | local_providers.exported_non_generic_symbols = |tcx, LocalCrate| { |
| 263 | 257 | let reachable_set = tcx.with_stable_hashing_context(|hcx| { |
| 264 | 258 | tcx.reachable_set(()).to_sorted(&hcx, true) |
src/tools/miri/src/borrow_tracker/mod.rs+16-9| ... | ... | @@ -11,6 +11,22 @@ use crate::*; |
| 11 | 11 | pub mod stacked_borrows; |
| 12 | 12 | pub mod tree_borrows; |
| 13 | 13 | |
| 14 | /// Indicates which kind of access is being performed. | |
| 15 | #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] | |
| 16 | pub enum AccessKind { | |
| 17 | Read, | |
| 18 | Write, | |
| 19 | } | |
| 20 | ||
| 21 | impl 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 | ||
| 14 | 30 | /// Tracking pointer provenance |
| 15 | 31 | #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] |
| 16 | 32 | pub struct BorTag(NonZero<u64>); |
| ... | ... | @@ -115,15 +131,6 @@ impl VisitProvenance for GlobalStateInner { |
| 115 | 131 | /// We need interior mutable access to the global state. |
| 116 | 132 | pub type GlobalState = RefCell<GlobalStateInner>; |
| 117 | 133 | |
| 118 | impl 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 | ||
| 127 | 134 | /// Policy on whether to recurse into fields to retag |
| 128 | 135 | #[derive(Copy, Clone, Debug)] |
| 129 | 136 | pub enum RetagFields { |
src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs+1-1| ... | ... | @@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashSet; |
| 5 | 5 | use rustc_span::{Span, SpanData}; |
| 6 | 6 | use smallvec::SmallVec; |
| 7 | 7 | |
| 8 | use crate::borrow_tracker::{GlobalStateInner, ProtectorKind}; | |
| 8 | use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind}; | |
| 9 | 9 | use crate::*; |
| 10 | 10 | |
| 11 | 11 | /// Error reporting |
src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs+1-1| ... | ... | @@ -21,7 +21,7 @@ pub use self::stack::Stack; |
| 21 | 21 | use crate::borrow_tracker::stacked_borrows::diagnostics::{ |
| 22 | 22 | AllocHistory, DiagnosticCx, DiagnosticCxBuilder, |
| 23 | 23 | }; |
| 24 | use crate::borrow_tracker::{GlobalStateInner, ProtectorKind}; | |
| 24 | use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind}; | |
| 25 | 25 | use crate::concurrency::data_race::{NaReadType, NaWriteType}; |
| 26 | 26 | use crate::*; |
| 27 | 27 |
src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs+1-1| ... | ... | @@ -4,10 +4,10 @@ use std::ops::Range; |
| 4 | 4 | use rustc_data_structures::fx::FxHashMap; |
| 5 | 5 | use rustc_span::{Span, SpanData}; |
| 6 | 6 | |
| 7 | use crate::borrow_tracker::ProtectorKind; | |
| 8 | 7 | use crate::borrow_tracker::tree_borrows::perms::{PermTransition, Permission}; |
| 9 | 8 | use crate::borrow_tracker::tree_borrows::tree::LocationState; |
| 10 | 9 | use crate::borrow_tracker::tree_borrows::unimap::UniIndex; |
| 10 | use crate::borrow_tracker::{AccessKind, ProtectorKind}; | |
| 11 | 11 | use crate::*; |
| 12 | 12 | |
| 13 | 13 | /// 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}; |
| 5 | 5 | |
| 6 | 6 | use self::foreign_access_skipping::IdempotentForeignAccess; |
| 7 | 7 | use self::tree::LocationState; |
| 8 | use crate::borrow_tracker::{GlobalState, GlobalStateInner, ProtectorKind}; | |
| 8 | use crate::borrow_tracker::{AccessKind, GlobalState, GlobalStateInner, ProtectorKind}; | |
| 9 | 9 | use crate::concurrency::data_race::NaReadType; |
| 10 | 10 | use crate::*; |
| 11 | 11 |
src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | use std::cmp::{Ordering, PartialOrd}; |
| 2 | 2 | use std::fmt; |
| 3 | 3 | |
| 4 | use crate::AccessKind; | |
| 4 | use crate::borrow_tracker::AccessKind; | |
| 5 | 5 | use crate::borrow_tracker::tree_borrows::diagnostics::TransitionError; |
| 6 | 6 | use crate::borrow_tracker::tree_borrows::tree::AccessRelatedness; |
| 7 | 7 |
src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs+1-1| ... | ... | @@ -25,7 +25,7 @@ use crate::borrow_tracker::tree_borrows::diagnostics::{ |
| 25 | 25 | use crate::borrow_tracker::tree_borrows::foreign_access_skipping::IdempotentForeignAccess; |
| 26 | 26 | use crate::borrow_tracker::tree_borrows::perms::PermTransition; |
| 27 | 27 | use crate::borrow_tracker::tree_borrows::unimap::{UniIndex, UniKeyMap, UniValMap}; |
| 28 | use crate::borrow_tracker::{GlobalState, ProtectorKind}; | |
| 28 | use crate::borrow_tracker::{AccessKind, GlobalState, ProtectorKind}; | |
| 29 | 29 | use crate::*; |
| 30 | 30 | |
| 31 | 31 | mod tests; |
src/tools/miri/src/concurrency/init_once.rs+4| ... | ... | @@ -57,6 +57,10 @@ impl InitOnceRef { |
| 57 | 57 | pub fn begin(&self) { |
| 58 | 58 | self.0.borrow_mut().begin(); |
| 59 | 59 | } |
| 60 | ||
| 61 | pub fn queue_is_empty(&self) -> bool { | |
| 62 | self.0.borrow().waiters.is_empty() | |
| 63 | } | |
| 60 | 64 | } |
| 61 | 65 | |
| 62 | 66 | impl VisitProvenance for InitOnceRef { |
src/tools/miri/src/concurrency/sync.rs+156-85| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | use std::any::Any; | |
| 1 | 2 | use std::cell::RefCell; |
| 2 | 3 | use std::collections::VecDeque; |
| 3 | 4 | use std::collections::hash_map::Entry; |
| ... | ... | @@ -5,6 +6,7 @@ use std::default::Default; |
| 5 | 6 | use std::ops::Not; |
| 6 | 7 | use std::rc::Rc; |
| 7 | 8 | use std::time::Duration; |
| 9 | use std::{fmt, iter}; | |
| 8 | 10 | |
| 9 | 11 | use rustc_abi::Size; |
| 10 | 12 | use rustc_data_structures::fx::FxHashMap; |
| ... | ... | @@ -12,6 +14,52 @@ use rustc_data_structures::fx::FxHashMap; |
| 12 | 14 | use super::vector_clock::VClock; |
| 13 | 15 | use crate::*; |
| 14 | 16 | |
| 17 | /// Indicates which kind of access is being performed. | |
| 18 | #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] | |
| 19 | pub enum AccessKind { | |
| 20 | Read, | |
| 21 | Write, | |
| 22 | Dealloc, | |
| 23 | } | |
| 24 | ||
| 25 | impl 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. | |
| 36 | pub 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 | ||
| 49 | impl 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 | ||
| 57 | impl 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 | ||
| 15 | 63 | /// The mutex state. |
| 16 | 64 | #[derive(Default, Debug)] |
| 17 | 65 | struct Mutex { |
| ... | ... | @@ -37,6 +85,10 @@ impl MutexRef { |
| 37 | 85 | pub fn owner(&self) -> Option<ThreadId> { |
| 38 | 86 | self.0.borrow().owner |
| 39 | 87 | } |
| 88 | ||
| 89 | pub fn queue_is_empty(&self) -> bool { | |
| 90 | self.0.borrow().queue.is_empty() | |
| 91 | } | |
| 40 | 92 | } |
| 41 | 93 | |
| 42 | 94 | impl VisitProvenance for MutexRef { |
| ... | ... | @@ -113,6 +165,11 @@ impl RwLockRef { |
| 113 | 165 | pub fn is_write_locked(&self) -> bool { |
| 114 | 166 | self.0.borrow().is_write_locked() |
| 115 | 167 | } |
| 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 | } | |
| 116 | 173 | } |
| 117 | 174 | |
| 118 | 175 | impl VisitProvenance for RwLockRef { |
| ... | ... | @@ -140,8 +197,8 @@ impl CondvarRef { |
| 140 | 197 | Self(Default::default()) |
| 141 | 198 | } |
| 142 | 199 | |
| 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() | |
| 145 | 202 | } |
| 146 | 203 | } |
| 147 | 204 | |
| ... | ... | @@ -214,127 +271,141 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 214 | 271 | |
| 215 | 272 | impl<'tcx> AllocExtra<'tcx> { |
| 216 | 273 | 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>()) | |
| 218 | 275 | } |
| 219 | 276 | } |
| 220 | 277 | |
| 221 | /// We designate an `init`` field in all primitives. | |
| 222 | /// If `init` is set to this, we consider the primitive initialized. | |
| 223 | pub 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 | |
| 226 | 279 | // cases, the function calls are infallible and it is the client's (shim |
| 227 | 280 | // implementation's) responsibility to detect and deal with erroneous |
| 228 | 281 | // situations. |
| 229 | 282 | impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} |
| 230 | 283 | pub 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>( | |
| 235 | 289 | &'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> | |
| 240 | 293 | where |
| 241 | 294 | 'tcx: 'a, |
| 242 | 295 | { |
| 243 | 296 | 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 | } | |
| 244 | 313 | |
| 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. | |
| 263 | 321 | /// |
| 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>( | |
| 266 | 331 | &'a mut self, |
| 267 | primitive: &MPlaceTy<'tcx>, | |
| 332 | obj: &MPlaceTy<'tcx>, | |
| 268 | 333 | 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>, | |
| 271 | 337 | ) -> InterpResult<'tcx, &'a T> |
| 272 | 338 | where |
| 273 | 339 | 'tcx: 'a, |
| 274 | 340 | { |
| 341 | assert!(init_val != uninit_val); | |
| 275 | 342 | 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 | } | |
| 276 | 354 | |
| 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 | |
| 283 | 358 | .atomic_compare_exchange_scalar( |
| 284 | 359 | &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), | |
| 287 | 362 | AtomicRwOrd::Relaxed, |
| 288 | 363 | AtomicReadOrd::Relaxed, |
| 289 | 364 | /* can_fail_spuriously */ false, |
| 290 | 365 | )? |
| 291 | 366 | .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 | ); | |
| 307 | 374 | } |
| 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()) | |
| 308 | 380 | } |
| 309 | 381 | |
| 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>( | |
| 315 | 385 | &'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>> | |
| 319 | 391 | where |
| 320 | 392 | 'tcx: 'a, |
| 321 | 393 | { |
| 322 | 394 | 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())) | |
| 338 | 409 | } |
| 339 | 410 | |
| 340 | 411 | /// 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 { |
| 128 | 128 | PoppedPointerTag(Item, String), |
| 129 | 129 | TrackingAlloc(AllocId, Size, Align), |
| 130 | 130 | FreedAlloc(AllocId), |
| 131 | AccessedAlloc(AllocId, AllocRange, AccessKind), | |
| 131 | AccessedAlloc(AllocId, AllocRange, borrow_tracker::AccessKind), | |
| 132 | 132 | RejectedIsolatedOp(String), |
| 133 | 133 | ProgressReport { |
| 134 | 134 | 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; |
| 22 | 22 | |
| 23 | 23 | use crate::*; |
| 24 | 24 | |
| 25 | /// Indicates which kind of access is being performed. | |
| 26 | #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] | |
| 27 | pub enum AccessKind { | |
| 28 | Read, | |
| 29 | Write, | |
| 30 | } | |
| 31 | ||
| 32 | 25 | /// Gets an instance for a path. |
| 33 | 26 | /// |
| 34 | 27 | /// 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::{ |
| 139 | 139 | EvalContextExt as _, NonHaltingDiagnostic, TerminationInfo, report_error, |
| 140 | 140 | }; |
| 141 | 141 | pub use crate::eval::{MiriConfig, MiriEntryFnType, create_ecx, eval_entry}; |
| 142 | pub use crate::helpers::{AccessKind, EvalContextExt as _, ToU64 as _, ToUsize as _}; | |
| 142 | pub use crate::helpers::{EvalContextExt as _, ToU64 as _, ToUsize as _}; | |
| 143 | 143 | pub use crate::intrinsics::EvalContextExt as _; |
| 144 | 144 | pub use crate::machine::{ |
| 145 | 145 | AlignmentCheck, AllocExtra, BacktraceStyle, DynMachineCallback, FloatRoundingErrorMode, |
| ... | ... | @@ -165,6 +165,7 @@ pub use crate::shims::unwind::{CatchUnwindData, EvalContextExt as _}; |
| 165 | 165 | /// Also disable the MIR pass that inserts an alignment check on every pointer dereference. Miri |
| 166 | 166 | /// does that too, and with a better error message. |
| 167 | 167 | pub const MIRI_DEFAULT_ARGS: &[&str] = &[ |
| 168 | "-Zcodegen-backend=dummy", | |
| 168 | 169 | "--cfg=miri", |
| 169 | 170 | "-Zalways-encode-mir", |
| 170 | 171 | "-Zextra-const-ub-checks", |
src/tools/miri/src/machine.rs+37-7| ... | ... | @@ -1,9 +1,9 @@ |
| 1 | 1 | //! Global machine state as well as implementation of the interpreter engine |
| 2 | 2 | //! `Machine` trait. |
| 3 | 3 | |
| 4 | use std::any::Any; | |
| 5 | 4 | use std::borrow::Cow; |
| 6 | 5 | use std::cell::{Cell, RefCell}; |
| 6 | use std::collections::BTreeMap; | |
| 7 | 7 | use std::path::Path; |
| 8 | 8 | use std::rc::Rc; |
| 9 | 9 | use std::{fmt, process}; |
| ... | ... | @@ -36,6 +36,7 @@ use rustc_target::spec::Arch; |
| 36 | 36 | use crate::alloc_addresses::EvalContextExt; |
| 37 | 37 | use crate::concurrency::cpu_affinity::{self, CpuAffinityMask}; |
| 38 | 38 | use crate::concurrency::data_race::{self, NaReadType, NaWriteType}; |
| 39 | use crate::concurrency::sync::SyncObj; | |
| 39 | 40 | use crate::concurrency::{ |
| 40 | 41 | AllocDataRaceHandler, GenmcCtx, GenmcEvalContextExt as _, GlobalDataRaceHandler, weak_memory, |
| 41 | 42 | }; |
| ... | ... | @@ -399,11 +400,11 @@ pub struct AllocExtra<'tcx> { |
| 399 | 400 | /// if this allocation is leakable. The backtrace is not |
| 400 | 401 | /// pruned yet; that should be done before printing it. |
| 401 | 402 | 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 | |
| 403 | 404 | /// inside the relevant allocation, to ensure that everything is removed when the allocation is |
| 404 | 405 | /// freed. |
| 405 | 406 | /// 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>>, | |
| 407 | 408 | } |
| 408 | 409 | |
| 409 | 410 | // We need a `Clone` impl because the machine passes `Allocation` through `Cow`... |
| ... | ... | @@ -416,7 +417,7 @@ impl<'tcx> Clone for AllocExtra<'tcx> { |
| 416 | 417 | |
| 417 | 418 | impl VisitProvenance for AllocExtra<'_> { |
| 418 | 419 | 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; | |
| 420 | 421 | |
| 421 | 422 | borrow_tracker.visit_provenance(visit); |
| 422 | 423 | data_race.visit_provenance(visit); |
| ... | ... | @@ -991,7 +992,12 @@ impl<'tcx> MiriMachine<'tcx> { |
| 991 | 992 | .insert(id, (ecx.machine.current_user_relevant_span(), None)); |
| 992 | 993 | } |
| 993 | 994 | |
| 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 | }) | |
| 995 | 1001 | } |
| 996 | 1002 | } |
| 997 | 1003 | |
| ... | ... | @@ -1516,7 +1522,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { |
| 1516 | 1522 | machine.emit_diagnostic(NonHaltingDiagnostic::AccessedAlloc( |
| 1517 | 1523 | alloc_id, |
| 1518 | 1524 | range, |
| 1519 | AccessKind::Read, | |
| 1525 | borrow_tracker::AccessKind::Read, | |
| 1520 | 1526 | )); |
| 1521 | 1527 | } |
| 1522 | 1528 | // 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> { |
| 1536 | 1542 | if let Some(borrow_tracker) = &alloc_extra.borrow_tracker { |
| 1537 | 1543 | borrow_tracker.before_memory_read(alloc_id, prov_extra, range, machine)?; |
| 1538 | 1544 | } |
| 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 | ||
| 1539 | 1550 | interp_ok(()) |
| 1540 | 1551 | } |
| 1541 | 1552 | |
| ... | ... | @@ -1552,7 +1563,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { |
| 1552 | 1563 | machine.emit_diagnostic(NonHaltingDiagnostic::AccessedAlloc( |
| 1553 | 1564 | alloc_id, |
| 1554 | 1565 | range, |
| 1555 | AccessKind::Write, | |
| 1566 | borrow_tracker::AccessKind::Write, | |
| 1556 | 1567 | )); |
| 1557 | 1568 | } |
| 1558 | 1569 | match &machine.data_race { |
| ... | ... | @@ -1576,6 +1587,20 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { |
| 1576 | 1587 | if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker { |
| 1577 | 1588 | borrow_tracker.before_memory_write(alloc_id, prov_extra, range, machine)?; |
| 1578 | 1589 | } |
| 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 | } | |
| 1579 | 1604 | interp_ok(()) |
| 1580 | 1605 | } |
| 1581 | 1606 | |
| ... | ... | @@ -1612,6 +1637,11 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { |
| 1612 | 1637 | if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker { |
| 1613 | 1638 | borrow_tracker.before_memory_deallocation(alloc_id, prove_extra, size, machine)?; |
| 1614 | 1639 | } |
| 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 | ||
| 1615 | 1645 | if let Some((_, deallocated_at)) = machine.allocation_spans.borrow_mut().get_mut(&alloc_id) |
| 1616 | 1646 | { |
| 1617 | 1647 | *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> { |
| 800 | 800 | |
| 801 | 801 | // Target-specific shims |
| 802 | 802 | 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) => | |
| 807 | 804 | { |
| 808 | 805 | return shims::x86::EvalContextExt::emulate_x86_intrinsic( |
| 809 | 806 | 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; |
| 4 | 4 | |
| 5 | 5 | use rustc_abi::FieldIdx; |
| 6 | 6 | |
| 7 | use crate::concurrency::sync::FutexRef; | |
| 7 | use crate::concurrency::sync::{FutexRef, SyncObj}; | |
| 8 | 8 | use crate::*; |
| 9 | 9 | |
| 10 | 10 | pub struct FreeBsdFutex { |
| 11 | 11 | futex: FutexRef, |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | impl SyncObj for FreeBsdFutex {} | |
| 15 | ||
| 14 | 16 | /// Extended variant of the `timespec` struct. |
| 15 | 17 | pub struct UmtxTime { |
| 16 | 18 | timeout: Duration, |
src/tools/miri/src/shims/unix/linux_like/sync.rs+3-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | use crate::concurrency::sync::FutexRef; | |
| 1 | use crate::concurrency::sync::{FutexRef, SyncObj}; | |
| 2 | 2 | use crate::shims::sig::check_min_vararg_count; |
| 3 | 3 | use crate::*; |
| 4 | 4 | |
| ... | ... | @@ -6,6 +6,8 @@ struct LinuxFutex { |
| 6 | 6 | futex: FutexRef, |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | impl SyncObj for LinuxFutex {} | |
| 10 | ||
| 9 | 11 | /// Implementation of the SYS_futex syscall. |
| 10 | 12 | /// `args` is the arguments *including* the syscall number. |
| 11 | 13 | pub fn futex<'tcx>( |
src/tools/miri/src/shims/unix/macos/sync.rs+49-17| ... | ... | @@ -13,15 +13,32 @@ |
| 13 | 13 | use std::cell::Cell; |
| 14 | 14 | use std::time::Duration; |
| 15 | 15 | |
| 16 | use rustc_abi::Size; | |
| 16 | use rustc_abi::{Endian, FieldIdx, Size}; | |
| 17 | 17 | |
| 18 | use crate::concurrency::sync::FutexRef; | |
| 18 | use crate::concurrency::sync::{AccessKind, FutexRef, SyncObj}; | |
| 19 | 19 | use crate::*; |
| 20 | 20 | |
| 21 | 21 | #[derive(Clone)] |
| 22 | 22 | enum MacOsUnfairLock { |
| 23 | Poisoned, | |
| 24 | 23 | Active { mutex_ref: MutexRef }, |
| 24 | PermanentlyLocked, | |
| 25 | } | |
| 26 | ||
| 27 | impl 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 | } | |
| 25 | 42 | } |
| 26 | 43 | |
| 27 | 44 | pub enum MacOsFutexTimeout<'a, 'tcx> { |
| ... | ... | @@ -44,6 +61,8 @@ struct MacOsFutex { |
| 44 | 61 | shared: Cell<bool>, |
| 45 | 62 | } |
| 46 | 63 | |
| 64 | impl SyncObj for MacOsFutex {} | |
| 65 | ||
| 47 | 66 | impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} |
| 48 | 67 | trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 49 | 68 | fn os_unfair_lock_get_data<'a>( |
| ... | ... | @@ -53,22 +72,35 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 53 | 72 | where |
| 54 | 73 | 'tcx: 'a, |
| 55 | 74 | { |
| 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. | |
| 56 | 77 | let this = self.eval_context_mut(); |
| 78 | assert!(this.tcx.data_layout.endian == Endian::Little); | |
| 79 | ||
| 57 | 80 | 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( | |
| 59 | 82 | &lock, |
| 60 | 83 | 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 | } | |
| 70 | 103 | }, |
| 71 | |_| interp_ok(MacOsUnfairLock::Active { mutex_ref: MutexRef::new() }), | |
| 72 | 104 | ) |
| 73 | 105 | } |
| 74 | 106 | } |
| ... | ... | @@ -332,7 +364,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 332 | 364 | let this = self.eval_context_mut(); |
| 333 | 365 | |
| 334 | 366 | 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. | |
| 336 | 368 | throw_machine_stop!(TerminationInfo::Abort( |
| 337 | 369 | "attempted to unlock an os_unfair_lock not owned by the current thread".to_owned() |
| 338 | 370 | )); |
| ... | ... | @@ -361,7 +393,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 361 | 393 | let this = self.eval_context_mut(); |
| 362 | 394 | |
| 363 | 395 | 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. | |
| 365 | 397 | throw_machine_stop!(TerminationInfo::Abort( |
| 366 | 398 | "called os_unfair_lock_assert_owner on an os_unfair_lock not owned by the current thread".to_owned() |
| 367 | 399 | )); |
| ... | ... | @@ -383,7 +415,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 383 | 415 | let this = self.eval_context_mut(); |
| 384 | 416 | |
| 385 | 417 | 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. | |
| 387 | 419 | return interp_ok(()); |
| 388 | 420 | }; |
| 389 | 421 | let mutex_ref = mutex_ref.clone(); |
src/tools/miri/src/shims/unix/sync.rs+108-65| ... | ... | @@ -1,13 +1,11 @@ |
| 1 | 1 | use rustc_abi::Size; |
| 2 | 2 | |
| 3 | use crate::concurrency::sync::LAZY_INIT_COOKIE; | |
| 3 | use crate::concurrency::sync::{AccessKind, SyncObj}; | |
| 4 | 4 | use crate::*; |
| 5 | 5 | |
| 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 | |
| 7 | 7 | /// 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. | |
| 10 | fn bytewise_equal_atomic_relaxed<'tcx>( | |
| 8 | fn bytewise_equal<'tcx>( | |
| 11 | 9 | ecx: &MiriInterpCx<'tcx>, |
| 12 | 10 | left: &MPlaceTy<'tcx>, |
| 13 | 11 | right: &MPlaceTy<'tcx>, |
| ... | ... | @@ -15,25 +13,16 @@ fn bytewise_equal_atomic_relaxed<'tcx>( |
| 15 | 13 | let size = left.layout.size; |
| 16 | 14 | assert_eq!(size, right.layout.size); |
| 17 | 15 | |
| 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)?; | |
| 33 | 18 | |
| 34 | interp_ok(true) | |
| 19 | interp_ok(left_bytes == right_bytes) | |
| 35 | 20 | } |
| 36 | 21 | |
| 22 | // The in-memory marker values we use to indicate whether objects have been initialized. | |
| 23 | const PTHREAD_UNINIT: u8 = 0; | |
| 24 | const PTHREAD_INIT: u8 = 1; | |
| 25 | ||
| 37 | 26 | // # pthread_mutexattr_t |
| 38 | 27 | // We store some data directly inside the type, ignoring the platform layout: |
| 39 | 28 | // - kind: i32 |
| ... | ... | @@ -103,7 +92,7 @@ fn mutexattr_translate_kind<'tcx>( |
| 103 | 92 | |
| 104 | 93 | // # pthread_mutex_t |
| 105 | 94 | // We store some data directly inside the type, ignoring the platform layout: |
| 106 | // - init: u32 | |
| 95 | // - init: u8 | |
| 107 | 96 | |
| 108 | 97 | /// The mutex kind. |
| 109 | 98 | #[derive(Debug, Clone, Copy)] |
| ... | ... | @@ -120,6 +109,21 @@ struct PthreadMutex { |
| 120 | 109 | kind: MutexKind, |
| 121 | 110 | } |
| 122 | 111 | |
| 112 | impl 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 | ||
| 123 | 127 | /// To ensure an initialized mutex that was moved somewhere else can be distinguished from |
| 124 | 128 | /// a statically initialized mutex that is used the first time, we pick some offset within |
| 125 | 129 | /// `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> |
| 138 | 142 | let check_static_initializer = |name| { |
| 139 | 143 | let static_initializer = ecx.eval_path(&["libc", name]); |
| 140 | 144 | 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" | |
| 146 | 150 | ); |
| 147 | 151 | }; |
| 148 | 152 | |
| ... | ... | @@ -172,7 +176,7 @@ fn mutex_create<'tcx>( |
| 172 | 176 | ) -> InterpResult<'tcx, PthreadMutex> { |
| 173 | 177 | let mutex = ecx.deref_pointer_as(mutex_ptr, ecx.libc_ty_layout("pthread_mutex_t"))?; |
| 174 | 178 | 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())?; | |
| 176 | 180 | interp_ok(data) |
| 177 | 181 | } |
| 178 | 182 | |
| ... | ... | @@ -186,10 +190,11 @@ where |
| 186 | 190 | 'tcx: 'a, |
| 187 | 191 | { |
| 188 | 192 | 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( | |
| 190 | 194 | &mutex, |
| 191 | 195 | mutex_init_offset(ecx)?, |
| 192 | || throw_ub_format!("`pthread_mutex_t` can't be moved after first use"), | |
| 196 | PTHREAD_UNINIT, | |
| 197 | PTHREAD_INIT, | |
| 193 | 198 | |ecx| { |
| 194 | 199 | let kind = mutex_kind_from_static_initializer(ecx, &mutex)?; |
| 195 | 200 | interp_ok(PthreadMutex { mutex_ref: MutexRef::new(), kind }) |
| ... | ... | @@ -203,8 +208,7 @@ fn mutex_kind_from_static_initializer<'tcx>( |
| 203 | 208 | mutex: &MPlaceTy<'tcx>, |
| 204 | 209 | ) -> InterpResult<'tcx, MutexKind> { |
| 205 | 210 | // 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])); | |
| 208 | 212 | |
| 209 | 213 | // PTHREAD_MUTEX_INITIALIZER is recognized on all targets. |
| 210 | 214 | if is_initializer("PTHREAD_MUTEX_INITIALIZER")? { |
| ... | ... | @@ -220,18 +224,35 @@ fn mutex_kind_from_static_initializer<'tcx>( |
| 220 | 224 | }, |
| 221 | 225 | _ => {} |
| 222 | 226 | } |
| 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 | ); | |
| 224 | 230 | } |
| 225 | 231 | |
| 226 | 232 | // # pthread_rwlock_t |
| 227 | 233 | // We store some data directly inside the type, ignoring the platform layout: |
| 228 | // - init: u32 | |
| 234 | // - init: u8 | |
| 229 | 235 | |
| 230 | 236 | #[derive(Debug, Clone)] |
| 231 | 237 | struct PthreadRwLock { |
| 232 | 238 | rwlock_ref: RwLockRef, |
| 233 | 239 | } |
| 234 | 240 | |
| 241 | impl 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 | ||
| 235 | 256 | fn rwlock_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> { |
| 236 | 257 | let offset = match &*ecx.tcx.sess.target.os { |
| 237 | 258 | "linux" | "illumos" | "solaris" | "freebsd" | "android" => 0, |
| ... | ... | @@ -245,11 +266,11 @@ fn rwlock_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size |
| 245 | 266 | // the `init` field must start out not equal to LAZY_INIT_COOKIE. |
| 246 | 267 | if !ecx.machine.pthread_rwlock_sanity.replace(true) { |
| 247 | 268 | 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" | |
| 253 | 274 | ); |
| 254 | 275 | } |
| 255 | 276 | |
| ... | ... | @@ -264,17 +285,20 @@ where |
| 264 | 285 | 'tcx: 'a, |
| 265 | 286 | { |
| 266 | 287 | 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( | |
| 268 | 289 | &rwlock, |
| 269 | 290 | rwlock_init_offset(ecx)?, |
| 270 | || throw_ub_format!("`pthread_rwlock_t` can't be moved after first use"), | |
| 291 | PTHREAD_UNINIT, | |
| 292 | PTHREAD_INIT, | |
| 271 | 293 | |ecx| { |
| 272 | if !bytewise_equal_atomic_relaxed( | |
| 294 | if !bytewise_equal( | |
| 273 | 295 | ecx, |
| 274 | 296 | &rwlock, |
| 275 | 297 | &ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]), |
| 276 | 298 | )? { |
| 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 | ); | |
| 278 | 302 | } |
| 279 | 303 | interp_ok(PthreadRwLock { rwlock_ref: RwLockRef::new() }) |
| 280 | 304 | }, |
| ... | ... | @@ -322,7 +346,7 @@ fn condattr_set_clock_id<'tcx>( |
| 322 | 346 | |
| 323 | 347 | // # pthread_cond_t |
| 324 | 348 | // We store some data directly inside the type, ignoring the platform layout: |
| 325 | // - init: u32 | |
| 349 | // - init: u8 | |
| 326 | 350 | |
| 327 | 351 | fn cond_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> { |
| 328 | 352 | let offset = match &*ecx.tcx.sess.target.os { |
| ... | ... | @@ -337,11 +361,11 @@ fn cond_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> |
| 337 | 361 | // the `init` field must start out not equal to LAZY_INIT_COOKIE. |
| 338 | 362 | if !ecx.machine.pthread_condvar_sanity.replace(true) { |
| 339 | 363 | 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" | |
| 345 | 369 | ); |
| 346 | 370 | } |
| 347 | 371 | |
| ... | ... | @@ -354,6 +378,21 @@ struct PthreadCondvar { |
| 354 | 378 | clock: TimeoutClock, |
| 355 | 379 | } |
| 356 | 380 | |
| 381 | impl 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 | ||
| 357 | 396 | fn cond_create<'tcx>( |
| 358 | 397 | ecx: &mut MiriInterpCx<'tcx>, |
| 359 | 398 | cond_ptr: &OpTy<'tcx>, |
| ... | ... | @@ -361,7 +400,7 @@ fn cond_create<'tcx>( |
| 361 | 400 | ) -> InterpResult<'tcx, PthreadCondvar> { |
| 362 | 401 | let cond = ecx.deref_pointer_as(cond_ptr, ecx.libc_ty_layout("pthread_cond_t"))?; |
| 363 | 402 | 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())?; | |
| 365 | 404 | interp_ok(data) |
| 366 | 405 | } |
| 367 | 406 | |
| ... | ... | @@ -373,17 +412,20 @@ where |
| 373 | 412 | 'tcx: 'a, |
| 374 | 413 | { |
| 375 | 414 | 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( | |
| 377 | 416 | &cond, |
| 378 | 417 | cond_init_offset(ecx)?, |
| 379 | || throw_ub_format!("`pthread_cond_t` can't be moved after first use"), | |
| 418 | PTHREAD_UNINIT, | |
| 419 | PTHREAD_INIT, | |
| 380 | 420 | |ecx| { |
| 381 | if !bytewise_equal_atomic_relaxed( | |
| 421 | if !bytewise_equal( | |
| 382 | 422 | ecx, |
| 383 | 423 | &cond, |
| 384 | 424 | &ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]), |
| 385 | 425 | )? { |
| 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 | ); | |
| 387 | 429 | } |
| 388 | 430 | // This used the static initializer. The clock there is always CLOCK_REALTIME. |
| 389 | 431 | interp_ok(PthreadCondvar { |
| ... | ... | @@ -575,11 +617,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 575 | 617 | throw_ub_format!("destroyed a locked mutex"); |
| 576 | 618 | } |
| 577 | 619 | |
| 620 | // This write also deletes the interpreter state for this mutex. | |
| 578 | 621 | // 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)?; | |
| 583 | 625 | |
| 584 | 626 | interp_ok(()) |
| 585 | 627 | } |
| ... | ... | @@ -693,11 +735,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 693 | 735 | throw_ub_format!("destroyed a locked rwlock"); |
| 694 | 736 | } |
| 695 | 737 | |
| 738 | // This write also deletes the interpreter state for this rwlock. | |
| 696 | 739 | // 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)?; | |
| 701 | 743 | |
| 702 | 744 | interp_ok(()) |
| 703 | 745 | } |
| ... | ... | @@ -885,13 +927,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 885 | 927 | // Reading the field also has the side-effect that we detect double-`destroy` |
| 886 | 928 | // since we make the field uninit below. |
| 887 | 929 | let condvar = &cond_get_data(this, cond_op)?.condvar_ref; |
| 888 | if condvar.is_awaited() { | |
| 930 | if !condvar.queue_is_empty() { | |
| 889 | 931 | throw_ub_format!("destroying an awaited conditional variable"); |
| 890 | 932 | } |
| 891 | 933 | |
| 934 | // This write also deletes the interpreter state for this mutex. | |
| 892 | 935 | // 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)?; | |
| 895 | 938 | |
| 896 | 939 | interp_ok(()) |
| 897 | 940 | } |
src/tools/miri/src/shims/windows/sync.rs+31-8| ... | ... | @@ -1,9 +1,9 @@ |
| 1 | 1 | use std::time::Duration; |
| 2 | 2 | |
| 3 | use rustc_abi::Size; | |
| 3 | use rustc_abi::{FieldIdx, Size}; | |
| 4 | 4 | |
| 5 | 5 | use crate::concurrency::init_once::{EvalContextExt as _, InitOnceStatus}; |
| 6 | use crate::concurrency::sync::FutexRef; | |
| 6 | use crate::concurrency::sync::{AccessKind, FutexRef, SyncObj}; | |
| 7 | 7 | use crate::*; |
| 8 | 8 | |
| 9 | 9 | #[derive(Clone)] |
| ... | ... | @@ -11,14 +11,31 @@ struct WindowsInitOnce { |
| 11 | 11 | init_once: InitOnceRef, |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | impl 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 | ||
| 14 | 29 | struct WindowsFutex { |
| 15 | 30 | futex: FutexRef, |
| 16 | 31 | } |
| 17 | 32 | |
| 33 | impl SyncObj for WindowsFutex {} | |
| 34 | ||
| 18 | 35 | impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} |
| 19 | 36 | trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 20 | 37 | // 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. | |
| 22 | 39 | |
| 23 | 40 | fn init_once_get_data<'a>( |
| 24 | 41 | &'a mut self, |
| ... | ... | @@ -33,13 +50,19 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 33 | 50 | this.deref_pointer_as(init_once_ptr, this.windows_ty_layout("INIT_ONCE"))?; |
| 34 | 51 | let init_offset = Size::ZERO; |
| 35 | 52 | |
| 36 | this.lazy_sync_get_data( | |
| 53 | this.get_immovable_sync_with_static_init( | |
| 37 | 54 | &init_once, |
| 38 | 55 | 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 | } | |
| 43 | 66 | }, |
| 44 | 67 | ) |
| 45 | 68 | } |
src/tools/miri/src/shims/x86/avx.rs+10-36| ... | ... | @@ -1,14 +1,12 @@ |
| 1 | 1 | use rustc_abi::CanonAbi; |
| 2 | 2 | use rustc_apfloat::ieee::{Double, Single}; |
| 3 | use rustc_middle::mir; | |
| 4 | 3 | use rustc_middle::ty::Ty; |
| 5 | 4 | use rustc_span::Symbol; |
| 6 | 5 | use rustc_target::callconv::FnAbi; |
| 7 | 6 | |
| 8 | 7 | use super::{ |
| 9 | 8 | 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, | |
| 12 | 10 | }; |
| 13 | 11 | use crate::*; |
| 14 | 12 | |
| ... | ... | @@ -93,21 +91,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 93 | 91 | |
| 94 | 92 | conditional_dot_product(this, left, right, imm, dest)?; |
| 95 | 93 | } |
| 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 | } | |
| 111 | 94 | // Used to implement the _mm256_cmp_ps function. |
| 112 | 95 | // Performs a comparison operation on each component of `left` |
| 113 | 96 | // and `right`. For each component, returns 0 if false or u32::MAX |
| ... | ... | @@ -251,40 +234,31 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 251 | 234 | // Unaligned copy, which is what we want. |
| 252 | 235 | this.mem_copy(src_ptr, dest.ptr(), dest.layout.size, /*nonoverlapping*/ true)?; |
| 253 | 236 | } |
| 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" => { | |
| 259 | 240 | let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; |
| 260 | 241 | |
| 261 | 242 | 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; | |
| 268 | 244 | |
| 269 | 245 | this.write_scalar(Scalar::from_i32(res.into()), dest)?; |
| 270 | 246 | } |
| 271 | 247 | // 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 | |
| 274 | 249 | // _mm_testnzc_ps functions. |
| 275 | 250 | // Calculates two booleans: |
| 276 | 251 | // `direct`, which is true when the highest bit of each element of `op & mask` is zero. |
| 277 | 252 | // `negated`, which is true when the highest bit of each element of `!op & mask` is zero. |
| 278 | 253 | // 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" => { | |
| 282 | 256 | let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; |
| 283 | 257 | |
| 284 | 258 | let (direct, negated) = test_high_bits_masked(this, op, mask)?; |
| 285 | 259 | 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, | |
| 288 | 262 | "vtestnzc.pd.256" | "vtestnzc.pd" | "vtestnzc.ps.256" | "vtestnzc.ps" => |
| 289 | 263 | !direct && !negated, |
| 290 | 264 | _ => unreachable!(), |
src/tools/miri/src/shims/x86/avx2.rs+9-87| ... | ... | @@ -5,8 +5,8 @@ use rustc_span::Symbol; |
| 5 | 5 | use rustc_target::callconv::FnAbi; |
| 6 | 6 | |
| 7 | 7 | use 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, | |
| 10 | 10 | }; |
| 11 | 11 | use crate::*; |
| 12 | 12 | |
| ... | ... | @@ -25,29 +25,20 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 25 | 25 | let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.avx2.").unwrap(); |
| 26 | 26 | |
| 27 | 27 | 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 | |
| 37 | 30 | // integer values in `left` and `right`. |
| 38 | "phadd.w" | "phadd.sw" | "phadd.d" | "phsub.w" | "phsub.sw" | "phsub.d" => { | |
| 31 | "phadd.sw" | "phsub.sw" => { | |
| 39 | 32 | let [left, right] = |
| 40 | 33 | this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; |
| 41 | 34 | |
| 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, | |
| 47 | 38 | _ => unreachable!(), |
| 48 | 39 | }; |
| 49 | 40 | |
| 50 | horizontal_bin_op(this, which, saturating, left, right, dest)?; | |
| 41 | horizontal_bin_op(this, which, /*saturating*/ true, left, right, dest)?; | |
| 51 | 42 | } |
| 52 | 43 | // Used to implement `_mm{,_mask}_{i32,i64}gather_{epi32,epi64,pd,ps}` functions |
| 53 | 44 | // Gathers elements from `slice` using `offsets * scale` as indices. |
| ... | ... | @@ -110,42 +101,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 110 | 101 | this.write_scalar(Scalar::from_int(0, dest.layout.size), &dest)?; |
| 111 | 102 | } |
| 112 | 103 | } |
| 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 | } | |
| 149 | 104 | // Used to implement the _mm256_maddubs_epi16 function. |
| 150 | 105 | // Multiplies packed 8-bit unsigned integers from `left` and packed |
| 151 | 106 | // signed 8-bit integers from `right` into 16-bit signed integers. Then, |
| ... | ... | @@ -285,39 +240,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 285 | 240 | this.copy_op(&left, &dest)?; |
| 286 | 241 | } |
| 287 | 242 | } |
| 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 | } | |
| 321 | 243 | // Used to implement the _mm256_sad_epu8 function. |
| 322 | 244 | // Compute the absolute differences of packed unsigned 8-bit integers |
| 323 | 245 | // 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> { |
| 42 | 42 | // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarry-u32-addcarry-u64.html |
| 43 | 43 | // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/subborrow-u32-subborrow-u64.html |
| 44 | 44 | "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 { | |
| 48 | 46 | return interp_ok(EmulateItemResult::NotSupported); |
| 49 | 47 | } |
| 50 | 48 | |
| ... | ... | @@ -61,28 +59,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 61 | 59 | this.write_immediate(*sum, &this.project_field(dest, FieldIdx::ONE)?)?; |
| 62 | 60 | } |
| 63 | 61 | |
| 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 | ||
| 86 | 62 | // Used to implement the `_mm_pause` function. |
| 87 | 63 | // The intrinsic is used to hint the processor that the code is in a spin-loop. |
| 88 | 64 | // It is compiled down to a `pause` instruction. When SSE2 is not available, |
| ... | ... | @@ -721,36 +697,6 @@ fn convert_float_to_int<'tcx>( |
| 721 | 697 | interp_ok(()) |
| 722 | 698 | } |
| 723 | 699 | |
| 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. | |
| 728 | fn 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 | ||
| 754 | 700 | /// Splits `op` (which must be a SIMD vector) into 128-bit chunks. |
| 755 | 701 | /// |
| 756 | 702 | /// 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> { |
| 180 | 180 | |
| 181 | 181 | this.write_immediate(*res, dest)?; |
| 182 | 182 | } |
| 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 | } | |
| 206 | 183 | _ => return interp_ok(EmulateItemResult::NotSupported), |
| 207 | 184 | } |
| 208 | 185 | 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> { |
| 36 | 36 | // Intrinsincs sufixed with "epiX" or "epuX" operate with X-bit signed or unsigned |
| 37 | 37 | // vectors. |
| 38 | 38 | 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 | } | |
| 75 | 39 | // Used to implement the _mm_sad_epu8 function. |
| 76 | 40 | // Computes the absolute differences of packed unsigned 8-bit integers in `a` |
| 77 | 41 | // and `b`, then horizontally sum each consecutive 8 differences to produce |
| ... | ... | @@ -320,10 +284,10 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 320 | 284 | |
| 321 | 285 | this.write_immediate(*res, dest)?; |
| 322 | 286 | } |
| 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" => { | |
| 327 | 291 | let [left, right] = |
| 328 | 292 | this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; |
| 329 | 293 | |
| ... | ... | @@ -336,8 +300,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 336 | 300 | // Convert first element of `right` |
| 337 | 301 | let right0 = this.read_immediate(&this.project_index(&right, 0)?)?; |
| 338 | 302 | 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). | |
| 341 | 303 | let res0 = this.float_to_float_or_int(&right0, dest0.layout)?; |
| 342 | 304 | this.write_immediate(*res0, &dest0)?; |
| 343 | 305 |
src/tools/miri/src/shims/x86/sse3.rs-17| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | use rustc_abi::CanonAbi; |
| 2 | use rustc_middle::mir; | |
| 3 | 2 | use rustc_middle::ty::Ty; |
| 4 | 3 | use rustc_span::Symbol; |
| 5 | 4 | use rustc_target::callconv::FnAbi; |
| 6 | 5 | |
| 7 | use super::horizontal_bin_op; | |
| 8 | 6 | use crate::*; |
| 9 | 7 | |
| 10 | 8 | impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} |
| ... | ... | @@ -22,21 +20,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 22 | 20 | let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse3.").unwrap(); |
| 23 | 21 | |
| 24 | 22 | 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 | } | |
| 40 | 23 | // Used to implement the _mm_lddqu_si128 function. |
| 41 | 24 | // Reads a 128-bit vector from an unaligned pointer. This intrinsic |
| 42 | 25 | // 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> { |
| 157 | 157 | |
| 158 | 158 | mpsadbw(this, left, right, imm, dest)?; |
| 159 | 159 | } |
| 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" => { | |
| 165 | 163 | let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; |
| 166 | 164 | |
| 167 | 165 | 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; | |
| 174 | 167 | |
| 175 | 168 | this.write_scalar(Scalar::from_i32(res.into()), dest)?; |
| 176 | 169 | } |
src/tools/miri/src/shims/x86/ssse3.rs+8-18| ... | ... | @@ -4,7 +4,7 @@ use rustc_middle::ty::Ty; |
| 4 | 4 | use rustc_span::Symbol; |
| 5 | 5 | use rustc_target::callconv::FnAbi; |
| 6 | 6 | |
| 7 | use super::{horizontal_bin_op, int_abs, pmulhrsw, psign}; | |
| 7 | use super::{horizontal_bin_op, pmulhrsw, psign}; | |
| 8 | 8 | use crate::*; |
| 9 | 9 | |
| 10 | 10 | impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} |
| ... | ... | @@ -22,13 +22,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { |
| 22 | 22 | let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.ssse3.").unwrap(); |
| 23 | 23 | |
| 24 | 24 | 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 | } | |
| 32 | 25 | // Used to implement the _mm_shuffle_epi8 intrinsic. |
| 33 | 26 | // Shuffles bytes from `left` using `right` as pattern. |
| 34 | 27 | // 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> { |
| 58 | 51 | this.write_scalar(res, &dest)?; |
| 59 | 52 | } |
| 60 | 53 | } |
| 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 | |
| 63 | 56 | // 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" => { | |
| 66 | 58 | let [left, right] = |
| 67 | 59 | this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; |
| 68 | 60 | |
| 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, | |
| 74 | 64 | _ => unreachable!(), |
| 75 | 65 | }; |
| 76 | 66 | |
| 77 | horizontal_bin_op(this, which, saturating, left, right, dest)?; | |
| 67 | horizontal_bin_op(this, which, /*saturating*/ true, left, right, dest)?; | |
| 78 | 68 | } |
| 79 | 69 | // Used to implement the _mm_maddubs_epi16 function. |
| 80 | 70 | // Multiplies packed 8-bit unsigned integers from `left` and packed |
src/tools/miri/test-cargo-miri/Cargo.lock-8| ... | ... | @@ -27,7 +27,6 @@ dependencies = [ |
| 27 | 27 | "autocfg", |
| 28 | 28 | "byteorder 0.5.3", |
| 29 | 29 | "byteorder 1.5.0", |
| 30 | "cdylib", | |
| 31 | 30 | "exported_symbol", |
| 32 | 31 | "eyre", |
| 33 | 32 | "issue_1567", |
| ... | ... | @@ -38,13 +37,6 @@ dependencies = [ |
| 38 | 37 | "proc_macro_crate", |
| 39 | 38 | ] |
| 40 | 39 | |
| 41 | [[package]] | |
| 42 | name = "cdylib" | |
| 43 | version = "0.1.0" | |
| 44 | dependencies = [ | |
| 45 | "byteorder 1.5.0", | |
| 46 | ] | |
| 47 | ||
| 48 | 40 | [[package]] |
| 49 | 41 | name = "exported_symbol" |
| 50 | 42 | version = "0.1.0" |
src/tools/miri/test-cargo-miri/Cargo.toml-1| ... | ... | @@ -10,7 +10,6 @@ edition = "2024" |
| 10 | 10 | |
| 11 | 11 | [dependencies] |
| 12 | 12 | byteorder = "1.0" |
| 13 | cdylib = { path = "cdylib" } | |
| 14 | 13 | exported_symbol = { path = "exported-symbol" } |
| 15 | 14 | proc_macro_crate = { path = "proc-macro-crate" } |
| 16 | 15 | issue_1567 = { path = "issue-1567" } |
src/tools/miri/test-cargo-miri/cdylib/Cargo.toml deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | [package] | |
| 2 | name = "cdylib" | |
| 3 | version = "0.1.0" | |
| 4 | authors = ["Miri Team"] | |
| 5 | edition = "2018" | |
| 6 | ||
| 7 | [lib] | |
| 8 | # cargo-miri used to handle `cdylib` crate-type specially (https://github.com/rust-lang/miri/pull/1577). | |
| 9 | crate-type = ["cdylib"] | |
| 10 | ||
| 11 | [dependencies] | |
| 12 | byteorder = "1.0" # to test dependencies of sub-crates |
src/tools/miri/test-cargo-miri/cdylib/src/lib.rs deleted-6| ... | ... | @@ -1,6 +0,0 @@ |
| 1 | use byteorder::{BigEndian, ByteOrder}; | |
| 2 | ||
| 3 | #[no_mangle] | |
| 4 | extern "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 @@ |
| 1 | subcrate,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 | |
| 1 | subcrate,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 | ||
| 4 | use std::cell::SyncUnsafeCell; | |
| 5 | use std::sync::atomic::*; | |
| 6 | use std::thread; | |
| 7 | ||
| 8 | fn 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 @@ |
| 1 | error: 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 | | | |
| 4 | LL | 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 | ||
| 10 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 11 | ||
| 12 | error: 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 @@ |
| 1 | 1 | //@ignore-target: windows # No pthreads on Windows |
| 2 | 2 | //@ 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]" | |
| 4 | 4 | |
| 5 | 5 | /// Test that destroying a pthread_cond twice fails, even without a check for number validity |
| 6 | 6 |
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: Undefined Behavior: `pthread_cond_t` can't be moved after first use | |
| 1 | error: Undefined Behavior: `pthread_cond_t` was not properly initialized at this location, or it got overwritten | |
| 2 | 2 | --> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC |
| 3 | 3 | | |
| 4 | 4 | LL | 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() { |
| 18 | 18 | // move pthread_cond_t |
| 19 | 19 | let mut cond2 = cond; |
| 20 | 20 | |
| 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 | |
| 22 | 22 | } |
| 23 | 23 | } |
| 24 | 24 | |
| ... | ... | @@ -32,6 +32,6 @@ fn check() { |
| 32 | 32 | // move pthread_cond_t |
| 33 | 33 | let mut cond2 = cond; |
| 34 | 34 | |
| 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 | |
| 36 | 36 | } |
| 37 | 37 | } |
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.static_initializer.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: Undefined Behavior: `pthread_cond_t` can't be moved after first use | |
| 1 | error: Undefined Behavior: `pthread_cond_t` was not properly initialized at this location, or it got overwritten | |
| 2 | 2 | --> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC |
| 3 | 3 | | |
| 4 | 4 | LL | 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 @@ |
| 1 | 1 | //@ignore-target: windows # No pthreads on Windows |
| 2 | 2 | //@ 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]" | |
| 4 | 4 | |
| 5 | 5 | /// Test that destroying a pthread_mutex twice fails, even without a check for number validity |
| 6 | 6 |
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 | ||
| 5 | use std::cell::UnsafeCell; | |
| 6 | use std::sync::atomic::*; | |
| 7 | use std::thread; | |
| 8 | ||
| 9 | struct Mutex(UnsafeCell<libc::pthread_mutex_t>); | |
| 10 | impl Mutex { | |
| 11 | fn get(&self) -> *mut libc::pthread_mutex_t { | |
| 12 | self.0.get() | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | unsafe impl Send for Mutex {} | |
| 17 | unsafe impl Sync for Mutex {} | |
| 18 | ||
| 19 | fn 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 @@ |
| 1 | error: Undefined Behavior: deallocation of `pthread_mutex_t` is forbidden while the queue is non-empty | |
| 2 | --> RUSTLIB/alloc/src/boxed.rs:LL:CC | |
| 3 | | | |
| 4 | LL | 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 | |
| 13 | note: inside closure | |
| 14 | --> tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.rs:LL:CC | |
| 15 | | | |
| 16 | LL | drop(unsafe { Box::from_raw(m.get().cast::<Mutex>()) }); | |
| 17 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 18 | ||
| 19 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 20 | ||
| 21 | error: 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 @@ |
| 1 | error: Undefined Behavior: `pthread_mutex_t` can't be moved after first use | |
| 1 | error: Undefined Behavior: `pthread_mutex_t` was not properly initialized at this location, or it got overwritten | |
| 2 | 2 | --> tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC |
| 3 | 3 | | |
| 4 | 4 | LL | 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() { |
| 12 | 12 | assert_eq!(libc::pthread_mutex_init(&mut m as *mut _, std::ptr::null()), 0); |
| 13 | 13 | |
| 14 | 14 | 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 | |
| 16 | 16 | } |
| 17 | 17 | } |
| 18 | 18 | |
| ... | ... | @@ -23,6 +23,6 @@ fn check() { |
| 23 | 23 | libc::pthread_mutex_lock(&mut m as *mut _); |
| 24 | 24 | |
| 25 | 25 | 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 | |
| 27 | 27 | } |
| 28 | 28 | } |
src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: Undefined Behavior: `pthread_mutex_t` can't be moved after first use | |
| 1 | error: Undefined Behavior: `pthread_mutex_t` was not properly initialized at this location, or it got overwritten | |
| 2 | 2 | --> tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC |
| 3 | 3 | | |
| 4 | 4 | LL | 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 | ||
| 3 | fn 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 @@ |
| 1 | error: 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 | | | |
| 4 | LL | 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 | ||
| 10 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 11 | ||
| 12 | error: 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 | ||
| 4 | use std::cell::UnsafeCell; | |
| 5 | use std::sync::atomic::*; | |
| 6 | use std::thread; | |
| 7 | ||
| 8 | struct Mutex(UnsafeCell<libc::pthread_mutex_t>); | |
| 9 | impl Mutex { | |
| 10 | fn get(&self) -> *mut libc::pthread_mutex_t { | |
| 11 | self.0.get() | |
| 12 | } | |
| 13 | } | |
| 14 | ||
| 15 | unsafe impl Send for Mutex {} | |
| 16 | unsafe impl Sync for Mutex {} | |
| 17 | ||
| 18 | // The offset to the "sensitive" part of the mutex (that Miri attaches the metadata to). | |
| 19 | const OFFSET: usize = if cfg!(target_os = "macos") { 4 } else { 0 }; | |
| 20 | ||
| 21 | fn 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 @@ |
| 1 | error: 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 | | | |
| 4 | LL | ... 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 | ||
| 10 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 11 | ||
| 12 | error: 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 | ||
| 4 | use std::cell::UnsafeCell; | |
| 5 | use std::sync::atomic::*; | |
| 6 | use std::thread; | |
| 7 | ||
| 8 | struct Mutex(UnsafeCell<libc::pthread_mutex_t>); | |
| 9 | impl Mutex { | |
| 10 | fn get(&self) -> *mut libc::pthread_mutex_t { | |
| 11 | self.0.get() | |
| 12 | } | |
| 13 | } | |
| 14 | ||
| 15 | unsafe impl Send for Mutex {} | |
| 16 | unsafe impl Sync for Mutex {} | |
| 17 | ||
| 18 | // The offset to the "sensitive" part of the mutex (that Miri attaches the metadata to). | |
| 19 | const OFFSET: usize = if cfg!(target_os = "macos") { 4 } else { 0 }; | |
| 20 | ||
| 21 | fn 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 @@ |
| 1 | error: 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 | | | |
| 4 | LL | 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 | ||
| 10 | note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | |
| 11 | ||
| 12 | error: 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 @@ |
| 1 | 1 | //@ignore-target: windows # No pthreads on Windows |
| 2 | 2 | //@ 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]" | |
| 4 | 4 | |
| 5 | 5 | /// Test that destroying a pthread_rwlock twice fails, even without a check for number validity |
| 6 | 6 |
src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs+1-1| ... | ... | @@ -9,6 +9,6 @@ fn main() { |
| 9 | 9 | // Move rwlock |
| 10 | 10 | let mut rw2 = rw; |
| 11 | 11 | |
| 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 | |
| 13 | 13 | } |
| 14 | 14 | } |
src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.stderr+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | error: Undefined Behavior: `pthread_rwlock_t` can't be moved after first use | |
| 1 | error: Undefined Behavior: `pthread_rwlock_t` was not properly initialized at this location, or it got overwritten | |
| 2 | 2 | --> tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs:LL:CC |
| 3 | 3 | | |
| 4 | 4 | LL | 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::*; |
| 6 | 6 | fn main() { |
| 7 | 7 | unsafe { |
| 8 | 8 | let buf = [0u32; 5]; |
| 9 | //~v ERROR: accessing memory with alignment | |
| 9 | //~v ERROR: accessing memory with alignment | |
| 10 | 10 | simd_masked_load::<_, _, _, { SimdAlign::Element }>( |
| 11 | 11 | i32x4::splat(-1), |
| 12 | 12 | // 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() { |
| 14 | 14 | libc::os_unfair_lock_assert_not_owner(lock.get()); |
| 15 | 15 | } |
| 16 | 16 | |
| 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. | |
| 21 | 18 | 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()) }); | |
| 25 | 23 | } |
src/tools/miri/tests/pass-dep/libc/pthread-sync.rs+34-19| ... | ... | @@ -8,18 +8,21 @@ use std::mem::MaybeUninit; |
| 8 | 8 | use std::{mem, ptr, thread}; |
| 9 | 9 | |
| 10 | 10 | fn main() { |
| 11 | test_mutex(); | |
| 11 | 12 | test_mutex_libc_init_recursive(); |
| 12 | 13 | test_mutex_libc_init_normal(); |
| 13 | 14 | test_mutex_libc_init_errorcheck(); |
| 14 | test_rwlock_libc_static_initializer(); | |
| 15 | 15 | #[cfg(target_os = "linux")] |
| 16 | 16 | 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(); | |
| 17 | 22 | |
| 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(); | |
| 23 | 26 | } |
| 24 | 27 | |
| 25 | 28 | // We want to only use pthread APIs here for easier testing. |
| ... | ... | @@ -107,8 +110,7 @@ fn test_mutex_libc_init_errorcheck() { |
| 107 | 110 | } |
| 108 | 111 | } |
| 109 | 112 | |
| 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. | |
| 112 | 114 | #[cfg(target_os = "linux")] |
| 113 | 115 | fn test_mutex_libc_static_initializer_recursive() { |
| 114 | 116 | let mutex = std::cell::UnsafeCell::new(libc::PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); |
| ... | ... | @@ -126,6 +128,22 @@ fn test_mutex_libc_static_initializer_recursive() { |
| 126 | 128 | } |
| 127 | 129 | } |
| 128 | 130 | |
| 131 | // Only linux provides PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP. | |
| 132 | #[cfg(target_os = "linux")] | |
| 133 | fn 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 | ||
| 129 | 147 | struct SendPtr<T> { |
| 130 | 148 | ptr: *mut T, |
| 131 | 149 | } |
| ... | ... | @@ -137,7 +155,7 @@ impl<T> Clone for SendPtr<T> { |
| 137 | 155 | } |
| 138 | 156 | } |
| 139 | 157 | |
| 140 | fn check_mutex() { | |
| 158 | fn test_mutex() { | |
| 141 | 159 | let bomb = AbortOnDrop; |
| 142 | 160 | // Specifically *not* using `Arc` to make sure there is no synchronization apart from the mutex. |
| 143 | 161 | unsafe { |
| ... | ... | @@ -168,7 +186,7 @@ fn check_mutex() { |
| 168 | 186 | bomb.defuse(); |
| 169 | 187 | } |
| 170 | 188 | |
| 171 | fn check_rwlock_write() { | |
| 189 | fn test_rwlock_write() { | |
| 172 | 190 | let bomb = AbortOnDrop; |
| 173 | 191 | unsafe { |
| 174 | 192 | let data = SyncUnsafeCell::new((libc::PTHREAD_RWLOCK_INITIALIZER, 0)); |
| ... | ... | @@ -209,7 +227,7 @@ fn check_rwlock_write() { |
| 209 | 227 | bomb.defuse(); |
| 210 | 228 | } |
| 211 | 229 | |
| 212 | fn check_rwlock_read_no_deadlock() { | |
| 230 | fn test_rwlock_read_no_deadlock() { | |
| 213 | 231 | let bomb = AbortOnDrop; |
| 214 | 232 | unsafe { |
| 215 | 233 | let l1 = SyncUnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER); |
| ... | ... | @@ -237,12 +255,11 @@ fn check_rwlock_read_no_deadlock() { |
| 237 | 255 | bomb.defuse(); |
| 238 | 256 | } |
| 239 | 257 | |
| 240 | fn check_cond() { | |
| 258 | fn test_cond() { | |
| 241 | 259 | let bomb = AbortOnDrop; |
| 242 | 260 | 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 }; | |
| 246 | 263 | |
| 247 | 264 | let mut mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER; |
| 248 | 265 | let mutex = SendPtr { ptr: &mut mutex }; |
| ... | ... | @@ -286,7 +303,7 @@ fn check_cond() { |
| 286 | 303 | bomb.defuse(); |
| 287 | 304 | } |
| 288 | 305 | |
| 289 | fn check_condattr() { | |
| 306 | fn test_condattr() { | |
| 290 | 307 | unsafe { |
| 291 | 308 | // Just smoke-testing that these functions can be called. |
| 292 | 309 | let mut attr: MaybeUninit<libc::pthread_condattr_t> = MaybeUninit::uninit(); |
| ... | ... | @@ -311,9 +328,7 @@ fn check_condattr() { |
| 311 | 328 | } |
| 312 | 329 | } |
| 313 | 330 | |
| 314 | // std::sync::RwLock does not even used pthread_rwlock any more. | |
| 315 | // Do some smoke testing of the API surface. | |
| 316 | fn test_rwlock_libc_static_initializer() { | |
| 331 | fn test_rwlock() { | |
| 317 | 332 | let rw = std::cell::UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER); |
| 318 | 333 | unsafe { |
| 319 | 334 | 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 |
| 20 | 20 | [assign.custom_welcome_messages] |
| 21 | 21 | welcome-message = "(unused)" |
| 22 | 22 | welcome-message-no-reviewer = """ |
| 23 | Thank you for contributing to Miri! | |
| 23 | Thank you for contributing to Miri! A reviewer will take a look at your PR, typically within a week or two. | |
| 24 | 24 | Please 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. |
| 25 | 25 | """ |
| 26 | 26 |
src/tools/tidy/src/diagnostics.rs+43-9| ... | ... | @@ -1,9 +1,10 @@ |
| 1 | 1 | use std::collections::HashSet; |
| 2 | 2 | use std::fmt::{Display, Formatter}; |
| 3 | use std::io; | |
| 3 | 4 | use std::path::{Path, PathBuf}; |
| 4 | 5 | use std::sync::{Arc, Mutex}; |
| 5 | 6 | |
| 6 | use termcolor::{Color, WriteColor}; | |
| 7 | use termcolor::Color; | |
| 7 | 8 | |
| 8 | 9 | #[derive(Clone, Default)] |
| 9 | 10 | ///CLI flags used by tidy. |
| ... | ... | @@ -245,30 +246,63 @@ pub const COLOR_WARNING: Color = Color::Yellow; |
| 245 | 246 | /// Output a message to stderr. |
| 246 | 247 | /// The message can be optionally scoped to a certain check, and it can also have a certain color. |
| 247 | 248 | pub fn output_message(msg: &str, id: Option<&CheckId>, color: Option<Color>) { |
| 248 | use std::io::Write; | |
| 249 | use termcolor::{ColorChoice, ColorSpec}; | |
| 249 | 250 | |
| 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 | }; | |
| 251 | 256 | |
| 252 | let mut stderr = StandardStream::stderr(ColorChoice::Auto); | |
| 253 | 257 | if let Some(color) = &color { |
| 254 | 258 | stderr.set_color(ColorSpec::new().set_fg(Some(*color))).unwrap(); |
| 255 | 259 | } |
| 256 | 260 | |
| 257 | 261 | match id { |
| 258 | 262 | Some(id) => { |
| 259 | write!(&mut stderr, "tidy [{}", id.name).unwrap(); | |
| 263 | write!(stderr, "tidy [{}", id.name).unwrap(); | |
| 260 | 264 | if let Some(path) = &id.path { |
| 261 | write!(&mut stderr, " ({})", path.display()).unwrap(); | |
| 265 | write!(stderr, " ({})", path.display()).unwrap(); | |
| 262 | 266 | } |
| 263 | write!(&mut stderr, "]").unwrap(); | |
| 267 | write!(stderr, "]").unwrap(); | |
| 264 | 268 | } |
| 265 | 269 | None => { |
| 266 | write!(&mut stderr, "tidy").unwrap(); | |
| 270 | write!(stderr, "tidy").unwrap(); | |
| 267 | 271 | } |
| 268 | 272 | } |
| 269 | 273 | if color.is_some() { |
| 270 | 274 | stderr.set_color(&ColorSpec::new()).unwrap(); |
| 271 | 275 | } |
| 272 | 276 | |
| 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. | |
| 283 | struct StderrForUnitTests; | |
| 284 | ||
| 285 | impl 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 | ||
| 296 | impl 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 | } | |
| 274 | 308 | } |
tests/crashes/119783.rs deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | //@ known-bug: #119783 | |
| 2 | #![feature(associated_const_equality, min_generic_const_args)] | |
| 3 | ||
| 4 | trait Trait { | |
| 5 | #[type_const] | |
| 6 | const F: fn(); | |
| 7 | } | |
| 8 | ||
| 9 | fn take(_: impl Trait<F = { || {} }>) {} | |
| 10 | ||
| 11 | fn main() {} |
tests/crashes/140729.rs deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | //@ known-bug: #140729 | |
| 2 | #![feature(min_generic_const_args)] | |
| 3 | ||
| 4 | const C: usize = 0; | |
| 5 | pub struct A<const M: usize> {} | |
| 6 | impl A<C> { | |
| 7 | fn fun1() {} | |
| 8 | } | |
| 9 | impl 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)] | |
| 5 | trait a < const b : &'static str> {} trait c {} struct d< e >(e); | |
| 6 | impl<e> c for e where e: a<""> {} | |
| 7 | impl<e> c for d<e> {} | |
| 8 | impl<e> !a<f> for e {} | |
| 9 | const f : &str = ""; | |
| 10 | fn 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 | ||
| 8 | trait GoodTr { | |
| 9 | #[type_const] | |
| 10 | const NUM: usize; | |
| 11 | } | |
| 12 | ||
| 13 | struct BadS; | |
| 14 | ||
| 15 | impl GoodTr for BadS { | |
| 16 | const NUM: usize = 42; | |
| 17 | } | |
| 18 | ||
| 19 | fn accept_good_tr<const N: usize, T: GoodTr<NUM = { N }>>(_x: &T) {} | |
| 20 | ||
| 21 | fn 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 {} |
| 38 | 38 | | |
| 39 | 39 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations |
| 40 | 40 | | |
| 41 | LL | #[const_trait] trait Foo { | |
| 42 | | ++++++++++++++ | |
| 41 | LL | const trait Foo { | |
| 42 | | +++++ | |
| 43 | 43 | |
| 44 | 44 | error: `[const]` can only be applied to `const` traits |
| 45 | 45 | --> const-super-trait.rs:9:17 |
| ... | ... | @@ -49,8 +49,8 @@ LL | const fn foo<T: [const] Bar>(x: &T) { |
| 49 | 49 | | |
| 50 | 50 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations |
| 51 | 51 | | |
| 52 | LL | #[const_trait] trait Bar: [const] Foo {} | |
| 53 | | ++++++++++++++ | |
| 52 | LL | const trait Bar: [const] Foo {} | |
| 53 | | +++++ | |
| 54 | 54 | |
| 55 | 55 | error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions |
| 56 | 56 | --> const-super-trait.rs:10:7 |
| ... | ... | @@ -65,13 +65,12 @@ LL | trait Foo { |
| 65 | 65 | | ^^^^^^^^^ this trait is not const |
| 66 | 66 | LL | fn a(&self); |
| 67 | 67 | | ------------ 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 | |
| 69 | 69 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants |
| 70 | 70 | help: consider making trait `Foo` const |
| 71 | 71 | | |
| 72 | LL + #[const_trait] | |
| 73 | LL | trait Foo { | |
| 74 | | | |
| 72 | LL | const trait Foo { | |
| 73 | | +++++ | |
| 75 | 74 | |
| 76 | 75 | error: aborting due to 6 previous errors |
| 77 | 76 |
tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-enabled.stderr+6-7| ... | ... | @@ -18,8 +18,8 @@ LL | trait Bar: [const] Foo {} |
| 18 | 18 | | |
| 19 | 19 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 20 | 20 | | |
| 21 | LL | #[const_trait] trait Foo { | |
| 22 | | ++++++++++++++ | |
| 21 | LL | const trait Foo { | |
| 22 | | +++++ | |
| 23 | 23 | |
| 24 | 24 | error: `[const]` can only be applied to `const` traits |
| 25 | 25 | --> const-super-trait.rs:9:17 |
| ... | ... | @@ -29,8 +29,8 @@ LL | const fn foo<T: [const] Bar>(x: &T) { |
| 29 | 29 | | |
| 30 | 30 | help: mark `Bar` as `const` to allow it to have `const` implementations |
| 31 | 31 | | |
| 32 | LL | #[const_trait] trait Bar: [const] Foo {} | |
| 33 | | ++++++++++++++ | |
| 32 | LL | const trait Bar: [const] Foo {} | |
| 33 | | +++++ | |
| 34 | 34 | |
| 35 | 35 | error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions |
| 36 | 36 | --> const-super-trait.rs:10:7 |
| ... | ... | @@ -48,9 +48,8 @@ LL | fn a(&self); |
| 48 | 48 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants |
| 49 | 49 | help: consider making trait `Foo` const |
| 50 | 50 | | |
| 51 | LL + #[const_trait] | |
| 52 | LL | trait Foo { | |
| 53 | | | |
| 51 | LL | const trait Foo { | |
| 52 | | +++++ | |
| 54 | 53 | |
| 55 | 54 | error: aborting due to 4 previous errors |
| 56 | 55 |
tests/rustdoc/constant/const-effect-param.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | #![crate_name = "foo"] |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | pub trait Tr { | |
| 6 | pub const trait Tr { | |
| 8 | 7 | fn f(); |
| 9 | 8 | } |
| 10 | 9 |
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. | |
| 3 | 2 | #![crate_name = "foo"] |
| 4 | 3 | #![feature(const_trait_impl)] |
| 5 | 4 | |
| ... | ... | @@ -8,8 +7,7 @@ |
| 8 | 7 | //@ !has - '//*[@id="tymethod.required"]' 'const' |
| 9 | 8 | //@ has - '//*[@id="method.defaulted"]' 'fn defaulted()' |
| 10 | 9 | //@ !has - '//*[@id="method.defaulted"]' 'const' |
| 11 | #[const_trait] | |
| 12 | pub trait Tr { | |
| 10 | pub const trait Tr { | |
| 13 | 11 | fn required(); |
| 14 | 12 | fn defaulted() {} |
| 15 | 13 | } |
tests/rustdoc/constant/rfc-2632-const-trait-impl.rs+1-2| ... | ... | @@ -19,8 +19,7 @@ pub struct S<T>(T); |
| 19 | 19 | //@ has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Fn' |
| 20 | 20 | //@ !has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' '[const]' |
| 21 | 21 | //@ has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' ': Fn' |
| 22 | #[const_trait] | |
| 23 | pub trait Tr<T> { | |
| 22 | pub const trait Tr<T> { | |
| 24 | 23 | //@ !has - '//section[@id="method.a"]/h4[@class="code-header"]' '[const]' |
| 25 | 24 | //@ has - '//section[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn' |
| 26 | 25 | //@ !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 @@ |
| 1 | 1 | //@ compile-flags: -Znext-solver |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | |
| 4 | #[const_trait] | |
| 5 | pub trait Resource {} | |
| 4 | pub const trait Resource {} | |
| 6 | 5 | |
| 7 | 6 | pub const fn load<R: [const] Resource>() -> i32 { |
| 8 | 7 | 0 |
tests/ui/associated-consts/assoc-const-eq-ambiguity.rs+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | // We used to say "ambiguous associated type" on ambiguous associated consts. |
| 2 | 2 | // Ensure that we now use the correct label. |
| 3 | 3 | |
| 4 | #![feature(associated_const_equality, min_generic_const_args)] | |
| 4 | #![feature(associated_const_equality, min_generic_const_args, unsized_const_params)] | |
| 5 | 5 | #![allow(incomplete_features)] |
| 6 | 6 | |
| 7 | 7 | trait 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 @@ |
| 1 | 1 | // Check that we eventually catch types of assoc const bounds |
| 2 | 2 | // (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 | )] | |
| 4 | 9 | #![allow(incomplete_features)] |
| 5 | 10 | |
| 6 | trait Trait<T> { | |
| 11 | use std::marker::ConstParamTy_; | |
| 12 | ||
| 13 | trait Trait<T: ConstParamTy_> { | |
| 7 | 14 | #[type_const] |
| 8 | 15 | const K: T; |
| 9 | 16 | } |
tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr+3-3| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | error: 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 | |
| 3 | 3 | | |
| 4 | 4 | LL | K = { () } |
| 5 | 5 | | ^^^^^^ |
| 6 | 6 | |
| 7 | 7 | error: 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 | |
| 9 | 9 | | |
| 10 | 10 | LL | K = { () } |
| 11 | 11 | | ^^^^^^ |
| ... | ... | @@ -13,7 +13,7 @@ LL | K = { () } |
| 13 | 13 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 14 | 14 | |
| 15 | 15 | error: 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 | |
| 17 | 17 | | |
| 18 | 18 | LL | _: impl Trait< |
| 19 | 19 | | _____________^ |
tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs+9-2| ... | ... | @@ -3,10 +3,17 @@ |
| 3 | 3 | // |
| 4 | 4 | //@ check-pass |
| 5 | 5 | |
| 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 | )] | |
| 7 | 12 | #![allow(incomplete_features)] |
| 8 | 13 | |
| 9 | trait Trait<T> { | |
| 14 | use std::marker::ConstParamTy_; | |
| 15 | ||
| 16 | trait Trait<T: ConstParamTy_> { | |
| 10 | 17 | #[type_const] |
| 11 | 18 | const K: T; |
| 12 | 19 | } |
tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | // Detect and reject escaping late-bound generic params in |
| 2 | 2 | // 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)] | |
| 4 | 4 | #![allow(incomplete_features)] |
| 5 | 5 | |
| 6 | 6 | trait Trait<'a> { |
tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs+12-5| ... | ... | @@ -1,14 +1,21 @@ |
| 1 | 1 | // Regression test for issue #108271. |
| 2 | 2 | // 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 | )] | |
| 4 | 9 | #![allow(incomplete_features)] |
| 5 | 10 | |
| 6 | trait Trait<'a, T: 'a, const N: usize> { | |
| 11 | use std::marker::ConstParamTy_; | |
| 12 | ||
| 13 | trait Trait<'a, T: 'a + ConstParamTy_, const N: usize> { | |
| 7 | 14 | #[type_const] |
| 8 | 15 | const K: &'a [T; N]; |
| 9 | 16 | } |
| 10 | 17 | |
| 11 | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} | |
| 18 | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} | |
| 12 | 19 | //~^ ERROR the type of the associated constant `K` must not depend on generic parameters |
| 13 | 20 | //~| NOTE its type must not depend on the lifetime parameter `'r` |
| 14 | 21 | //~| 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 {} }>) {} |
| 22 | 29 | //~| NOTE the const parameter `Q` is defined here |
| 23 | 30 | //~| NOTE `K` has type `&'r [A; Q]` |
| 24 | 31 | |
| 25 | trait Project { | |
| 32 | trait Project: ConstParamTy_ { | |
| 26 | 33 | #[type_const] |
| 27 | 34 | const SELF: Self; |
| 28 | 35 | } |
| ... | ... | @@ -38,7 +45,7 @@ fn take2<P: Project<SELF = {}>>(_: P) {} |
| 38 | 45 | //~| NOTE the type parameter `P` is defined here |
| 39 | 46 | //~| NOTE `SELF` has type `P` |
| 40 | 47 | |
| 41 | trait Iface<'r> { | |
| 48 | trait Iface<'r>: ConstParamTy_ { | |
| 42 | 49 | //~^ NOTE the lifetime parameter `'r` is defined here |
| 43 | 50 | //~| NOTE the lifetime parameter `'r` is defined here |
| 44 | 51 | 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 @@ |
| 1 | 1 | error: 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 | |
| 3 | 3 | | |
| 4 | LL | 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` | |
| 4 | LL | 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` | |
| 6 | 6 | | |
| 7 | 7 | = note: `K` has type `&'r [A; Q]` |
| 8 | 8 | |
| 9 | 9 | error: 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 | |
| 11 | 11 | | |
| 12 | LL | 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` | |
| 12 | LL | 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` | |
| 14 | 14 | | |
| 15 | 15 | = note: `K` has type `&'r [A; Q]` |
| 16 | 16 | |
| 17 | 17 | error: 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 | |
| 19 | 19 | | |
| 20 | LL | 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 | |
| 20 | LL | 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 | |
| 24 | 24 | | |
| 25 | 25 | = note: `K` has type `&'r [A; Q]` |
| 26 | 26 | |
| 27 | 27 | error: 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 | |
| 29 | 29 | | |
| 30 | 30 | LL | fn take1(_: impl Project<SELF = {}>) {} |
| 31 | 31 | | -------------^^^^------ |
| ... | ... | @@ -34,7 +34,7 @@ LL | fn take1(_: impl Project<SELF = {}>) {} |
| 34 | 34 | | the `impl Trait` is specified here |
| 35 | 35 | |
| 36 | 36 | error: 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 | |
| 38 | 38 | | |
| 39 | 39 | LL | fn take2<P: Project<SELF = {}>>(_: P) {} |
| 40 | 40 | | - ^^^^ its type must not depend on the type parameter `P` |
| ... | ... | @@ -44,9 +44,9 @@ LL | fn take2<P: Project<SELF = {}>>(_: P) {} |
| 44 | 44 | = note: `SELF` has type `P` |
| 45 | 45 | |
| 46 | 46 | error: 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 | |
| 48 | 48 | | |
| 49 | LL | trait Iface<'r> { | |
| 49 | LL | trait Iface<'r>: ConstParamTy_ { | |
| 50 | 50 | | -- the lifetime parameter `'r` is defined here |
| 51 | 51 | ... |
| 52 | 52 | LL | 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 {} }> |
| 55 | 55 | = note: `K` has type `&'r [Self; Q]` |
| 56 | 56 | |
| 57 | 57 | error: 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 | |
| 59 | 59 | | |
| 60 | 60 | LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }> |
| 61 | 61 | | ^ its type must not depend on `Self` |
| ... | ... | @@ -63,7 +63,7 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }> |
| 63 | 63 | = note: `K` has type `&'r [Self; Q]` |
| 64 | 64 | |
| 65 | 65 | error: 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 | |
| 67 | 67 | | |
| 68 | 68 | LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }> |
| 69 | 69 | | - ^ 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 {} }> |
| 73 | 73 | = note: `K` has type `&'r [Self; Q]` |
| 74 | 74 | |
| 75 | 75 | error: 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 | |
| 77 | 77 | | |
| 78 | LL | trait Iface<'r> { | |
| 78 | LL | trait Iface<'r>: ConstParamTy_ { | |
| 79 | 79 | | -- the lifetime parameter `'r` is defined here |
| 80 | 80 | ... |
| 81 | 81 | LL | 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 {} }> |
| 85 | 85 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 86 | 86 | |
| 87 | 87 | error: 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 | |
| 89 | 89 | | |
| 90 | 90 | LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }> |
| 91 | 91 | | ^ its type must not depend on `Self` |
| ... | ... | @@ -94,7 +94,7 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }> |
| 94 | 94 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 95 | 95 | |
| 96 | 96 | error: 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 | |
| 98 | 98 | | |
| 99 | 99 | LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }> |
| 100 | 100 | | - ^ 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 @@ |
| 3 | 3 | |
| 4 | 4 | //@ check-pass |
| 5 | 5 | |
| 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 | )] | |
| 7 | 12 | #![allow(incomplete_features)] |
| 8 | 13 | |
| 14 | use std::marker::ConstParamTy_; | |
| 15 | ||
| 9 | 16 | trait Trait: SuperTrait {} |
| 10 | 17 | trait SuperTrait: SuperSuperTrait<i32> {} |
| 11 | trait SuperSuperTrait<T> { | |
| 18 | trait SuperSuperTrait<T: ConstParamTy_> { | |
| 12 | 19 | #[type_const] |
| 13 | 20 | const K: T; |
| 14 | 21 | } |
tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs+1-1| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | |
| 6 | 6 | //@ check-pass |
| 7 | 7 | |
| 8 | #![feature(associated_const_equality, min_generic_const_args)] | |
| 8 | #![feature(associated_const_equality, min_generic_const_args, unsized_const_params)] | |
| 9 | 9 | #![allow(incomplete_features)] |
| 10 | 10 | |
| 11 | 11 | trait Trait: SuperTrait { |
tests/ui/const-generics/const_trait_fn-issue-88433.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Func<T> { | |
| 6 | const trait Func<T> { | |
| 8 | 7 | type Output; |
| 9 | 8 | |
| 10 | 9 | fn call_once(self, arg: T) -> Self::Output; |
tests/ui/const-generics/issues/issue-88119.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | #![allow(incomplete_features)] |
| 4 | 4 | #![feature(const_trait_impl, generic_const_exprs)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait ConstName { | |
| 6 | const trait ConstName { | |
| 8 | 7 | const NAME_BYTES: &'static [u8]; |
| 9 | 8 | } |
| 10 | 9 |
tests/ui/const-generics/issues/issue-88119.stderr+14-14| ... | ... | @@ -7,85 +7,85 @@ LL | #![feature(const_trait_impl, generic_const_exprs)] |
| 7 | 7 | = help: remove one of these features |
| 8 | 8 | |
| 9 | 9 | error[E0275]: overflow evaluating the requirement `&T: [const] ConstName` |
| 10 | --> $DIR/issue-88119.rs:19:49 | |
| 10 | --> $DIR/issue-88119.rs:18:49 | |
| 11 | 11 | | |
| 12 | 12 | LL | impl<T: ?Sized + ConstName> const ConstName for &T |
| 13 | 13 | | ^^ |
| 14 | 14 | |
| 15 | 15 | error[E0275]: overflow evaluating the requirement `&T: ConstName` |
| 16 | --> $DIR/issue-88119.rs:19:49 | |
| 16 | --> $DIR/issue-88119.rs:18:49 | |
| 17 | 17 | | |
| 18 | 18 | LL | impl<T: ?Sized + ConstName> const ConstName for &T |
| 19 | 19 | | ^^ |
| 20 | 20 | |
| 21 | 21 | error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed` |
| 22 | --> $DIR/issue-88119.rs:21:5 | |
| 22 | --> $DIR/issue-88119.rs:20:5 | |
| 23 | 23 | | |
| 24 | 24 | LL | [(); name_len::<T>()]:, |
| 25 | 25 | | ^^^^^^^^^^^^^^^^^^^^^ |
| 26 | 26 | | |
| 27 | 27 | note: required by a bound in `<&T as ConstName>` |
| 28 | --> $DIR/issue-88119.rs:21:5 | |
| 28 | --> $DIR/issue-88119.rs:20:5 | |
| 29 | 29 | | |
| 30 | 30 | LL | [(); name_len::<T>()]:, |
| 31 | 31 | | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` |
| 32 | 32 | |
| 33 | 33 | error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed` |
| 34 | --> $DIR/issue-88119.rs:21:10 | |
| 34 | --> $DIR/issue-88119.rs:20:10 | |
| 35 | 35 | | |
| 36 | 36 | LL | [(); name_len::<T>()]:, |
| 37 | 37 | | ^^^^^^^^^^^^^^^ |
| 38 | 38 | | |
| 39 | 39 | note: required by a bound in `<&T as ConstName>` |
| 40 | --> $DIR/issue-88119.rs:21:5 | |
| 40 | --> $DIR/issue-88119.rs:20:5 | |
| 41 | 41 | | |
| 42 | 42 | LL | [(); name_len::<T>()]:, |
| 43 | 43 | | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` |
| 44 | 44 | |
| 45 | 45 | error[E0275]: overflow evaluating the requirement `&mut T: [const] ConstName` |
| 46 | --> $DIR/issue-88119.rs:26:49 | |
| 46 | --> $DIR/issue-88119.rs:25:49 | |
| 47 | 47 | | |
| 48 | 48 | LL | impl<T: ?Sized + ConstName> const ConstName for &mut T |
| 49 | 49 | | ^^^^^^ |
| 50 | 50 | |
| 51 | 51 | error[E0275]: overflow evaluating the requirement `&mut T: ConstName` |
| 52 | --> $DIR/issue-88119.rs:26:49 | |
| 52 | --> $DIR/issue-88119.rs:25:49 | |
| 53 | 53 | | |
| 54 | 54 | LL | impl<T: ?Sized + ConstName> const ConstName for &mut T |
| 55 | 55 | | ^^^^^^ |
| 56 | 56 | |
| 57 | 57 | error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed` |
| 58 | --> $DIR/issue-88119.rs:28:5 | |
| 58 | --> $DIR/issue-88119.rs:27:5 | |
| 59 | 59 | | |
| 60 | 60 | LL | [(); name_len::<T>()]:, |
| 61 | 61 | | ^^^^^^^^^^^^^^^^^^^^^ |
| 62 | 62 | | |
| 63 | 63 | note: required by a bound in `<&mut T as ConstName>` |
| 64 | --> $DIR/issue-88119.rs:28:5 | |
| 64 | --> $DIR/issue-88119.rs:27:5 | |
| 65 | 65 | | |
| 66 | 66 | LL | [(); name_len::<T>()]:, |
| 67 | 67 | | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` |
| 68 | 68 | |
| 69 | 69 | error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed` |
| 70 | --> $DIR/issue-88119.rs:28:10 | |
| 70 | --> $DIR/issue-88119.rs:27:10 | |
| 71 | 71 | | |
| 72 | 72 | LL | [(); name_len::<T>()]:, |
| 73 | 73 | | ^^^^^^^^^^^^^^^ |
| 74 | 74 | | |
| 75 | 75 | note: required by a bound in `<&mut T as ConstName>` |
| 76 | --> $DIR/issue-88119.rs:28:5 | |
| 76 | --> $DIR/issue-88119.rs:27:5 | |
| 77 | 77 | | |
| 78 | 78 | LL | [(); name_len::<T>()]:, |
| 79 | 79 | | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` |
| 80 | 80 | |
| 81 | 81 | error[E0275]: overflow evaluating the requirement `&&mut u8: ConstName` |
| 82 | --> $DIR/issue-88119.rs:33:35 | |
| 82 | --> $DIR/issue-88119.rs:32:35 | |
| 83 | 83 | | |
| 84 | 84 | LL | pub const ICE_1: &'static [u8] = <&&mut u8 as ConstName>::NAME_BYTES; |
| 85 | 85 | | ^^^^^^^^ |
| 86 | 86 | |
| 87 | 87 | error[E0275]: overflow evaluating the requirement `&mut &u8: ConstName` |
| 88 | --> $DIR/issue-88119.rs:34:35 | |
| 88 | --> $DIR/issue-88119.rs:33:35 | |
| 89 | 89 | | |
| 90 | 90 | LL | pub const ICE_2: &'static [u8] = <&mut &u8 as ConstName>::NAME_BYTES; |
| 91 | 91 | | ^^^^^^^^ |
tests/ui/const-generics/issues/issue-98629.rs+1-2| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | #![feature(const_trait_impl)] |
| 2 | 2 | |
| 3 | #[const_trait] | |
| 4 | trait Trait { | |
| 3 | const trait Trait { | |
| 5 | 4 | const N: usize; |
| 6 | 5 | } |
| 7 | 6 |
tests/ui/const-generics/issues/issue-98629.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[E0046]: not all trait items implemented, missing: `N` |
| 2 | --> $DIR/issue-98629.rs:8:1 | |
| 2 | --> $DIR/issue-98629.rs:7:1 | |
| 3 | 3 | | |
| 4 | 4 | LL | const N: usize; |
| 5 | 5 | | -------------- `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 | ||
| 6 | pub 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 | ||
| 15 | pub struct S; | |
| 16 | ||
| 17 | impl<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 | ||
| 26 | fn 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 | ||
| 6 | const C: usize = 0; | |
| 7 | pub struct A<const M: usize> {} | |
| 8 | impl A<C> { | |
| 9 | fn fun1() {} | |
| 10 | //~^ ERROR duplicate definitions with name `fun1` | |
| 11 | } | |
| 12 | impl A { | |
| 13 | //~^ ERROR missing generics for struct `A` | |
| 14 | fn fun1() {} | |
| 15 | } | |
| 16 | ||
| 17 | fn main() {} |
tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr created+29| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | error[E0107]: missing generics for struct `A` | |
| 2 | --> $DIR/const-arg-coherence-conflicting-methods.rs:12:6 | |
| 3 | | | |
| 4 | LL | impl A { | |
| 5 | | ^ expected 1 generic argument | |
| 6 | | | |
| 7 | note: struct defined here, with 1 generic parameter: `M` | |
| 8 | --> $DIR/const-arg-coherence-conflicting-methods.rs:7:12 | |
| 9 | | | |
| 10 | LL | pub struct A<const M: usize> {} | |
| 11 | | ^ -------------- | |
| 12 | help: add missing generic argument | |
| 13 | | | |
| 14 | LL | impl A<M> { | |
| 15 | | +++ | |
| 16 | ||
| 17 | error[E0592]: duplicate definitions with name `fun1` | |
| 18 | --> $DIR/const-arg-coherence-conflicting-methods.rs:9:5 | |
| 19 | | | |
| 20 | LL | fn fun1() {} | |
| 21 | | ^^^^^^^^^ duplicate definitions for `fun1` | |
| 22 | ... | |
| 23 | LL | fn fun1() {} | |
| 24 | | --------- other definition for `fun1` | |
| 25 | ||
| 26 | error: aborting due to 2 previous errors | |
| 27 | ||
| 28 | Some errors have detailed explanations: E0107, E0592. | |
| 29 | For 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] | |
| 5 | const FREE: u32 = 5_usize; | |
| 6 | //~^ ERROR mismatched types | |
| 7 | ||
| 8 | #[type_const] | |
| 9 | const FREE2: isize = FREE; | |
| 10 | //~^ ERROR the constant `5` is not of type `isize` | |
| 11 | ||
| 12 | trait Tr { | |
| 13 | #[type_const] | |
| 14 | const N: usize; | |
| 15 | } | |
| 16 | ||
| 17 | impl Tr for () { | |
| 18 | #[type_const] | |
| 19 | const N: usize = false; | |
| 20 | //~^ ERROR mismatched types | |
| 21 | } | |
| 22 | ||
| 23 | fn main() {} |
tests/ui/const-generics/mgca/type_const-mismatched-types.stderr created+27| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | error: the constant `5` is not of type `isize` | |
| 2 | --> $DIR/type_const-mismatched-types.rs:9:1 | |
| 3 | | | |
| 4 | LL | const FREE2: isize = FREE; | |
| 5 | | ^^^^^^^^^^^^^^^^^^ expected `isize`, found `u32` | |
| 6 | ||
| 7 | error[E0308]: mismatched types | |
| 8 | --> $DIR/type_const-mismatched-types.rs:5:19 | |
| 9 | | | |
| 10 | LL | const FREE: u32 = 5_usize; | |
| 11 | | ^^^^^^^ expected `u32`, found `usize` | |
| 12 | | | |
| 13 | help: change the type of the numeric literal from `usize` to `u32` | |
| 14 | | | |
| 15 | LL - const FREE: u32 = 5_usize; | |
| 16 | LL + const FREE: u32 = 5_u32; | |
| 17 | | | |
| 18 | ||
| 19 | error[E0308]: mismatched types | |
| 20 | --> $DIR/type_const-mismatched-types.rs:19:22 | |
| 21 | | | |
| 22 | LL | const N: usize = false; | |
| 23 | | ^^^^^ expected `usize`, found `bool` | |
| 24 | ||
| 25 | error: aborting due to 3 previous errors | |
| 26 | ||
| 27 | For 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 | ||
| 4 | struct 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] | |
| 9 | const FREE: S = { { S } }; | |
| 10 | //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter | |
| 11 | ||
| 12 | trait 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 | ||
| 18 | impl 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 | ||
| 26 | fn main() {} |
tests/ui/const-generics/mgca/type_const-not-constparamty.stderr created+39| ... | ... | @@ -0,0 +1,39 @@ |
| 1 | error[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 | | | |
| 4 | LL | const FREE: S = { { S } }; | |
| 5 | | ^ | |
| 6 | | | |
| 7 | help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct | |
| 8 | | | |
| 9 | LL + #[derive(ConstParamTy, PartialEq, Eq)] | |
| 10 | LL | struct S; | |
| 11 | | | |
| 12 | ||
| 13 | error[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 | | | |
| 16 | LL | const N: S = { { S } }; | |
| 17 | | ^ | |
| 18 | | | |
| 19 | help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct | |
| 20 | | | |
| 21 | LL + #[derive(ConstParamTy, PartialEq, Eq)] | |
| 22 | LL | struct S; | |
| 23 | | | |
| 24 | ||
| 25 | error[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 | | | |
| 28 | LL | const N: S; | |
| 29 | | ^ | |
| 30 | | | |
| 31 | help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct | |
| 32 | | | |
| 33 | LL + #[derive(ConstParamTy, PartialEq, Eq)] | |
| 34 | LL | struct S; | |
| 35 | | | |
| 36 | ||
| 37 | error: aborting due to 3 previous errors | |
| 38 | ||
| 39 | For 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] | |
| 5 | const FREE1<T>: usize = std::mem::size_of::<T>(); | |
| 6 | //~^ ERROR generic parameters may not be used in const operations | |
| 7 | #[type_const] | |
| 8 | const FREE2<const I: usize>: usize = I + 1; | |
| 9 | //~^ ERROR generic parameters may not be used in const operations | |
| 10 | ||
| 11 | pub 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 | ||
| 20 | pub struct S; | |
| 21 | ||
| 22 | impl<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 | ||
| 34 | fn main() {} |
tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr created+47| ... | ... | @@ -0,0 +1,47 @@ |
| 1 | error: generic parameters may not be used in const operations | |
| 2 | --> $DIR/type_const-on-generic-expr.rs:5:45 | |
| 3 | | | |
| 4 | LL | 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 | ||
| 10 | error: generic parameters may not be used in const operations | |
| 11 | --> $DIR/type_const-on-generic-expr.rs:8:38 | |
| 12 | | | |
| 13 | LL | 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 | ||
| 19 | error: generic parameters may not be used in const operations | |
| 20 | --> $DIR/type_const-on-generic-expr.rs:24:46 | |
| 21 | | | |
| 22 | LL | 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 | ||
| 28 | error: generic parameters may not be used in const operations | |
| 29 | --> $DIR/type_const-on-generic-expr.rs:27:39 | |
| 30 | | | |
| 31 | LL | 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 | ||
| 37 | error: generic parameters may not be used in const operations | |
| 38 | --> $DIR/type_const-on-generic-expr.rs:30:27 | |
| 39 | | | |
| 40 | LL | 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 | ||
| 46 | error: 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 | ||
| 4 | trait GoodTr { | |
| 5 | #[type_const] | |
| 6 | const NUM: usize; | |
| 7 | } | |
| 8 | ||
| 9 | struct BadS; | |
| 10 | ||
| 11 | impl GoodTr for BadS { | |
| 12 | const NUM: usize = 42; | |
| 13 | //~^ ERROR implementation of `#[type_const]` const must be marked with `#[type_const]` | |
| 14 | } | |
| 15 | ||
| 16 | fn accept_good_tr<const N: usize, T: GoodTr<NUM = { N }>>(_x: &T) {} | |
| 17 | ||
| 18 | fn main() { | |
| 19 | accept_good_tr(&BadS); | |
| 20 | } |
tests/ui/const-generics/mgca/type_const-only-in-trait.stderr created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | error: implementation of `#[type_const]` const must be marked with `#[type_const]` | |
| 2 | --> $DIR/type_const-only-in-trait.rs:12:5 | |
| 3 | | | |
| 4 | LL | const NUM: usize = 42; | |
| 5 | | ^^^^^^^^^^^^^^^^ | |
| 6 | | | |
| 7 | note: trait declaration of const is marked with `#[type_const]` | |
| 8 | --> $DIR/type_const-only-in-trait.rs:5:5 | |
| 9 | | | |
| 10 | LL | #[type_const] | |
| 11 | | ^^^^^^^^^^^^^ | |
| 12 | LL | const NUM: usize; | |
| 13 | | ^^^^^^^^^^^^^^^^ | |
| 14 | ||
| 15 | error: 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 | ||
| 6 | trait Trait { | |
| 7 | #[type_const] | |
| 8 | const F: fn(); | |
| 9 | //~^ ERROR using function pointers as const generic parameters is forbidden | |
| 10 | } | |
| 11 | ||
| 12 | fn take(_: impl Trait<F = { || {} }>) {} | |
| 13 | ||
| 14 | fn main() {} |
tests/ui/const-generics/mgca/using-fnptr-as-type_const.stderr created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | error[E0741]: using function pointers as const generic parameters is forbidden | |
| 2 | --> $DIR/using-fnptr-as-type_const.rs:8:14 | |
| 3 | | | |
| 4 | LL | const F: fn(); | |
| 5 | | ^^^^ | |
| 6 | ||
| 7 | error: aborting due to 1 previous error | |
| 8 | ||
| 9 | For more information about this error, try `rustc --explain E0741`. |
tests/ui/consts/constifconst-call-in-const-position.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | #![feature(const_trait_impl, generic_const_exprs)] |
| 4 | 4 | #![allow(incomplete_features)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | pub trait Tr { | |
| 6 | pub const trait Tr { | |
| 8 | 7 | fn a() -> usize; |
| 9 | 8 | } |
| 10 | 9 |
tests/ui/consts/constifconst-call-in-const-position.stderr+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | const fn foo<T: [const] Tr>() -> [u8; T::a()] { |
| 5 | 5 | | ^ |
| 6 | 6 | |
| 7 | 7 | error[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 | |
| 9 | 9 | | |
| 10 | 10 | LL | [0; T::a()] |
| 11 | 11 | | ^ |
tests/ui/delegation/unsupported.current.stderr+1-1| ... | ... | @@ -46,7 +46,7 @@ LL | reuse to_reuse1::foo; |
| 46 | 46 | | ^^^ |
| 47 | 47 | |
| 48 | 48 | error[E0283]: type annotations needed |
| 49 | --> $DIR/unsupported.rs:56:18 | |
| 49 | --> $DIR/unsupported.rs:55:18 | |
| 50 | 50 | | |
| 51 | 51 | LL | reuse Trait::foo; |
| 52 | 52 | | ^^^ cannot infer type |
tests/ui/delegation/unsupported.next.stderr+1-1| ... | ... | @@ -38,7 +38,7 @@ LL | reuse to_reuse1::foo; |
| 38 | 38 | | ^^^ |
| 39 | 39 | |
| 40 | 40 | error[E0283]: type annotations needed |
| 41 | --> $DIR/unsupported.rs:56:18 | |
| 41 | --> $DIR/unsupported.rs:55:18 | |
| 42 | 42 | | |
| 43 | 43 | LL | reuse Trait::foo; |
| 44 | 44 | | ^^^ cannot infer type |
tests/ui/delegation/unsupported.rs+1-2| ... | ... | @@ -48,8 +48,7 @@ mod recursive { |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 50 | mod effects { |
| 51 | #[const_trait] | |
| 52 | trait Trait { | |
| 51 | const trait Trait { | |
| 53 | 52 | fn foo(); |
| 54 | 53 | } |
| 55 | 54 |
tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | // ICE: assertion failed: !value.has_infer() |
| 2 | 2 | // 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)] | |
| 4 | 4 | #![allow(incomplete_features)] |
| 5 | 5 | |
| 6 | 6 | pub struct NoPin; |
tests/ui/generic-const-items/associated-const-equality.rs+7-5| ... | ... | @@ -9,8 +9,8 @@ trait Owner { |
| 9 | 9 | const C<const N: u32>: u32; |
| 10 | 10 | #[type_const] |
| 11 | 11 | const K<const N: u32>: u32; |
| 12 | #[type_const] | |
| 13 | const Q<T>: Maybe<T>; | |
| 12 | // #[type_const] | |
| 13 | // const Q<T>: Maybe<T>; | |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | 16 | impl Owner for () { |
| ... | ... | @@ -18,13 +18,15 @@ impl Owner for () { |
| 18 | 18 | const C<const N: u32>: u32 = N; |
| 19 | 19 | #[type_const] |
| 20 | 20 | 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; | |
| 23 | 24 | } |
| 24 | 25 | |
| 25 | 26 | fn take0<const N: u32>(_: impl Owner<C<N> = { N }>) {} |
| 26 | 27 | fn take1(_: impl Owner<K<99> = 100>) {} |
| 27 | fn 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(()) }>) {} | |
| 28 | 30 | |
| 29 | 31 | fn main() { |
| 30 | 32 | 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(); |
| 11 | 11 | pub const K0: i32 = CREATE::<i32>; |
| 12 | 12 | pub const K1: i32 = CREATE; // arg inferred |
| 13 | 13 | |
| 14 | #[const_trait] | |
| 15 | trait Create { | |
| 14 | const trait Create { | |
| 16 | 15 | fn create() -> Self; |
| 17 | 16 | } |
| 18 | 17 | |
| ... | ... | @@ -22,7 +21,7 @@ impl const Create for i32 { |
| 22 | 21 | } |
| 23 | 22 | } |
| 24 | 23 | |
| 25 | trait Mod { // doesn't need to be a `#[const_trait]` | |
| 24 | trait Mod { // doesn't need to be a const trait | |
| 26 | 25 | const CREATE<T: const Create>: T; |
| 27 | 26 | } |
| 28 | 27 |
tests/ui/parser/impls-nested-within-fns-semantic-1.rs+1-2| ... | ... | @@ -4,8 +4,7 @@ |
| 4 | 4 | |
| 5 | 5 | #![feature(const_trait_impl)] |
| 6 | 6 | |
| 7 | #[const_trait] | |
| 8 | trait Trait { | |
| 7 | const trait Trait { | |
| 9 | 8 | fn required(); |
| 10 | 9 | } |
| 11 | 10 |
tests/ui/resolve/issue-39559-2.stderr+6-8| ... | ... | @@ -11,13 +11,12 @@ LL | trait Dim { |
| 11 | 11 | | ^^^^^^^^^ this trait is not const |
| 12 | 12 | LL | fn dim() -> usize; |
| 13 | 13 | | ------------------ 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 | |
| 15 | 15 | = note: calls in constants are limited to constant functions, tuple structs and tuple variants |
| 16 | 16 | help: consider making trait `Dim` const |
| 17 | 17 | | |
| 18 | LL + #[const_trait] | |
| 19 | LL | trait Dim { | |
| 20 | | | |
| 18 | LL | const trait Dim { | |
| 19 | | +++++ | |
| 21 | 20 | |
| 22 | 21 | error[E0015]: cannot call non-const associated function `<Dim3 as Dim>::dim` in constants |
| 23 | 22 | --> $DIR/issue-39559-2.rs:16:15 |
| ... | ... | @@ -32,13 +31,12 @@ LL | trait Dim { |
| 32 | 31 | | ^^^^^^^^^ this trait is not const |
| 33 | 32 | LL | fn dim() -> usize; |
| 34 | 33 | | ------------------ 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 | |
| 36 | 35 | = note: calls in constants are limited to constant functions, tuple structs and tuple variants |
| 37 | 36 | help: consider making trait `Dim` const |
| 38 | 37 | | |
| 39 | LL + #[const_trait] | |
| 40 | LL | trait Dim { | |
| 41 | | | |
| 38 | LL | const trait Dim { | |
| 39 | | +++++ | |
| 42 | 40 | |
| 43 | 41 | error: aborting due to 2 previous errors |
| 44 | 42 |
tests/ui/specialization/const_trait_impl.rs+3-6| ... | ... | @@ -5,14 +5,12 @@ |
| 5 | 5 | use std::fmt::Debug; |
| 6 | 6 | |
| 7 | 7 | #[rustc_specialization_trait] |
| 8 | #[const_trait] | |
| 9 | pub unsafe trait Sup { | |
| 8 | pub const unsafe trait Sup { | |
| 10 | 9 | fn foo() -> u32; |
| 11 | 10 | } |
| 12 | 11 | |
| 13 | 12 | #[rustc_specialization_trait] |
| 14 | #[const_trait] | |
| 15 | pub unsafe trait Sub: [const] Sup {} | |
| 13 | pub const unsafe trait Sub: [const] Sup {} | |
| 16 | 14 | |
| 17 | 15 | unsafe impl const Sup for u8 { |
| 18 | 16 | default fn foo() -> u32 { |
| ... | ... | @@ -28,8 +26,7 @@ unsafe impl const Sup for () { |
| 28 | 26 | |
| 29 | 27 | unsafe impl const Sub for () {} |
| 30 | 28 | |
| 31 | #[const_trait] | |
| 32 | pub trait A { | |
| 29 | pub const trait A { | |
| 33 | 30 | fn a() -> u32; |
| 34 | 31 | } |
| 35 | 32 |
tests/ui/specialization/const_trait_impl.stderr+6-6| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error: `[const]` can only be applied to `const` traits |
| 2 | --> $DIR/const_trait_impl.rs:36:9 | |
| 2 | --> $DIR/const_trait_impl.rs:33:9 | |
| 3 | 3 | | |
| 4 | 4 | LL | impl<T: [const] Debug> const A for T { |
| 5 | 5 | | ^^^^^^^ can't be applied to `Debug` |
| ... | ... | @@ -8,7 +8,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const` |
| 8 | 8 | --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL |
| 9 | 9 | |
| 10 | 10 | error: `[const]` can only be applied to `const` traits |
| 11 | --> $DIR/const_trait_impl.rs:42:9 | |
| 11 | --> $DIR/const_trait_impl.rs:39:9 | |
| 12 | 12 | | |
| 13 | 13 | LL | impl<T: [const] Debug + [const] Sup> const A for T { |
| 14 | 14 | | ^^^^^^^ can't be applied to `Debug` |
| ... | ... | @@ -17,7 +17,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const` |
| 17 | 17 | --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL |
| 18 | 18 | |
| 19 | 19 | error: `[const]` can only be applied to `const` traits |
| 20 | --> $DIR/const_trait_impl.rs:48:9 | |
| 20 | --> $DIR/const_trait_impl.rs:45:9 | |
| 21 | 21 | | |
| 22 | 22 | LL | impl<T: [const] Debug + [const] Sub> const A for T { |
| 23 | 23 | | ^^^^^^^ can't be applied to `Debug` |
| ... | ... | @@ -26,7 +26,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const` |
| 26 | 26 | --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL |
| 27 | 27 | |
| 28 | 28 | error: `[const]` can only be applied to `const` traits |
| 29 | --> $DIR/const_trait_impl.rs:42:9 | |
| 29 | --> $DIR/const_trait_impl.rs:39:9 | |
| 30 | 30 | | |
| 31 | 31 | LL | impl<T: [const] Debug + [const] Sup> const A for T { |
| 32 | 32 | | ^^^^^^^ can't be applied to `Debug` |
| ... | ... | @@ -36,7 +36,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const` |
| 36 | 36 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 37 | 37 | |
| 38 | 38 | error: `[const]` can only be applied to `const` traits |
| 39 | --> $DIR/const_trait_impl.rs:36:9 | |
| 39 | --> $DIR/const_trait_impl.rs:33:9 | |
| 40 | 40 | | |
| 41 | 41 | LL | impl<T: [const] Debug> const A for T { |
| 42 | 42 | | ^^^^^^^ can't be applied to `Debug` |
| ... | ... | @@ -46,7 +46,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const` |
| 46 | 46 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 47 | 47 | |
| 48 | 48 | error: `[const]` can only be applied to `const` traits |
| 49 | --> $DIR/const_trait_impl.rs:48:9 | |
| 49 | --> $DIR/const_trait_impl.rs:45:9 | |
| 50 | 50 | | |
| 51 | 51 | LL | impl<T: [const] Debug + [const] Sub> const A for T { |
| 52 | 52 | | ^^^^^^^ can't be applied to `Debug` |
tests/ui/structs/default-field-values/support.rs+1-1| ... | ... | @@ -27,7 +27,7 @@ pub enum Bar { |
| 27 | 27 | } |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | #[const_trait] pub trait ConstDefault { | |
| 30 | pub const trait ConstDefault { | |
| 31 | 31 | fn value() -> Self; |
| 32 | 32 | } |
| 33 | 33 |
tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs+1-2| ... | ... | @@ -4,8 +4,7 @@ |
| 4 | 4 | |
| 5 | 5 | #![feature(const_trait_impl)] |
| 6 | 6 | |
| 7 | #[const_trait] | |
| 8 | trait Trait { | |
| 7 | const trait Trait { | |
| 9 | 8 | type Assoc: [const] Trait; |
| 10 | 9 | fn func() -> i32; |
| 11 | 10 | } |
tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | #![feature(const_trait_impl, generic_const_exprs)] |
| 4 | 4 | #![allow(incomplete_features)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Trait { | |
| 6 | const trait Trait { | |
| 8 | 7 | type Assoc: [const] Trait; |
| 9 | 8 | fn func() -> i32; |
| 10 | 9 | } |
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | T::Assoc::<U>::func(); |
| 5 | 5 | | ^^^^^^^^^^^^^ |
| 6 | 6 | |
| 7 | 7 | error[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 | |
| 9 | 9 | | |
| 10 | 10 | LL | <T as Trait>::Assoc::<U>::func(); |
| 11 | 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^ |
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | T::Assoc::<U>::func(); |
| 5 | 5 | | ^^^^^^^^^^^^^ |
| 6 | 6 | |
| 7 | 7 | error[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 | |
| 9 | 9 | | |
| 10 | 10 | LL | <T as Trait>::Assoc::<U>::func(); |
| 11 | 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^ |
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs+2-4| ... | ... | @@ -8,8 +8,7 @@ |
| 8 | 8 | |
| 9 | 9 | #![feature(const_trait_impl)] |
| 10 | 10 | |
| 11 | #[const_trait] | |
| 12 | trait Trait { | |
| 11 | const trait Trait { | |
| 13 | 12 | type Assoc<U>: [const] Trait |
| 14 | 13 | where |
| 15 | 14 | U: [const] Other; |
| ... | ... | @@ -17,8 +16,7 @@ trait Trait { |
| 17 | 16 | fn func(); |
| 18 | 17 | } |
| 19 | 18 | |
| 20 | #[const_trait] | |
| 21 | trait Other {} | |
| 19 | const trait Other {} | |
| 22 | 20 | |
| 23 | 21 | const fn fails<T: [const] Trait, U: Other>() { |
| 24 | 22 | T::Assoc::<U>::func(); |
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.current.stderr+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | T::Assoc::func(); |
| 5 | 5 | | ^^^^^^^^ |
| 6 | 6 | |
| 7 | 7 | error[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 | |
| 9 | 9 | | |
| 10 | 10 | LL | <T as Trait>::Assoc::func(); |
| 11 | 11 | | ^^^^^^^^^^^^^^^^^^^ |
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | T::Assoc::func(); |
| 5 | 5 | | ^^^^^^^^ |
| 6 | 6 | |
| 7 | 7 | error[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 | |
| 9 | 9 | | |
| 10 | 10 | LL | <T as Trait>::Assoc::func(); |
| 11 | 11 | | ^^^^^^^^^^^^^^^^^^^ |
tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs+1-2| ... | ... | @@ -7,8 +7,7 @@ |
| 7 | 7 | |
| 8 | 8 | #![feature(const_trait_impl)] |
| 9 | 9 | |
| 10 | #[const_trait] | |
| 11 | trait Trait { | |
| 10 | const trait Trait { | |
| 12 | 11 | type Assoc: [const] Trait; |
| 13 | 12 | fn func(); |
| 14 | 13 | } |
tests/ui/traits/const-traits/assoc-type.current.stderr+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | error[E0277]: the trait bound `NonConstAdd: [const] Add` is not satisfied |
| 2 | --> $DIR/assoc-type.rs:37:16 | |
| 2 | --> $DIR/assoc-type.rs:35:16 | |
| 3 | 3 | | |
| 4 | 4 | LL | type Bar = NonConstAdd; |
| 5 | 5 | | ^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | 7 | note: required by a bound in `Foo::Bar` |
| 8 | --> $DIR/assoc-type.rs:33:15 | |
| 8 | --> $DIR/assoc-type.rs:31:15 | |
| 9 | 9 | | |
| 10 | 10 | LL | type Bar: [const] Add; |
| 11 | 11 | | ^^^^^^^^^^^ required by this bound in `Foo::Bar` |
tests/ui/traits/const-traits/assoc-type.next.stderr+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | error[E0277]: the trait bound `NonConstAdd: [const] Add` is not satisfied |
| 2 | --> $DIR/assoc-type.rs:37:16 | |
| 2 | --> $DIR/assoc-type.rs:35:16 | |
| 3 | 3 | | |
| 4 | 4 | LL | type Bar = NonConstAdd; |
| 5 | 5 | | ^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | 7 | note: required by a bound in `Foo::Bar` |
| 8 | --> $DIR/assoc-type.rs:33:15 | |
| 8 | --> $DIR/assoc-type.rs:31:15 | |
| 9 | 9 | | |
| 10 | 10 | LL | type Bar: [const] Add; |
| 11 | 11 | | ^^^^^^^^^^^ required by this bound in `Foo::Bar` |
tests/ui/traits/const-traits/assoc-type.rs+3-6| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Add<Rhs = Self> { | |
| 6 | const trait Add<Rhs = Self> { | |
| 8 | 7 | type Output; |
| 9 | 8 | |
| 10 | 9 | fn add(self, other: Rhs) -> Self::Output; |
| ... | ... | @@ -28,8 +27,7 @@ impl Add for NonConstAdd { |
| 28 | 27 | } |
| 29 | 28 | } |
| 30 | 29 | |
| 31 | #[const_trait] | |
| 32 | trait Foo { | |
| 30 | const trait Foo { | |
| 33 | 31 | type Bar: [const] Add; |
| 34 | 32 | } |
| 35 | 33 | |
| ... | ... | @@ -38,8 +36,7 @@ impl const Foo for NonConstAdd { |
| 38 | 36 | //~^ ERROR the trait bound `NonConstAdd: [const] Add` is not satisfied |
| 39 | 37 | } |
| 40 | 38 | |
| 41 | #[const_trait] | |
| 42 | trait Baz { | |
| 39 | const trait Baz { | |
| 43 | 40 | type Qux: Add; |
| 44 | 41 | } |
| 45 | 42 |
tests/ui/traits/const-traits/attr-misuse.rs deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | #![feature(const_trait_impl)] | |
| 2 | ||
| 3 | #[const_trait] | |
| 4 | trait 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 | |
| 10 | fn main() {} |
tests/ui/traits/const-traits/attr-misuse.stderr deleted-18| ... | ... | @@ -1,18 +0,0 @@ |
| 1 | error: `#[const_trait]` attribute cannot be used on required trait methods | |
| 2 | --> $DIR/attr-misuse.rs:5:5 | |
| 3 | | | |
| 4 | LL | #[const_trait] | |
| 5 | | ^^^^^^^^^^^^^^ | |
| 6 | | | |
| 7 | = help: `#[const_trait]` can only be applied to traits | |
| 8 | ||
| 9 | error: `#[const_trait]` attribute cannot be used on functions | |
| 10 | --> $DIR/attr-misuse.rs:9:1 | |
| 11 | | | |
| 12 | LL | #[const_trait] | |
| 13 | | ^^^^^^^^^^^^^^ | |
| 14 | | | |
| 15 | = help: `#[const_trait]` can only be applied to traits | |
| 16 | ||
| 17 | error: aborting due to 2 previous errors | |
| 18 |
tests/ui/traits/const-traits/auxiliary/cross-crate.rs+1-2| ... | ... | @@ -1,8 +1,7 @@ |
| 1 | 1 | //@ compile-flags: -Znext-solver |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | |
| 4 | #[const_trait] | |
| 5 | pub trait MyTrait { | |
| 4 | pub const trait MyTrait { | |
| 6 | 5 | fn defaulted_func(&self) {} |
| 7 | 6 | fn func(self); |
| 8 | 7 | } |
tests/ui/traits/const-traits/auxiliary/minicore.rs+17-34| ... | ... | @@ -35,8 +35,7 @@ impl Copy for u8 {} |
| 35 | 35 | impl<T: PointeeSized> Copy for &T {} |
| 36 | 36 | |
| 37 | 37 | #[lang = "add"] |
| 38 | #[const_trait] | |
| 39 | pub trait Add<Rhs = Self> { | |
| 38 | pub const trait Add<Rhs = Self> { | |
| 40 | 39 | type Output; |
| 41 | 40 | |
| 42 | 41 | fn add(self, rhs: Rhs) -> Self::Output; |
| ... | ... | @@ -58,8 +57,7 @@ const fn bar() { |
| 58 | 57 | } |
| 59 | 58 | |
| 60 | 59 | #[lang = "Try"] |
| 61 | #[const_trait] | |
| 62 | pub trait Try: FromResidual<Self::Residual> { | |
| 60 | pub const trait Try: FromResidual<Self::Residual> { | |
| 63 | 61 | type Output; |
| 64 | 62 | type Residual; |
| 65 | 63 | |
| ... | ... | @@ -70,8 +68,7 @@ pub trait Try: FromResidual<Self::Residual> { |
| 70 | 68 | fn branch(self) -> ControlFlow<Self::Residual, Self::Output>; |
| 71 | 69 | } |
| 72 | 70 | |
| 73 | #[const_trait] | |
| 74 | pub trait FromResidual<R = <Self as Try>::Residual> { | |
| 71 | pub const trait FromResidual<R = <Self as Try>::Residual> { | |
| 75 | 72 | #[lang = "from_residual"] |
| 76 | 73 | fn from_residual(residual: R) -> Self; |
| 77 | 74 | } |
| ... | ... | @@ -83,24 +80,21 @@ enum ControlFlow<B, C = ()> { |
| 83 | 80 | Break(B), |
| 84 | 81 | } |
| 85 | 82 | |
| 86 | #[const_trait] | |
| 87 | 83 | #[lang = "fn"] |
| 88 | 84 | #[rustc_paren_sugar] |
| 89 | pub trait Fn<Args: Tuple>: [const] FnMut<Args> { | |
| 85 | pub const trait Fn<Args: Tuple>: [const] FnMut<Args> { | |
| 90 | 86 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; |
| 91 | 87 | } |
| 92 | 88 | |
| 93 | #[const_trait] | |
| 94 | 89 | #[lang = "fn_mut"] |
| 95 | 90 | #[rustc_paren_sugar] |
| 96 | pub trait FnMut<Args: Tuple>: [const] FnOnce<Args> { | |
| 91 | pub const trait FnMut<Args: Tuple>: [const] FnOnce<Args> { | |
| 97 | 92 | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; |
| 98 | 93 | } |
| 99 | 94 | |
| 100 | #[const_trait] | |
| 101 | 95 | #[lang = "fn_once"] |
| 102 | 96 | #[rustc_paren_sugar] |
| 103 | pub trait FnOnce<Args: Tuple> { | |
| 97 | pub const trait FnOnce<Args: Tuple> { | |
| 104 | 98 | #[lang = "fn_once_output"] |
| 105 | 99 | type Output; |
| 106 | 100 | |
| ... | ... | @@ -128,20 +122,17 @@ impl<T: Deref + MetaSized> Receiver for T { |
| 128 | 122 | } |
| 129 | 123 | |
| 130 | 124 | #[lang = "destruct"] |
| 131 | #[const_trait] | |
| 132 | pub trait Destruct {} | |
| 125 | pub const trait Destruct {} | |
| 133 | 126 | |
| 134 | 127 | #[lang = "freeze"] |
| 135 | 128 | pub unsafe auto trait Freeze {} |
| 136 | 129 | |
| 137 | 130 | #[lang = "drop"] |
| 138 | #[const_trait] | |
| 139 | pub trait Drop { | |
| 131 | pub const trait Drop { | |
| 140 | 132 | fn drop(&mut self); |
| 141 | 133 | } |
| 142 | 134 | |
| 143 | #[const_trait] | |
| 144 | pub trait Residual<O> { | |
| 135 | pub const trait Residual<O> { | |
| 145 | 136 | type TryType: [const] Try<Output = O, Residual = Self> + Try<Output = O, Residual = Self>; |
| 146 | 137 | } |
| 147 | 138 | |
| ... | ... | @@ -168,15 +159,13 @@ const fn panic_display() { |
| 168 | 159 | fn panic_fmt() {} |
| 169 | 160 | |
| 170 | 161 | #[lang = "index"] |
| 171 | #[const_trait] | |
| 172 | pub trait Index<Idx: PointeeSized> { | |
| 162 | pub const trait Index<Idx: PointeeSized> { | |
| 173 | 163 | type Output: MetaSized; |
| 174 | 164 | |
| 175 | 165 | fn index(&self, index: Idx) -> &Self::Output; |
| 176 | 166 | } |
| 177 | 167 | |
| 178 | #[const_trait] | |
| 179 | pub unsafe trait SliceIndex<T: PointeeSized> { | |
| 168 | pub const unsafe trait SliceIndex<T: PointeeSized> { | |
| 180 | 169 | type Output: MetaSized; |
| 181 | 170 | fn index(self, slice: &T) -> &Self::Output; |
| 182 | 171 | } |
| ... | ... | @@ -214,8 +203,7 @@ pub trait CoerceUnsized<T: PointeeSized> {} |
| 214 | 203 | impl<'a, 'b: 'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {} |
| 215 | 204 | |
| 216 | 205 | #[lang = "deref"] |
| 217 | #[const_trait] | |
| 218 | pub trait Deref { | |
| 206 | pub const trait Deref { | |
| 219 | 207 | #[lang = "deref_target"] |
| 220 | 208 | type Target: MetaSized; |
| 221 | 209 | |
| ... | ... | @@ -273,13 +261,11 @@ where |
| 273 | 261 | } |
| 274 | 262 | } |
| 275 | 263 | |
| 276 | #[const_trait] | |
| 277 | pub trait Into<T>: Sized { | |
| 264 | pub const trait Into<T>: Sized { | |
| 278 | 265 | fn into(self) -> T; |
| 279 | 266 | } |
| 280 | 267 | |
| 281 | #[const_trait] | |
| 282 | pub trait From<T>: Sized { | |
| 268 | pub const trait From<T>: Sized { | |
| 283 | 269 | fn from(value: T) -> Self; |
| 284 | 270 | } |
| 285 | 271 | |
| ... | ... | @@ -313,8 +299,7 @@ fn from_str(s: &str) -> Result<bool, ()> { |
| 313 | 299 | } |
| 314 | 300 | |
| 315 | 301 | #[lang = "eq"] |
| 316 | #[const_trait] | |
| 317 | pub trait PartialEq<Rhs: PointeeSized = Self>: PointeeSized { | |
| 302 | pub const trait PartialEq<Rhs: PointeeSized = Self>: PointeeSized { | |
| 318 | 303 | fn eq(&self, other: &Rhs) -> bool; |
| 319 | 304 | fn ne(&self, other: &Rhs) -> bool { |
| 320 | 305 | !self.eq(other) |
| ... | ... | @@ -337,8 +322,7 @@ impl PartialEq for str { |
| 337 | 322 | } |
| 338 | 323 | |
| 339 | 324 | #[lang = "not"] |
| 340 | #[const_trait] | |
| 341 | pub trait Not { | |
| 325 | pub const trait Not { | |
| 342 | 326 | type Output; |
| 343 | 327 | fn not(self) -> Self::Output; |
| 344 | 328 | } |
| ... | ... | @@ -462,8 +446,7 @@ impl<T: MetaSized> Deref for Ref<'_, T> { |
| 462 | 446 | |
| 463 | 447 | #[lang = "clone"] |
| 464 | 448 | #[rustc_trivial_field_reads] |
| 465 | #[const_trait] | |
| 466 | pub trait Clone: Sized { | |
| 449 | pub const trait Clone: Sized { | |
| 467 | 450 | fn clone(&self) -> Self; |
| 468 | 451 | fn clone_from(&mut self, source: &Self) |
| 469 | 452 | where |
tests/ui/traits/const-traits/auxiliary/staged-api.rs+1-2| ... | ... | @@ -5,8 +5,7 @@ |
| 5 | 5 | |
| 6 | 6 | #[stable(feature = "rust1", since = "1.0.0")] |
| 7 | 7 | #[rustc_const_unstable(feature = "unstable", issue = "none")] |
| 8 | #[const_trait] | |
| 9 | pub trait MyTrait { | |
| 8 | pub const trait MyTrait { | |
| 10 | 9 | #[stable(feature = "rust1", since = "1.0.0")] |
| 11 | 10 | fn func(); |
| 12 | 11 | } |
tests/ui/traits/const-traits/call-const-closure.rs+1-2| ... | ... | @@ -4,8 +4,7 @@ |
| 4 | 4 | #![feature(const_trait_impl, const_closures)] |
| 5 | 5 | #![allow(incomplete_features)] |
| 6 | 6 | |
| 7 | #[const_trait] | |
| 8 | trait Bar { | |
| 7 | const trait Bar { | |
| 9 | 8 | fn foo(&self); |
| 10 | 9 | } |
| 11 | 10 |
tests/ui/traits/const-traits/call-const-closure.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | (const || ().foo())(); |
| 5 | 5 | | ^^^ |
tests/ui/traits/const-traits/call-const-in-conditionally-const.rs+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | //@ compile-flags: -Znext-solver |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | |
| 4 | #[const_trait] trait Foo { | |
| 4 | const trait Foo { | |
| 5 | 5 | fn foo(); |
| 6 | 6 | } |
| 7 | 7 |
tests/ui/traits/const-traits/call-const-trait-method-fail.rs+1-2| ... | ... | @@ -1,8 +1,7 @@ |
| 1 | 1 | //@ compile-flags: -Znext-solver |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | |
| 4 | #[const_trait] | |
| 5 | pub trait Plus { | |
| 4 | pub const trait Plus { | |
| 6 | 5 | fn plus(self, rhs: Self) -> Self; |
| 7 | 6 | } |
| 8 | 7 |
tests/ui/traits/const-traits/call-const-trait-method-fail.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | a.plus(b) |
| 5 | 5 | | ^ |
tests/ui/traits/const-traits/call-const-trait-method-pass.rs+1-2| ... | ... | @@ -20,8 +20,7 @@ impl const PartialEq for Int { |
| 20 | 20 | } |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | #[const_trait] | |
| 24 | pub trait Plus { | |
| 23 | pub const trait Plus { | |
| 25 | 24 | fn plus(self, rhs: Self) -> Self; |
| 26 | 25 | } |
| 27 | 26 |
tests/ui/traits/const-traits/call-generic-in-impl.rs+1-2| ... | ... | @@ -1,8 +1,7 @@ |
| 1 | 1 | //@ check-pass |
| 2 | 2 | #![feature(const_trait_impl, const_cmp)] |
| 3 | 3 | |
| 4 | #[const_trait] | |
| 5 | trait MyPartialEq { | |
| 4 | const trait MyPartialEq { | |
| 6 | 5 | fn eq(&self, other: &Self) -> bool; |
| 7 | 6 | } |
| 8 | 7 |
tests/ui/traits/const-traits/call-generic-method-nonconst.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | struct S; |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Foo { | |
| 6 | const trait Foo { | |
| 8 | 7 | fn eq(&self, _: &Self) -> bool; |
| 9 | 8 | } |
| 10 | 9 |
tests/ui/traits/const-traits/call-generic-method-nonconst.stderr+2-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | pub const EQ: bool = equals_self(&S); |
| 5 | 5 | | ----------- ^^ |
| ... | ... | @@ -7,7 +7,7 @@ LL | pub const EQ: bool = equals_self(&S); |
| 7 | 7 | | required by a bound introduced by this call |
| 8 | 8 | | |
| 9 | 9 | note: 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 | |
| 11 | 11 | | |
| 12 | 12 | LL | const fn equals_self<T: [const] Foo>(t: &T) -> bool { |
| 13 | 13 | | ^^^^^^^^^^^ 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> { |
| 12 | 12 | } |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | #[const_trait] | |
| 16 | trait Add42 { | |
| 15 | const trait Add42 { | |
| 17 | 16 | fn add(a: usize) -> usize; |
| 18 | 17 | } |
| 19 | 18 |
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) }> { |
| 11 | 11 | | ^^^ |
| 12 | 12 | |
| 13 | 13 | error: `[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 | |
| 15 | 15 | | |
| 16 | 16 | LL | fn bar<A: [const] Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { |
| 17 | 17 | | ^^^^^^^ |
| 18 | 18 | | |
| 19 | 19 | note: 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 | |
| 21 | 21 | | |
| 22 | 22 | LL | fn bar<A: [const] Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { |
| 23 | 23 | | ^^^ |
| 24 | 24 | |
| 25 | 25 | error[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 | |
| 27 | 27 | | |
| 28 | 28 | LL | fn bar<A: [const] Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { |
| 29 | 29 | | ^ |
tests/ui/traits/const-traits/conditionally-const-assoc-fn-in-trait-impl.rs+2-4| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | //@ compile-flags: -Znext-solver |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Main { | |
| 6 | const trait Main { | |
| 8 | 7 | fn compute<T: [const] Aux>() -> u32; |
| 9 | 8 | } |
| 10 | 9 | |
| ... | ... | @@ -14,8 +13,7 @@ impl const Main for () { |
| 14 | 13 | } |
| 15 | 14 | } |
| 16 | 15 | |
| 17 | #[const_trait] | |
| 18 | trait Aux { | |
| 16 | const trait Aux { | |
| 19 | 17 | fn generate() -> u32; |
| 20 | 18 | } |
| 21 | 19 |
tests/ui/traits/const-traits/conditionally-const-in-anon-const.rs+1-2| ... | ... | @@ -1,8 +1,7 @@ |
| 1 | 1 | #![feature(const_trait_impl, impl_trait_in_bindings)] |
| 2 | 2 | |
| 3 | 3 | struct S; |
| 4 | #[const_trait] | |
| 5 | trait Trait<const N: u32> {} | |
| 4 | const trait Trait<const N: u32> {} | |
| 6 | 5 | |
| 7 | 6 | impl const Trait<0> for () {} |
| 8 | 7 |
tests/ui/traits/const-traits/conditionally-const-in-anon-const.stderr+4-4| ... | ... | @@ -1,23 +1,23 @@ |
| 1 | 1 | error: `[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | struct I<U: [const] Trait<0>>(U); |
| 5 | 5 | | ^^^^^^^ |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | 10 | LL | struct I<U: [const] Trait<0>>(U); |
| 11 | 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 12 | 12 | |
| 13 | 13 | error: `[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 | |
| 15 | 15 | | |
| 16 | 16 | LL | let x: &impl [const] Trait<0> = &(); |
| 17 | 17 | | ^^^^^^^ |
| 18 | 18 | | |
| 19 | 19 | note: 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 | |
| 21 | 21 | | |
| 22 | 22 | LL | / { |
| 23 | 23 | LL | | 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 @@ |
| 2 | 2 | //@ compile-flags: -Znext-solver |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Foo { | |
| 5 | const trait Foo { | |
| 7 | 6 | fn foo(&self) {} |
| 8 | 7 | } |
| 9 | 8 |
tests/ui/traits/const-traits/conditionally-const-invalid-places.rs+1-2| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | #![feature(const_trait_impl)] |
| 2 | 2 | |
| 3 | #[const_trait] | |
| 4 | trait Trait {} | |
| 3 | const trait Trait {} | |
| 5 | 4 | |
| 6 | 5 | // Regression test for issue #90052. |
| 7 | 6 | fn 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 @@ |
| 1 | 1 | error: `[const]` is not allowed here |
| 2 | --> $DIR/conditionally-const-invalid-places.rs:7:26 | |
| 2 | --> $DIR/conditionally-const-invalid-places.rs:6:26 | |
| 3 | 3 | | |
| 4 | 4 | LL | fn non_const_function<T: [const] Trait>() {} |
| 5 | 5 | | ^^^^^^^ |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | 10 | LL | fn non_const_function<T: [const] Trait>() {} |
| 11 | 11 | | ^^^^^^^^^^^^^^^^^^ |
| 12 | 12 | |
| 13 | 13 | error: `[const]` is not allowed here |
| 14 | --> $DIR/conditionally-const-invalid-places.rs:9:18 | |
| 14 | --> $DIR/conditionally-const-invalid-places.rs:8:18 | |
| 15 | 15 | | |
| 16 | 16 | LL | struct Struct<T: [const] Trait> { field: T } |
| 17 | 17 | | ^^^^^^^ |
| 18 | 18 | | |
| 19 | 19 | note: structs cannot have `[const]` trait bounds |
| 20 | --> $DIR/conditionally-const-invalid-places.rs:9:1 | |
| 20 | --> $DIR/conditionally-const-invalid-places.rs:8:1 | |
| 21 | 21 | | |
| 22 | 22 | LL | struct Struct<T: [const] Trait> { field: T } |
| 23 | 23 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 24 | 24 | |
| 25 | 25 | error: `[const]` is not allowed here |
| 26 | --> $DIR/conditionally-const-invalid-places.rs:10:23 | |
| 26 | --> $DIR/conditionally-const-invalid-places.rs:9:23 | |
| 27 | 27 | | |
| 28 | 28 | LL | struct TupleStruct<T: [const] Trait>(T); |
| 29 | 29 | | ^^^^^^^ |
| 30 | 30 | | |
| 31 | 31 | note: structs cannot have `[const]` trait bounds |
| 32 | --> $DIR/conditionally-const-invalid-places.rs:10:1 | |
| 32 | --> $DIR/conditionally-const-invalid-places.rs:9:1 | |
| 33 | 33 | | |
| 34 | 34 | LL | struct TupleStruct<T: [const] Trait>(T); |
| 35 | 35 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 36 | 36 | |
| 37 | 37 | error: `[const]` is not allowed here |
| 38 | --> $DIR/conditionally-const-invalid-places.rs:11:22 | |
| 38 | --> $DIR/conditionally-const-invalid-places.rs:10:22 | |
| 39 | 39 | | |
| 40 | 40 | LL | struct UnitStruct<T: [const] Trait>; |
| 41 | 41 | | ^^^^^^^ |
| 42 | 42 | | |
| 43 | 43 | note: structs cannot have `[const]` trait bounds |
| 44 | --> $DIR/conditionally-const-invalid-places.rs:11:1 | |
| 44 | --> $DIR/conditionally-const-invalid-places.rs:10:1 | |
| 45 | 45 | | |
| 46 | 46 | LL | struct UnitStruct<T: [const] Trait>; |
| 47 | 47 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 48 | 48 | |
| 49 | 49 | error: `[const]` is not allowed here |
| 50 | --> $DIR/conditionally-const-invalid-places.rs:14:14 | |
| 50 | --> $DIR/conditionally-const-invalid-places.rs:13:14 | |
| 51 | 51 | | |
| 52 | 52 | LL | enum Enum<T: [const] Trait> { Variant(T) } |
| 53 | 53 | | ^^^^^^^ |
| 54 | 54 | | |
| 55 | 55 | note: enums cannot have `[const]` trait bounds |
| 56 | --> $DIR/conditionally-const-invalid-places.rs:14:1 | |
| 56 | --> $DIR/conditionally-const-invalid-places.rs:13:1 | |
| 57 | 57 | | |
| 58 | 58 | LL | enum Enum<T: [const] Trait> { Variant(T) } |
| 59 | 59 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 60 | 60 | |
| 61 | 61 | error: `[const]` is not allowed here |
| 62 | --> $DIR/conditionally-const-invalid-places.rs:16:16 | |
| 62 | --> $DIR/conditionally-const-invalid-places.rs:15:16 | |
| 63 | 63 | | |
| 64 | 64 | LL | union Union<T: [const] Trait> { field: T } |
| 65 | 65 | | ^^^^^^^ |
| 66 | 66 | | |
| 67 | 67 | note: unions cannot have `[const]` trait bounds |
| 68 | --> $DIR/conditionally-const-invalid-places.rs:16:1 | |
| 68 | --> $DIR/conditionally-const-invalid-places.rs:15:1 | |
| 69 | 69 | | |
| 70 | 70 | LL | union Union<T: [const] Trait> { field: T } |
| 71 | 71 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 72 | 72 | |
| 73 | 73 | error: `[const]` is not allowed here |
| 74 | --> $DIR/conditionally-const-invalid-places.rs:19:14 | |
| 74 | --> $DIR/conditionally-const-invalid-places.rs:18:14 | |
| 75 | 75 | | |
| 76 | 76 | LL | type Type<T: [const] Trait> = T; |
| 77 | 77 | | ^^^^^^^ |
| ... | ... | @@ -79,7 +79,7 @@ LL | type Type<T: [const] Trait> = T; |
| 79 | 79 | = note: this item cannot have `[const]` trait bounds |
| 80 | 80 | |
| 81 | 81 | error: `[const]` is not allowed here |
| 82 | --> $DIR/conditionally-const-invalid-places.rs:21:19 | |
| 82 | --> $DIR/conditionally-const-invalid-places.rs:20:19 | |
| 83 | 83 | | |
| 84 | 84 | LL | const CONSTANT<T: [const] Trait>: () = (); |
| 85 | 85 | | ^^^^^^^ |
| ... | ... | @@ -87,43 +87,43 @@ LL | const CONSTANT<T: [const] Trait>: () = (); |
| 87 | 87 | = note: this item cannot have `[const]` trait bounds |
| 88 | 88 | |
| 89 | 89 | error: `[const]` is not allowed here |
| 90 | --> $DIR/conditionally-const-invalid-places.rs:25:18 | |
| 90 | --> $DIR/conditionally-const-invalid-places.rs:24:18 | |
| 91 | 91 | | |
| 92 | 92 | LL | type Type<T: [const] Trait>: [const] Trait; |
| 93 | 93 | | ^^^^^^^ |
| 94 | 94 | | |
| 95 | 95 | note: 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 | |
| 97 | 97 | | |
| 98 | 98 | LL | type Type<T: [const] Trait>: [const] Trait; |
| 99 | 99 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 100 | 100 | |
| 101 | 101 | error: `[const]` is not allowed here |
| 102 | --> $DIR/conditionally-const-invalid-places.rs:25:34 | |
| 102 | --> $DIR/conditionally-const-invalid-places.rs:24:34 | |
| 103 | 103 | | |
| 104 | 104 | LL | type Type<T: [const] Trait>: [const] Trait; |
| 105 | 105 | | ^^^^^^^ |
| 106 | 106 | | |
| 107 | 107 | note: 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 | |
| 109 | 109 | | |
| 110 | 110 | LL | type Type<T: [const] Trait>: [const] Trait; |
| 111 | 111 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 112 | 112 | |
| 113 | 113 | error: `[const]` is not allowed here |
| 114 | --> $DIR/conditionally-const-invalid-places.rs:28:30 | |
| 114 | --> $DIR/conditionally-const-invalid-places.rs:27:30 | |
| 115 | 115 | | |
| 116 | 116 | LL | fn non_const_function<T: [const] Trait>(); |
| 117 | 117 | | ^^^^^^^ |
| 118 | 118 | | |
| 119 | 119 | note: 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 | |
| 121 | 121 | | |
| 122 | 122 | LL | fn non_const_function<T: [const] Trait>(); |
| 123 | 123 | | ^^^^^^^^^^^^^^^^^^ |
| 124 | 124 | |
| 125 | 125 | error: `[const]` is not allowed here |
| 126 | --> $DIR/conditionally-const-invalid-places.rs:29:23 | |
| 126 | --> $DIR/conditionally-const-invalid-places.rs:28:23 | |
| 127 | 127 | | |
| 128 | 128 | LL | const CONSTANT<T: [const] Trait>: (); |
| 129 | 129 | | ^^^^^^^ |
| ... | ... | @@ -131,31 +131,31 @@ LL | const CONSTANT<T: [const] Trait>: (); |
| 131 | 131 | = note: this item cannot have `[const]` trait bounds |
| 132 | 132 | |
| 133 | 133 | error: `[const]` is not allowed here |
| 134 | --> $DIR/conditionally-const-invalid-places.rs:34:18 | |
| 134 | --> $DIR/conditionally-const-invalid-places.rs:33:18 | |
| 135 | 135 | | |
| 136 | 136 | LL | type Type<T: [const] Trait> = (); |
| 137 | 137 | | ^^^^^^^ |
| 138 | 138 | | |
| 139 | 139 | note: 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 | |
| 141 | 141 | | |
| 142 | 142 | LL | type Type<T: [const] Trait> = (); |
| 143 | 143 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 144 | 144 | |
| 145 | 145 | error: `[const]` is not allowed here |
| 146 | --> $DIR/conditionally-const-invalid-places.rs:36:30 | |
| 146 | --> $DIR/conditionally-const-invalid-places.rs:35:30 | |
| 147 | 147 | | |
| 148 | 148 | LL | fn non_const_function<T: [const] Trait>() {} |
| 149 | 149 | | ^^^^^^^ |
| 150 | 150 | | |
| 151 | 151 | note: 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 | |
| 153 | 153 | | |
| 154 | 154 | LL | fn non_const_function<T: [const] Trait>() {} |
| 155 | 155 | | ^^^^^^^^^^^^^^^^^^ |
| 156 | 156 | |
| 157 | 157 | error: `[const]` is not allowed here |
| 158 | --> $DIR/conditionally-const-invalid-places.rs:37:23 | |
| 158 | --> $DIR/conditionally-const-invalid-places.rs:36:23 | |
| 159 | 159 | | |
| 160 | 160 | LL | const CONSTANT<T: [const] Trait>: () = (); |
| 161 | 161 | | ^^^^^^^ |
| ... | ... | @@ -163,31 +163,31 @@ LL | const CONSTANT<T: [const] Trait>: () = (); |
| 163 | 163 | = note: this item cannot have `[const]` trait bounds |
| 164 | 164 | |
| 165 | 165 | error: `[const]` is not allowed here |
| 166 | --> $DIR/conditionally-const-invalid-places.rs:44:18 | |
| 166 | --> $DIR/conditionally-const-invalid-places.rs:43:18 | |
| 167 | 167 | | |
| 168 | 168 | LL | type Type<T: [const] Trait> = (); |
| 169 | 169 | | ^^^^^^^ |
| 170 | 170 | | |
| 171 | 171 | note: 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 | |
| 173 | 173 | | |
| 174 | 174 | LL | type Type<T: [const] Trait> = (); |
| 175 | 175 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 176 | 176 | |
| 177 | 177 | error: `[const]` is not allowed here |
| 178 | --> $DIR/conditionally-const-invalid-places.rs:46:30 | |
| 178 | --> $DIR/conditionally-const-invalid-places.rs:45:30 | |
| 179 | 179 | | |
| 180 | 180 | LL | fn non_const_function<T: [const] Trait>() {} |
| 181 | 181 | | ^^^^^^^ |
| 182 | 182 | | |
| 183 | 183 | note: 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 | |
| 185 | 185 | | |
| 186 | 186 | LL | fn non_const_function<T: [const] Trait>() {} |
| 187 | 187 | | ^^^^^^^^^^^^^^^^^^ |
| 188 | 188 | |
| 189 | 189 | error: `[const]` is not allowed here |
| 190 | --> $DIR/conditionally-const-invalid-places.rs:47:23 | |
| 190 | --> $DIR/conditionally-const-invalid-places.rs:46:23 | |
| 191 | 191 | | |
| 192 | 192 | LL | const CONSTANT<T: [const] Trait>: () = (); |
| 193 | 193 | | ^^^^^^^ |
| ... | ... | @@ -195,55 +195,55 @@ LL | const CONSTANT<T: [const] Trait>: () = (); |
| 195 | 195 | = note: this item cannot have `[const]` trait bounds |
| 196 | 196 | |
| 197 | 197 | error: `[const]` is not allowed here |
| 198 | --> $DIR/conditionally-const-invalid-places.rs:52:15 | |
| 198 | --> $DIR/conditionally-const-invalid-places.rs:51:15 | |
| 199 | 199 | | |
| 200 | 200 | LL | trait Child0: [const] Trait {} |
| 201 | 201 | | ^^^^^^^ |
| 202 | 202 | | |
| 203 | 203 | note: 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 | |
| 205 | 205 | | |
| 206 | 206 | LL | trait Child0: [const] Trait {} |
| 207 | 207 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 208 | 208 | |
| 209 | 209 | error: `[const]` is not allowed here |
| 210 | --> $DIR/conditionally-const-invalid-places.rs:53:26 | |
| 210 | --> $DIR/conditionally-const-invalid-places.rs:52:26 | |
| 211 | 211 | | |
| 212 | 212 | LL | trait Child1 where Self: [const] Trait {} |
| 213 | 213 | | ^^^^^^^ |
| 214 | 214 | | |
| 215 | 215 | note: 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 | |
| 217 | 217 | | |
| 218 | 218 | LL | trait Child1 where Self: [const] Trait {} |
| 219 | 219 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 220 | 220 | |
| 221 | 221 | error: `[const]` is not allowed here |
| 222 | --> $DIR/conditionally-const-invalid-places.rs:56:9 | |
| 222 | --> $DIR/conditionally-const-invalid-places.rs:55:9 | |
| 223 | 223 | | |
| 224 | 224 | LL | impl<T: [const] Trait> Trait for T {} |
| 225 | 225 | | ^^^^^^^ |
| 226 | 226 | | |
| 227 | 227 | note: 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 | |
| 229 | 229 | | |
| 230 | 230 | LL | impl<T: [const] Trait> Trait for T {} |
| 231 | 231 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 232 | 232 | |
| 233 | 233 | error: `[const]` is not allowed here |
| 234 | --> $DIR/conditionally-const-invalid-places.rs:59:9 | |
| 234 | --> $DIR/conditionally-const-invalid-places.rs:58:9 | |
| 235 | 235 | | |
| 236 | 236 | LL | impl<T: [const] Trait> Struct<T> {} |
| 237 | 237 | | ^^^^^^^ |
| 238 | 238 | | |
| 239 | 239 | note: 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 | |
| 241 | 241 | | |
| 242 | 242 | LL | impl<T: [const] Trait> Struct<T> {} |
| 243 | 243 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 244 | 244 | |
| 245 | 245 | error[E0658]: generic const items are experimental |
| 246 | --> $DIR/conditionally-const-invalid-places.rs:21:15 | |
| 246 | --> $DIR/conditionally-const-invalid-places.rs:20:15 | |
| 247 | 247 | | |
| 248 | 248 | LL | const CONSTANT<T: [const] Trait>: () = (); |
| 249 | 249 | | ^^^^^^^^^^^^^^^^^^ |
| ... | ... | @@ -253,7 +253,7 @@ LL | const CONSTANT<T: [const] Trait>: () = (); |
| 253 | 253 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 254 | 254 | |
| 255 | 255 | error[E0658]: generic const items are experimental |
| 256 | --> $DIR/conditionally-const-invalid-places.rs:29:19 | |
| 256 | --> $DIR/conditionally-const-invalid-places.rs:28:19 | |
| 257 | 257 | | |
| 258 | 258 | LL | const CONSTANT<T: [const] Trait>: (); |
| 259 | 259 | | ^^^^^^^^^^^^^^^^^^ |
| ... | ... | @@ -263,7 +263,7 @@ LL | const CONSTANT<T: [const] Trait>: (); |
| 263 | 263 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 264 | 264 | |
| 265 | 265 | error[E0658]: generic const items are experimental |
| 266 | --> $DIR/conditionally-const-invalid-places.rs:37:19 | |
| 266 | --> $DIR/conditionally-const-invalid-places.rs:36:19 | |
| 267 | 267 | | |
| 268 | 268 | LL | const CONSTANT<T: [const] Trait>: () = (); |
| 269 | 269 | | ^^^^^^^^^^^^^^^^^^ |
| ... | ... | @@ -273,7 +273,7 @@ LL | const CONSTANT<T: [const] Trait>: () = (); |
| 273 | 273 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 274 | 274 | |
| 275 | 275 | error[E0658]: generic const items are experimental |
| 276 | --> $DIR/conditionally-const-invalid-places.rs:47:19 | |
| 276 | --> $DIR/conditionally-const-invalid-places.rs:46:19 | |
| 277 | 277 | | |
| 278 | 278 | LL | const CONSTANT<T: [const] Trait>: () = (); |
| 279 | 279 | | ^^^^^^^^^^^^^^^^^^ |
| ... | ... | @@ -283,7 +283,7 @@ LL | const CONSTANT<T: [const] Trait>: () = (); |
| 283 | 283 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 284 | 284 | |
| 285 | 285 | error[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 | |
| 287 | 287 | | |
| 288 | 288 | LL | struct UnitStruct<T: [const] Trait>; |
| 289 | 289 | | ^ unused type parameter |
| ... | ... | @@ -291,7 +291,7 @@ LL | struct UnitStruct<T: [const] Trait>; |
| 291 | 291 | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` |
| 292 | 292 | |
| 293 | 293 | error[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 | |
| 295 | 295 | | |
| 296 | 296 | LL | union Union<T: [const] Trait> { field: T } |
| 297 | 297 | | ^^^^^^^^ |
| ... | ... | @@ -303,19 +303,19 @@ LL | union Union<T: [const] Trait> { field: std::mem::ManuallyDrop<T> } |
| 303 | 303 | | +++++++++++++++++++++++ + |
| 304 | 304 | |
| 305 | 305 | error[E0275]: overflow evaluating the requirement `(): Trait` |
| 306 | --> $DIR/conditionally-const-invalid-places.rs:34:35 | |
| 306 | --> $DIR/conditionally-const-invalid-places.rs:33:35 | |
| 307 | 307 | | |
| 308 | 308 | LL | type Type<T: [const] Trait> = (); |
| 309 | 309 | | ^^ |
| 310 | 310 | | |
| 311 | 311 | note: 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 | |
| 313 | 313 | | |
| 314 | 314 | LL | type Type<T: [const] Trait>: [const] Trait; |
| 315 | 315 | | ^^^^^^^^^^^^^ required by this bound in `NonConstTrait::Type` |
| 316 | 316 | |
| 317 | 317 | error[E0658]: inherent associated types are unstable |
| 318 | --> $DIR/conditionally-const-invalid-places.rs:44:5 | |
| 318 | --> $DIR/conditionally-const-invalid-places.rs:43:5 | |
| 319 | 319 | | |
| 320 | 320 | LL | type Type<T: [const] Trait> = (); |
| 321 | 321 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
tests/ui/traits/const-traits/conditionally-const-trait-bound-assoc-tys.rs+2-4| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | //@ compile-flags: -Znext-solver |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Trait { | |
| 5 | const trait Trait { | |
| 7 | 6 | type Assoc<T: [const] Bound>; |
| 8 | 7 | } |
| 9 | 8 | |
| ... | ... | @@ -11,7 +10,6 @@ impl const Trait for () { |
| 11 | 10 | type Assoc<T: [const] Bound> = T; |
| 12 | 11 | } |
| 13 | 12 | |
| 14 | #[const_trait] | |
| 15 | trait Bound {} | |
| 13 | const trait Bound {} | |
| 16 | 14 | |
| 17 | 15 | fn main() {} |
tests/ui/traits/const-traits/const-assoc-bound-in-trait-wc.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | #![feature(const_clone)] |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait A where Self::Target: [const] Clone { | |
| 6 | const trait A where Self::Target: [const] Clone { | |
| 8 | 7 | type Target; |
| 9 | 8 | } |
| 10 | 9 |
tests/ui/traits/const-traits/const-bound-in-host.rs+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] trait Foo { | |
| 6 | const trait Foo { | |
| 7 | 7 | fn foo(); |
| 8 | 8 | } |
| 9 | 9 |
tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs+1-2| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait MyTrait { | |
| 5 | const trait MyTrait { | |
| 7 | 6 | fn do_something(&self); |
| 8 | 7 | } |
| 9 | 8 |
tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr+4-4| ... | ... | @@ -1,23 +1,23 @@ |
| 1 | 1 | error: `[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | fn do_something_else() where Self: [const] MyTrait; |
| 5 | 5 | | ^^^^^^^ |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | 10 | LL | fn do_something_else() where Self: [const] MyTrait; |
| 11 | 11 | | ^^^^^^^^^^^^^^^^^ |
| 12 | 12 | |
| 13 | 13 | error: `[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 | |
| 15 | 15 | | |
| 16 | 16 | LL | pub fn foo(&self) where T: [const] MyTrait { |
| 17 | 17 | | ^^^^^^^ |
| 18 | 18 | | |
| 19 | 19 | note: 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 | |
| 21 | 21 | | |
| 22 | 22 | LL | pub fn foo(&self) where T: [const] MyTrait { |
| 23 | 23 | | ^^^ |
tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr+6-6| ... | ... | @@ -6,8 +6,8 @@ LL | const fn perform<T: [const] NonConst>() {} |
| 6 | 6 | | |
| 7 | 7 | help: mark `NonConst` as `const` to allow it to have `const` implementations |
| 8 | 8 | | |
| 9 | LL | #[const_trait] trait NonConst {} | |
| 10 | | ++++++++++++++ | |
| 9 | LL | const trait NonConst {} | |
| 10 | | +++++ | |
| 11 | 11 | |
| 12 | 12 | error: `[const]` can only be applied to `const` traits |
| 13 | 13 | --> $DIR/const-bounds-non-const-trait.rs:6:21 |
| ... | ... | @@ -18,8 +18,8 @@ LL | const fn perform<T: [const] NonConst>() {} |
| 18 | 18 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 19 | 19 | help: mark `NonConst` as `const` to allow it to have `const` implementations |
| 20 | 20 | | |
| 21 | LL | #[const_trait] trait NonConst {} | |
| 22 | | ++++++++++++++ | |
| 21 | LL | const trait NonConst {} | |
| 22 | | +++++ | |
| 23 | 23 | |
| 24 | 24 | error: `const` can only be applied to `const` traits |
| 25 | 25 | --> $DIR/const-bounds-non-const-trait.rs:10:15 |
| ... | ... | @@ -29,8 +29,8 @@ LL | fn operate<T: const NonConst>() {} |
| 29 | 29 | | |
| 30 | 30 | help: mark `NonConst` as `const` to allow it to have `const` implementations |
| 31 | 31 | | |
| 32 | LL | #[const_trait] trait NonConst {} | |
| 33 | | ++++++++++++++ | |
| 32 | LL | const trait NonConst {} | |
| 33 | | +++++ | |
| 34 | 34 | |
| 35 | 35 | error: aborting due to 3 previous errors |
| 36 | 36 |
tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | 5 | struct S; |
| 6 | #[const_trait] | |
| 7 | trait T { | |
| 6 | const trait T { | |
| 8 | 7 | fn foo(); |
| 9 | 8 | } |
| 10 | 9 |
tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | fn foo() { non_const() } |
| 5 | 5 | | ^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | 10 | LL | fn non_const() {} |
| 11 | 11 | | ^^^^^^^^^^^^^^ |
tests/ui/traits/const-traits/const-closure-trait-method-fail.rs+1-2| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Tr { | |
| 5 | const trait Tr { | |
| 7 | 6 | fn a(self) -> i32; |
| 8 | 7 | } |
| 9 | 8 |
tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | const _: () = assert!(need_const_closure(Tr::a) == 42); |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ |
tests/ui/traits/const-traits/const-closure-trait-method.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | //@[next] compile-flags: -Znext-solver |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Tr { | |
| 6 | const trait Tr { | |
| 8 | 7 | fn a(self) -> i32; |
| 9 | 8 | } |
| 10 | 9 |
tests/ui/traits/const-traits/const-cond-for-rpitit.rs+2-4| ... | ... | @@ -4,13 +4,11 @@ |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | #![allow(refining_impl_trait)] |
| 6 | 6 | |
| 7 | #[const_trait] | |
| 8 | pub trait Foo { | |
| 7 | pub const trait Foo { | |
| 9 | 8 | fn method(self) -> impl [const] Bar; |
| 10 | 9 | } |
| 11 | 10 | |
| 12 | #[const_trait] | |
| 13 | pub trait Bar {} | |
| 11 | pub const trait Bar {} | |
| 14 | 12 | |
| 15 | 13 | struct A<T>(T); |
| 16 | 14 | impl<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 @@ |
| 1 | 1 | //@ compile-flags: -Znext-solver |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | |
| 4 | #[const_trait] | |
| 5 | trait ConstDefaultFn: Sized { | |
| 4 | const trait ConstDefaultFn: Sized { | |
| 6 | 5 | fn b(self); |
| 7 | 6 | |
| 8 | 7 | fn a(self) { |
tests/ui/traits/const-traits/const-default-method-bodies.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | NonConstImpl.a(); |
| 5 | 5 | | ^ |
tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr+3-3| ... | ... | @@ -1,18 +1,18 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>( |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | 10 | LL | impl<T: [const] A> const Drop for ConstDropImplWithBounds<T> { |
| 11 | 11 | | --------- ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 12 | 12 | | | |
| 13 | 13 | | unsatisfied trait bound introduced here |
| 14 | 14 | note: required by a bound in `check` |
| 15 | --> $DIR/const-drop-fail-2.rs:21:19 | |
| 15 | --> $DIR/const-drop-fail-2.rs:20:19 | |
| 16 | 16 | | |
| 17 | 17 | LL | const fn check<T: [const] Destruct>(_: T) {} |
| 18 | 18 | | ^^^^^^^^^^^^^^^^ 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 { |
| 13 | 13 | } |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | #[const_trait] | |
| 17 | trait A { fn a() { } } | |
| 16 | const trait A { fn a() { } } | |
| 18 | 17 | |
| 19 | 18 | impl A for NonTrivialDrop {} |
| 20 | 19 |
tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr+3-3| ... | ... | @@ -1,18 +1,18 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>( |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | 10 | LL | impl<T: [const] A> const Drop for ConstDropImplWithBounds<T> { |
| 11 | 11 | | --------- ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 12 | 12 | | | |
| 13 | 13 | | unsatisfied trait bound introduced here |
| 14 | 14 | note: required by a bound in `check` |
| 15 | --> $DIR/const-drop-fail-2.rs:21:19 | |
| 15 | --> $DIR/const-drop-fail-2.rs:20:19 | |
| 16 | 16 | | |
| 17 | 17 | LL | const fn check<T: [const] Destruct>(_: T) {} |
| 18 | 18 | | ^^^^^^^^^^^^^^^^ required by this bound in `check` |
tests/ui/traits/const-traits/const-drop.rs+1-2| ... | ... | @@ -49,8 +49,7 @@ mod t { |
| 49 | 49 | pub struct HasConstDrop(pub ConstDrop); |
| 50 | 50 | pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize); |
| 51 | 51 | |
| 52 | #[const_trait] | |
| 53 | pub trait SomeTrait { | |
| 52 | pub const trait SomeTrait { | |
| 54 | 53 | fn foo(); |
| 55 | 54 | } |
| 56 | 55 | impl const SomeTrait for () { |
tests/ui/traits/const-traits/const-impl-recovery.rs+2-4| ... | ... | @@ -1,12 +1,10 @@ |
| 1 | 1 | #![feature(const_trait_impl)] |
| 2 | 2 | |
| 3 | #[const_trait] | |
| 4 | trait Foo {} | |
| 3 | const trait Foo {} | |
| 5 | 4 | |
| 6 | 5 | const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword |
| 7 | 6 | |
| 8 | #[const_trait] | |
| 9 | trait Bar {} | |
| 7 | const trait Bar {} | |
| 10 | 8 | |
| 11 | 9 | const impl<T: Foo> Bar for T {} //~ ERROR: expected identifier, found keyword |
| 12 | 10 |
tests/ui/traits/const-traits/const-impl-recovery.stderr+2-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error: expected identifier, found keyword `impl` |
| 2 | --> $DIR/const-impl-recovery.rs:6:7 | |
| 2 | --> $DIR/const-impl-recovery.rs:5:7 | |
| 3 | 3 | | |
| 4 | 4 | LL | const impl Foo for i32 {} |
| 5 | 5 | | ^^^^ expected identifier, found keyword |
| ... | ... | @@ -11,7 +11,7 @@ LL + impl const Foo for i32 {} |
| 11 | 11 | | |
| 12 | 12 | |
| 13 | 13 | error: expected identifier, found keyword `impl` |
| 14 | --> $DIR/const-impl-recovery.rs:11:7 | |
| 14 | --> $DIR/const-impl-recovery.rs:9:7 | |
| 15 | 15 | | |
| 16 | 16 | LL | const impl<T: Foo> Bar for T {} |
| 17 | 17 | | ^^^^ 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 () {} |
| 8 | 8 | = note: adding a non-const method body in the future would be a breaking change |
| 9 | 9 | help: mark `A` as `const` to allow it to have `const` implementations |
| 10 | 10 | | |
| 11 | LL | #[const_trait] pub trait A {} | |
| 12 | | ++++++++++++++ | |
| 11 | LL | pub const trait A {} | |
| 12 | | +++++ | |
| 13 | 13 | |
| 14 | 14 | error: aborting due to 1 previous error |
| 15 | 15 |
tests/ui/traits/const-traits/const-impl-trait.rs+2-4| ... | ... | @@ -16,8 +16,7 @@ const fn wrap( |
| 16 | 16 | x |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | #[const_trait] | |
| 20 | trait Foo { | |
| 19 | const trait Foo { | |
| 21 | 20 | fn huh() -> impl [const] PartialEq + [const] Destruct + Copy; |
| 22 | 21 | } |
| 23 | 22 | |
| ... | ... | @@ -36,8 +35,7 @@ const _: () = { |
| 36 | 35 | assert!(x == x); |
| 37 | 36 | }; |
| 38 | 37 | |
| 39 | #[const_trait] | |
| 40 | trait T {} | |
| 38 | const trait T {} | |
| 41 | 39 | struct S; |
| 42 | 40 | impl const T for S {} |
| 43 | 41 |
tests/ui/traits/const-traits/const-in-closure.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Trait { | |
| 6 | const trait Trait { | |
| 8 | 7 | fn method(); |
| 9 | 8 | } |
| 10 | 9 |
tests/ui/traits/const-traits/const-opaque.no.stderr+3-3| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[E0277]: the trait bound `(): const Foo` is not satisfied |
| 2 | --> $DIR/const-opaque.rs:31:22 | |
| 2 | --> $DIR/const-opaque.rs:30:22 | |
| 3 | 3 | | |
| 4 | 4 | LL | let opaque = bar(()); |
| 5 | 5 | | --- ^^ |
| ... | ... | @@ -7,7 +7,7 @@ LL | let opaque = bar(()); |
| 7 | 7 | | required by a bound introduced by this call |
| 8 | 8 | | |
| 9 | 9 | note: required by a bound in `bar` |
| 10 | --> $DIR/const-opaque.rs:26:17 | |
| 10 | --> $DIR/const-opaque.rs:25:17 | |
| 11 | 11 | | |
| 12 | 12 | LL | const fn bar<T: [const] Foo>(t: T) -> impl [const] Foo { |
| 13 | 13 | | ^^^^^^^^^^^ required by this bound in `bar` |
| ... | ... | @@ -17,7 +17,7 @@ LL | impl const Foo for () { |
| 17 | 17 | | +++++ |
| 18 | 18 | |
| 19 | 19 | error[E0277]: the trait bound `(): const Foo` is not satisfied |
| 20 | --> $DIR/const-opaque.rs:33:12 | |
| 20 | --> $DIR/const-opaque.rs:32:12 | |
| 21 | 21 | | |
| 22 | 22 | LL | opaque.method(); |
| 23 | 23 | | ^^^^^^ |
tests/ui/traits/const-traits/const-opaque.rs+1-2| ... | ... | @@ -4,8 +4,7 @@ |
| 4 | 4 | |
| 5 | 5 | #![feature(const_trait_impl)] |
| 6 | 6 | |
| 7 | #[const_trait] | |
| 8 | trait Foo { | |
| 7 | const trait Foo { | |
| 9 | 8 | fn method(&self); |
| 10 | 9 | } |
| 11 | 10 |
tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr+4-4| ... | ... | @@ -34,8 +34,8 @@ LL | const fn handle(_: &dyn const NonConst) {} |
| 34 | 34 | | |
| 35 | 35 | help: mark `NonConst` as `const` to allow it to have `const` implementations |
| 36 | 36 | | |
| 37 | LL | #[const_trait] trait NonConst {} | |
| 38 | | ++++++++++++++ | |
| 37 | LL | const trait NonConst {} | |
| 38 | | +++++ | |
| 39 | 39 | |
| 40 | 40 | error: `[const]` can only be applied to `const` traits |
| 41 | 41 | --> $DIR/const-trait-bounds-trait-objects.rs:16:23 |
| ... | ... | @@ -45,8 +45,8 @@ LL | const fn take(_: &dyn [const] NonConst) {} |
| 45 | 45 | | |
| 46 | 46 | help: mark `NonConst` as `const` to allow it to have `const` implementations |
| 47 | 47 | | |
| 48 | LL | #[const_trait] trait NonConst {} | |
| 49 | | ++++++++++++++ | |
| 48 | LL | const trait NonConst {} | |
| 49 | | +++++ | |
| 50 | 50 | |
| 51 | 51 | error: aborting due to 6 previous errors |
| 52 | 52 |
tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs+2-4| ... | ... | @@ -10,8 +10,7 @@ |
| 10 | 10 | #![feature(const_trait_impl, effects)] |
| 11 | 11 | //~^ ERROR feature has been removed |
| 12 | 12 | |
| 13 | #[const_trait] | |
| 14 | trait Main { | |
| 13 | const trait Main { | |
| 15 | 14 | fn compute<T: [const] Aux>() -> u32; |
| 16 | 15 | } |
| 17 | 16 | |
| ... | ... | @@ -22,8 +21,7 @@ impl const Main for () { |
| 22 | 21 | } |
| 23 | 22 | } |
| 24 | 23 | |
| 25 | #[const_trait] | |
| 26 | trait Aux {} | |
| 24 | const trait Aux {} | |
| 27 | 25 | |
| 28 | 26 | impl const Aux for () {} |
| 29 | 27 |
tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr+1-1| ... | ... | @@ -8,7 +8,7 @@ LL | #![feature(const_trait_impl, effects)] |
| 8 | 8 | = note: removed, redundant with `#![feature(const_trait_impl)]` |
| 9 | 9 | |
| 10 | 10 | error[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 | |
| 12 | 12 | | |
| 13 | 13 | LL | fn compute<T: [const] Aux>() -> u32; |
| 14 | 14 | | - expected 1 type parameter |
tests/ui/traits/const-traits/const-via-item-bound.rs+1-2| ... | ... | @@ -5,8 +5,7 @@ |
| 5 | 5 | |
| 6 | 6 | #![feature(const_trait_impl)] |
| 7 | 7 | |
| 8 | #[const_trait] | |
| 9 | trait Bar {} | |
| 8 | const trait Bar {} | |
| 10 | 9 | |
| 11 | 10 | trait Baz: const Bar {} |
| 12 | 11 |
tests/ui/traits/const-traits/cross-crate.gatednc.stderr+1-1| ... | ... | @@ -5,7 +5,7 @@ LL | NonConst.func(); |
| 5 | 5 | | ^^^^ |
| 6 | 6 | | |
| 7 | 7 | note: trait `MyTrait` is implemented but not `const` |
| 8 | --> $DIR/auxiliary/cross-crate.rs:12:1 | |
| 8 | --> $DIR/auxiliary/cross-crate.rs:11:1 | |
| 9 | 9 | | |
| 10 | 10 | LL | impl MyTrait for NonConst { |
| 11 | 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ |
tests/ui/traits/const-traits/default-method-body-is-const-body-checking.rs+2-4| ... | ... | @@ -1,13 +1,11 @@ |
| 1 | 1 | #![feature(const_trait_impl)] |
| 2 | 2 | |
| 3 | #[const_trait] | |
| 4 | trait Tr {} | |
| 3 | const trait Tr {} | |
| 5 | 4 | impl Tr for () {} |
| 6 | 5 | |
| 7 | 6 | const fn foo<T>() where T: [const] Tr {} |
| 8 | 7 | |
| 9 | #[const_trait] | |
| 10 | pub trait Foo { | |
| 8 | pub const trait Foo { | |
| 11 | 9 | fn foo() { |
| 12 | 10 | foo::<()>(); |
| 13 | 11 | //~^ 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 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | foo::<()>(); |
| 5 | 5 | | ^^ |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | 10 | LL | const fn foo<T>() where T: [const] Tr {} |
| 11 | 11 | | ^^^^^^^^^^ 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 @@ |
| 1 | 1 | //@ compile-flags: -Znext-solver |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | |
| 4 | #[const_trait] | |
| 5 | pub trait Tr { | |
| 4 | pub const trait Tr { | |
| 6 | 5 | fn a(&self) {} |
| 7 | 6 | |
| 8 | 7 | fn b(&self) { |
tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | ().a() |
| 5 | 5 | | ^ |
tests/ui/traits/const-traits/default-method-body-is-const-with-staged-api.rs+1-2| ... | ... | @@ -9,8 +9,7 @@ |
| 9 | 9 | #![feature(const_trait_impl)] |
| 10 | 10 | #![stable(feature = "foo", since = "3.3.3")] |
| 11 | 11 | |
| 12 | #[const_trait] | |
| 13 | trait Tr { | |
| 12 | const trait Tr { | |
| 14 | 13 | fn a() {} |
| 15 | 14 | } |
| 16 | 15 |
tests/ui/traits/const-traits/do-not-const-check-override.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | #![allow(incomplete_features)] |
| 4 | 4 | #![feature(const_trait_impl, rustc_attrs)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Foo { | |
| 6 | const trait Foo { | |
| 8 | 7 | #[rustc_do_not_const_check] |
| 9 | 8 | fn into_iter(&self) { println!("FEAR ME!") } |
| 10 | 9 | } |
tests/ui/traits/const-traits/do-not-const-check.rs+2-4| ... | ... | @@ -1,13 +1,11 @@ |
| 1 | 1 | //@ check-pass |
| 2 | 2 | #![feature(const_trait_impl, rustc_attrs)] |
| 3 | 3 | |
| 4 | #[const_trait] | |
| 5 | trait IntoIter { | |
| 4 | const trait IntoIter { | |
| 6 | 5 | fn into_iter(self); |
| 7 | 6 | } |
| 8 | 7 | |
| 9 | #[const_trait] | |
| 10 | trait Hmm: Sized { | |
| 8 | const trait Hmm: Sized { | |
| 11 | 9 | #[rustc_do_not_const_check] |
| 12 | 10 | fn chain<U>(self, other: U) where U: IntoIter, |
| 13 | 11 | { |
tests/ui/traits/const-traits/dont-ice-on-const-pred-for-bounds.rs+1-2| ... | ... | @@ -8,8 +8,7 @@ |
| 8 | 8 | |
| 9 | 9 | #![feature(const_trait_impl)] |
| 10 | 10 | |
| 11 | #[const_trait] | |
| 12 | trait Trait { | |
| 11 | const trait Trait { | |
| 13 | 12 | type Assoc: const Trait; |
| 14 | 13 | } |
| 15 | 14 |
tests/ui/traits/const-traits/dont-observe-host.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Trait { | |
| 6 | const trait Trait { | |
| 8 | 7 | fn method() {} |
| 9 | 8 | } |
| 10 | 9 |
tests/ui/traits/const-traits/dont-prefer-param-env-for-infer-self-ty.rs+1-2| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Foo {} | |
| 5 | const trait Foo {} | |
| 7 | 6 | |
| 8 | 7 | impl<T> const Foo for (T,) where T: [const] Foo {} |
| 9 | 8 |
tests/ui/traits/const-traits/double-error-for-unimplemented-trait.rs+1-2| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Trait { | |
| 5 | const trait Trait { | |
| 7 | 6 | type Out; |
| 8 | 7 | } |
| 9 | 8 |
tests/ui/traits/const-traits/double-error-for-unimplemented-trait.stderr+10-10| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | needs_const(&()); |
| 5 | 5 | | ----------- ^^^ the trait `Trait` is not implemented for `()` |
| ... | ... | @@ -7,18 +7,18 @@ LL | needs_const(&()); |
| 7 | 7 | | required by a bound introduced by this call |
| 8 | 8 | | |
| 9 | 9 | help: 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 | |
| 11 | 11 | | |
| 12 | LL | trait Trait { | |
| 13 | | ^^^^^^^^^^^ | |
| 12 | LL | const trait Trait { | |
| 13 | | ^^^^^^^^^^^^^^^^^ | |
| 14 | 14 | note: 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 | |
| 16 | 16 | | |
| 17 | 17 | LL | const fn needs_const<T: [const] Trait>(_: &T) {} |
| 18 | 18 | | ^^^^^^^^^^^^^ required by this bound in `needs_const` |
| 19 | 19 | |
| 20 | 20 | error[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 | |
| 22 | 22 | | |
| 23 | 23 | LL | needs_const(&()); |
| 24 | 24 | | ----------- ^^^ the trait `Trait` is not implemented for `()` |
| ... | ... | @@ -26,12 +26,12 @@ LL | needs_const(&()); |
| 26 | 26 | | required by a bound introduced by this call |
| 27 | 27 | | |
| 28 | 28 | help: 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 | |
| 30 | 30 | | |
| 31 | LL | trait Trait { | |
| 32 | | ^^^^^^^^^^^ | |
| 31 | LL | const trait Trait { | |
| 32 | | ^^^^^^^^^^^^^^^^^ | |
| 33 | 33 | note: 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 | |
| 35 | 35 | | |
| 36 | 36 | LL | const fn needs_const<T: [const] Trait>(_: &T) {} |
| 37 | 37 | | ^^^^^^^^^^^^^ required by this bound in `needs_const` |
tests/ui/traits/const-traits/effect-param-infer.rs+1-2| ... | ... | @@ -5,8 +5,7 @@ |
| 5 | 5 | //@ compile-flags: -Znext-solver |
| 6 | 6 | #![feature(const_trait_impl)] |
| 7 | 7 | |
| 8 | #[const_trait] | |
| 9 | pub trait Foo<Rhs: ?Sized = Self> { | |
| 8 | pub const trait Foo<Rhs: ?Sized = Self> { | |
| 10 | 9 | /* stuff */ |
| 11 | 10 | } |
| 12 | 11 |
tests/ui/traits/const-traits/eval-bad-signature.rs+1-2| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Value { | |
| 5 | const trait Value { | |
| 7 | 6 | fn value() -> u32; |
| 8 | 7 | } |
| 9 | 8 |
tests/ui/traits/const-traits/eval-bad-signature.stderr+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | fn value() -> i64 { |
| 5 | 5 | | ^^^ expected `u32`, found `i64` |
| 6 | 6 | | |
| 7 | 7 | note: type in trait |
| 8 | --> $DIR/eval-bad-signature.rs:7:19 | |
| 8 | --> $DIR/eval-bad-signature.rs:6:19 | |
| 9 | 9 | | |
| 10 | 10 | LL | fn value() -> u32; |
| 11 | 11 | | ^^^ |
tests/ui/traits/const-traits/feature-gate.rs+1-3| ... | ... | @@ -5,15 +5,13 @@ |
| 5 | 5 | #![cfg_attr(gated, feature(const_trait_impl))] |
| 6 | 6 | |
| 7 | 7 | struct S; |
| 8 | #[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder | |
| 9 | trait T {} | |
| 8 | const trait T {} //[stock]~ ERROR const trait impls are experimental | |
| 10 | 9 | impl const T for S {} |
| 11 | 10 | //[stock]~^ ERROR const trait impls are experimental |
| 12 | 11 | |
| 13 | 12 | const fn f<A: [const] T>() {} //[stock]~ ERROR const trait impls are experimental |
| 14 | 13 | fn g<A: const T>() {} //[stock]~ ERROR const trait impls are experimental |
| 15 | 14 | |
| 16 | const trait Trait {} //[stock]~ ERROR const trait impls are experimental | |
| 17 | 15 | #[cfg(false)] const trait Trait {} //[stock]~ ERROR const trait impls are experimental |
| 18 | 16 | |
| 19 | 17 | macro_rules! discard { ($ty:ty) => {} } |
tests/ui/traits/const-traits/feature-gate.stock.stderr+16-26| ... | ... | @@ -1,45 +1,45 @@ |
| 1 | 1 | error[E0658]: const trait impls are experimental |
| 2 | --> $DIR/feature-gate.rs:10:6 | |
| 2 | --> $DIR/feature-gate.rs:8:1 | |
| 3 | 3 | | |
| 4 | LL | impl const T for S {} | |
| 5 | | ^^^^^ | |
| 4 | LL | const trait T {} | |
| 5 | | ^^^^^ | |
| 6 | 6 | | |
| 7 | 7 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 8 | 8 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 9 | 9 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 10 | 10 | |
| 11 | 11 | error[E0658]: const trait impls are experimental |
| 12 | --> $DIR/feature-gate.rs:13:15 | |
| 12 | --> $DIR/feature-gate.rs:9:6 | |
| 13 | 13 | | |
| 14 | LL | const fn f<A: [const] T>() {} | |
| 15 | | ^^^^^^^ | |
| 14 | LL | impl const T for S {} | |
| 15 | | ^^^^^ | |
| 16 | 16 | | |
| 17 | 17 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 18 | 18 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 19 | 19 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 20 | 20 | |
| 21 | 21 | error[E0658]: const trait impls are experimental |
| 22 | --> $DIR/feature-gate.rs:14:9 | |
| 22 | --> $DIR/feature-gate.rs:12:15 | |
| 23 | 23 | | |
| 24 | LL | fn g<A: const T>() {} | |
| 25 | | ^^^^^ | |
| 24 | LL | const fn f<A: [const] T>() {} | |
| 25 | | ^^^^^^^ | |
| 26 | 26 | | |
| 27 | 27 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 28 | 28 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 29 | 29 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 30 | 30 | |
| 31 | 31 | error[E0658]: const trait impls are experimental |
| 32 | --> $DIR/feature-gate.rs:16:1 | |
| 32 | --> $DIR/feature-gate.rs:13:9 | |
| 33 | 33 | | |
| 34 | LL | const trait Trait {} | |
| 35 | | ^^^^^ | |
| 34 | LL | fn g<A: const T>() {} | |
| 35 | | ^^^^^ | |
| 36 | 36 | | |
| 37 | 37 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 38 | 38 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 39 | 39 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 40 | 40 | |
| 41 | 41 | error[E0658]: const trait impls are experimental |
| 42 | --> $DIR/feature-gate.rs:17:15 | |
| 42 | --> $DIR/feature-gate.rs:15:15 | |
| 43 | 43 | | |
| 44 | 44 | LL | #[cfg(false)] const trait Trait {} |
| 45 | 45 | | ^^^^^ |
| ... | ... | @@ -49,7 +49,7 @@ LL | #[cfg(false)] const trait Trait {} |
| 49 | 49 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 50 | 50 | |
| 51 | 51 | error[E0658]: const trait impls are experimental |
| 52 | --> $DIR/feature-gate.rs:21:17 | |
| 52 | --> $DIR/feature-gate.rs:19:17 | |
| 53 | 53 | | |
| 54 | 54 | LL | discard! { impl [const] T } |
| 55 | 55 | | ^^^^^^^ |
| ... | ... | @@ -59,7 +59,7 @@ LL | discard! { impl [const] T } |
| 59 | 59 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 60 | 60 | |
| 61 | 61 | error[E0658]: const trait impls are experimental |
| 62 | --> $DIR/feature-gate.rs:22:17 | |
| 62 | --> $DIR/feature-gate.rs:20:17 | |
| 63 | 63 | | |
| 64 | 64 | LL | discard! { impl const T } |
| 65 | 65 | | ^^^^^ |
| ... | ... | @@ -68,16 +68,6 @@ LL | discard! { impl const T } |
| 68 | 68 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 69 | 69 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 70 | 70 | |
| 71 | error[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 | | | |
| 74 | LL | #[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 | ||
| 81 | error: aborting due to 8 previous errors | |
| 71 | error: aborting due to 7 previous errors | |
| 82 | 72 | |
| 83 | 73 | For 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 @@ |
| 1 | 1 | //@ check-pass |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | |
| 4 | #[const_trait] | |
| 5 | pub trait Test {} | |
| 4 | pub const trait Test {} | |
| 6 | 5 | |
| 7 | 6 | impl Test for () {} |
| 8 | 7 |
tests/ui/traits/const-traits/hir-const-check.rs+1-2| ... | ... | @@ -6,8 +6,7 @@ |
| 6 | 6 | #![feature(const_trait_impl)] |
| 7 | 7 | #![feature(const_try)] |
| 8 | 8 | |
| 9 | #[const_trait] | |
| 10 | pub trait MyTrait { | |
| 9 | pub const trait MyTrait { | |
| 11 | 10 | fn method(&self) -> Option<()>; |
| 12 | 11 | } |
| 13 | 12 |
tests/ui/traits/const-traits/ice-121536-const-method.rs+1-2| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | pub struct Vec3; |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | pub trait Add { | |
| 5 | pub const trait Add { | |
| 7 | 6 | fn add(self) -> Vec3; |
| 8 | 7 | } |
| 9 | 8 |
tests/ui/traits/const-traits/ice-121536-const-method.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | const fn add(self) -> Vec3 { |
| 5 | 5 | | ^^^^^ 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 @@ |
| 2 | 2 | |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Foo {} | |
| 5 | const trait Foo {} | |
| 7 | 6 | |
| 8 | 7 | impl const Foo for i32 {} |
| 9 | 8 |
tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | impl const Foo for i32 {} |
| 5 | 5 | | ---------------------- first implementation here |
tests/ui/traits/const-traits/impl-with-default-fn-fail.rs+1-2| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | #![feature(const_trait_impl)] |
| 2 | 2 | |
| 3 | #[const_trait] | |
| 4 | trait Tr { | |
| 3 | const trait Tr { | |
| 5 | 4 | fn req(&self); |
| 6 | 5 | |
| 7 | 6 | fn default() {} |
tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | fn req(&self); |
| 5 | 5 | | -------------- `req` from trait |
tests/ui/traits/const-traits/impl-with-default-fn-pass.rs+1-2| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | //@ compile-flags: -Znext-solver |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Tr { | |
| 5 | const trait Tr { | |
| 7 | 6 | fn req(&self); |
| 8 | 7 | |
| 9 | 8 | fn default() {} |
tests/ui/traits/const-traits/imply-always-const.rs+2-4| ... | ... | @@ -2,13 +2,11 @@ |
| 2 | 2 | |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait A where Self::Assoc: const B { | |
| 5 | const trait A where Self::Assoc: const B { | |
| 7 | 6 | type Assoc; |
| 8 | 7 | } |
| 9 | 8 | |
| 10 | #[const_trait] | |
| 11 | trait B {} | |
| 9 | const trait B {} | |
| 12 | 10 | |
| 13 | 11 | fn needs_b<T: const B>() {} |
| 14 | 12 |
tests/ui/traits/const-traits/inherent-impl-const-bounds.rs+2-4| ... | ... | @@ -3,10 +3,8 @@ |
| 3 | 3 | |
| 4 | 4 | struct S; |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait A {} | |
| 8 | #[const_trait] | |
| 9 | trait B {} | |
| 6 | const trait A {} | |
| 7 | const trait B {} | |
| 10 | 8 | |
| 11 | 9 | impl const A for S {} |
| 12 | 10 | impl 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); |
| 23 | 23 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants |
| 24 | 24 | help: consider making trait `Trait` const |
| 25 | 25 | | |
| 26 | LL + #[const_trait] | |
| 27 | LL | trait Trait { | |
| 28 | | | |
| 26 | LL | const trait Trait { | |
| 27 | | +++++ | |
| 29 | 28 | |
| 30 | 29 | error: aborting due to 2 previous errors |
| 31 | 30 |
tests/ui/traits/const-traits/issue-100222.rs+12-4| ... | ... | @@ -5,12 +5,20 @@ |
| 5 | 5 | #![allow(incomplete_features)] |
| 6 | 6 | #![feature(const_trait_impl, associated_type_defaults)] |
| 7 | 7 | |
| 8 | #[cfg_attr(any(yn, yy), const_trait)] | |
| 9 | pub 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))] | |
| 12 | pub const trait IndexMut | |
| 13 | where | |
| 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; | |
| 11 | 19 | } |
| 12 | 20 | |
| 13 | #[cfg_attr(any(ny, yy), const_trait)] | |
| 21 | #[cfg(not(any(ny, yy)))] | |
| 14 | 22 | pub trait IndexMut |
| 15 | 23 | where |
| 16 | 24 | Self: Index, |
tests/ui/traits/const-traits/issue-79450.rs+1-2| ... | ... | @@ -1,8 +1,7 @@ |
| 1 | 1 | //@ compile-flags: -Znext-solver |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | |
| 4 | #[const_trait] | |
| 5 | trait Tr { | |
| 4 | const trait Tr { | |
| 6 | 5 | fn req(&self); |
| 7 | 6 | |
| 8 | 7 | fn prov(&self) { |
tests/ui/traits/const-traits/issue-79450.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[E0015]: cannot call non-const function `_print` in constant functions |
| 2 | --> $DIR/issue-79450.rs:9:9 | |
| 2 | --> $DIR/issue-79450.rs:8:9 | |
| 3 | 3 | | |
| 4 | 4 | LL | println!("lul"); |
| 5 | 5 | | ^^^^^^^^^^^^^^^ |
tests/ui/traits/const-traits/issue-88155.stderr+2-3| ... | ... | @@ -14,9 +14,8 @@ LL | fn assoc() -> bool; |
| 14 | 14 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants |
| 15 | 15 | help: consider making trait `A` const |
| 16 | 16 | | |
| 17 | LL + #[const_trait] | |
| 18 | LL | pub trait A { | |
| 19 | | | |
| 17 | LL | pub const trait A { | |
| 18 | | +++++ | |
| 20 | 19 | |
| 21 | 20 | error: aborting due to 1 previous error |
| 22 | 21 |
tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs+2-4| ... | ... | @@ -5,10 +5,8 @@ |
| 5 | 5 | |
| 6 | 6 | #![feature(const_trait_impl)] |
| 7 | 7 | |
| 8 | #[const_trait] | |
| 9 | pub trait Super {} | |
| 10 | #[const_trait] | |
| 11 | pub trait Sub: Super {} | |
| 8 | pub const trait Super {} | |
| 9 | pub const trait Sub: Super {} | |
| 12 | 10 | |
| 13 | 11 | impl<A> const Super for &A where A: [const] Super {} |
| 14 | 12 | impl<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 @@ |
| 1 | 1 | //@ compile-flags: -Znext-solver |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | |
| 4 | #[const_trait] trait Foo { | |
| 4 | const trait Foo { | |
| 5 | 5 | type Assoc<T>: [const] Bar |
| 6 | 6 | where |
| 7 | 7 | T: [const] Bar; |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | #[const_trait] trait Bar {} | |
| 10 | const trait Bar {} | |
| 11 | 11 | struct N<T>(T); |
| 12 | 12 | impl<T> Bar for N<T> where T: Bar {} |
| 13 | 13 | struct C<T>(T); |
tests/ui/traits/const-traits/item-bound-entailment.rs+2-2| ... | ... | @@ -3,13 +3,13 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] trait Foo { | |
| 6 | const trait Foo { | |
| 7 | 7 | type Assoc<T>: [const] Bar |
| 8 | 8 | where |
| 9 | 9 | T: [const] Bar; |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | #[const_trait] trait Bar {} | |
| 12 | const trait Bar {} | |
| 13 | 13 | struct N<T>(T); |
| 14 | 14 | impl<T> Bar for N<T> where T: Bar {} |
| 15 | 15 | struct C<T>(T); |
tests/ui/traits/const-traits/minicore-drop-fail.rs+1-1| ... | ... | @@ -15,7 +15,7 @@ impl Drop for NotDropImpl { |
| 15 | 15 | fn drop(&mut self) {} |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | #[const_trait] trait Foo {} | |
| 18 | const trait Foo {} | |
| 19 | 19 | impl Foo for () {} |
| 20 | 20 | |
| 21 | 21 | struct Conditional<T: Foo>(T); |
tests/ui/traits/const-traits/minicore-fn-fail.rs+1-2| ... | ... | @@ -10,8 +10,7 @@ use minicore::*; |
| 10 | 10 | |
| 11 | 11 | const fn call_indirect<T: [const] Fn()>(t: &T) { t() } |
| 12 | 12 | |
| 13 | #[const_trait] | |
| 14 | trait Foo {} | |
| 13 | const trait Foo {} | |
| 15 | 14 | impl Foo for () {} |
| 16 | 15 | const fn foo<T: [const] Foo>() {} |
| 17 | 16 |
tests/ui/traits/const-traits/minicore-fn-fail.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | call_indirect(&foo::<()>); |
| 5 | 5 | | ------------- ^^^^^^^^^^ |
tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs+1-2| ... | ... | @@ -17,7 +17,6 @@ fn const_negative<T: const !Trait>() {} |
| 17 | 17 | //~^ ERROR `const` trait not allowed with `!` trait polarity modifier |
| 18 | 18 | //~| ERROR negative bounds are not supported |
| 19 | 19 | |
| 20 | #[const_trait] | |
| 21 | trait Trait {} | |
| 20 | const trait Trait {} | |
| 22 | 21 | |
| 23 | 22 | fn main() {} |
tests/ui/traits/const-traits/no-explicit-const-params.rs+1-2| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | const fn foo() {} |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Bar { | |
| 5 | const trait Bar { | |
| 7 | 6 | fn bar(); |
| 8 | 7 | } |
| 9 | 8 |
tests/ui/traits/const-traits/no-explicit-const-params.stderr+11-11| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | foo::<true>(); |
| 5 | 5 | | ^^^-------- help: remove the unnecessary generics |
| ... | ... | @@ -13,7 +13,7 @@ LL | const fn foo() {} |
| 13 | 13 | | ^^^ |
| 14 | 14 | |
| 15 | 15 | error[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 | |
| 17 | 17 | | |
| 18 | 18 | LL | <() as Bar<true>>::bar(); |
| 19 | 19 | | ^^^------ help: remove the unnecessary generics |
| ... | ... | @@ -21,13 +21,13 @@ LL | <() as Bar<true>>::bar(); |
| 21 | 21 | | expected 0 generic arguments |
| 22 | 22 | | |
| 23 | 23 | note: 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 | |
| 25 | 25 | | |
| 26 | LL | trait Bar { | |
| 27 | | ^^^ | |
| 26 | LL | const trait Bar { | |
| 27 | | ^^^ | |
| 28 | 28 | |
| 29 | 29 | error[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 | |
| 31 | 31 | | |
| 32 | 32 | LL | foo::<false>(); |
| 33 | 33 | | ^^^--------- help: remove the unnecessary generics |
| ... | ... | @@ -41,7 +41,7 @@ LL | const fn foo() {} |
| 41 | 41 | | ^^^ |
| 42 | 42 | |
| 43 | 43 | error[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 | |
| 45 | 45 | | |
| 46 | 46 | LL | <() as Bar<false>>::bar(); |
| 47 | 47 | | ^^^------- help: remove the unnecessary generics |
| ... | ... | @@ -49,13 +49,13 @@ LL | <() as Bar<false>>::bar(); |
| 49 | 49 | | expected 0 generic arguments |
| 50 | 50 | | |
| 51 | 51 | note: 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 | |
| 53 | 53 | | |
| 54 | LL | trait Bar { | |
| 55 | | ^^^ | |
| 54 | LL | const trait Bar { | |
| 55 | | ^^^ | |
| 56 | 56 | |
| 57 | 57 | error[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 | |
| 59 | 59 | | |
| 60 | 60 | LL | <() as Bar<false>>::bar(); |
| 61 | 61 | | ^^ |
tests/ui/traits/const-traits/non-const-op-in-closure-in-const.rs+1-2| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | //@ check-pass |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Convert<T> { | |
| 5 | const trait Convert<T> { | |
| 7 | 6 | fn to(self) -> T; |
| 8 | 7 | } |
| 9 | 8 |
tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | / impl<T> const Foo for T |
| 5 | 5 | LL | | where |
tests/ui/traits/const-traits/overlap-const-with-nonconst.rs+2-4| ... | ... | @@ -5,12 +5,10 @@ |
| 5 | 5 | //[spec]~^ WARN the feature `specialization` is incomplete |
| 6 | 6 | #![cfg_attr(min_spec, feature(min_specialization))] |
| 7 | 7 | |
| 8 | #[const_trait] | |
| 9 | trait Bar {} | |
| 8 | const trait Bar {} | |
| 10 | 9 | impl<T> const Bar for T {} |
| 11 | 10 | |
| 12 | #[const_trait] | |
| 13 | trait Foo { | |
| 11 | const trait Foo { | |
| 14 | 12 | fn method(&self); |
| 15 | 13 | } |
| 16 | 14 | impl<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))] |
| 9 | 9 | = note: `#[warn(incomplete_features)]` on by default |
| 10 | 10 | |
| 11 | 11 | error[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 | |
| 13 | 13 | | |
| 14 | 14 | LL | / impl<T> const Foo for T |
| 15 | 15 | LL | | where |
tests/ui/traits/const-traits/predicate-entailment-fails.rs+3-3| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | //@ compile-flags: -Znext-solver |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | |
| 4 | #[const_trait] trait Bar {} | |
| 4 | const trait Bar {} | |
| 5 | 5 | impl const Bar for () {} |
| 6 | 6 | |
| 7 | 7 | |
| 8 | #[const_trait] trait TildeConst { | |
| 8 | const trait TildeConst { | |
| 9 | 9 | type Bar<T> where T: [const] Bar; |
| 10 | 10 | |
| 11 | 11 | fn foo<T>() where T: [const] Bar; |
| ... | ... | @@ -19,7 +19,7 @@ impl TildeConst for () { |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | 21 | |
| 22 | #[const_trait] trait NeverConst { | |
| 22 | const trait NeverConst { | |
| 23 | 23 | type Bar<T> where T: Bar; |
| 24 | 24 | |
| 25 | 25 | fn foo<T>() where T: Bar; |
tests/ui/traits/const-traits/predicate-entailment-passes.rs+3-3| ... | ... | @@ -3,10 +3,10 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] trait Bar {} | |
| 6 | const trait Bar {} | |
| 7 | 7 | impl const Bar for () {} |
| 8 | 8 | |
| 9 | #[const_trait] trait TildeConst { | |
| 9 | const trait TildeConst { | |
| 10 | 10 | fn foo<T>() where T: [const] Bar; |
| 11 | 11 | } |
| 12 | 12 | impl TildeConst for () { |
| ... | ... | @@ -14,7 +14,7 @@ impl TildeConst for () { |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | 16 | |
| 17 | #[const_trait] trait AlwaysConst { | |
| 17 | const trait AlwaysConst { | |
| 18 | 18 | fn foo<T>() where T: const Bar; |
| 19 | 19 | } |
| 20 | 20 | impl AlwaysConst for i32 { |
tests/ui/traits/const-traits/project.rs+2-4| ... | ... | @@ -2,11 +2,9 @@ |
| 2 | 2 | //@ compile-flags: -Znext-solver |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | pub trait Owo<X = <Self as Uwu>::T> {} | |
| 5 | pub const trait Owo<X = <Self as Uwu>::T> {} | |
| 7 | 6 | |
| 8 | #[const_trait] | |
| 9 | pub trait Uwu: Owo { | |
| 7 | pub const trait Uwu: Owo { | |
| 10 | 8 | type T; |
| 11 | 9 | } |
| 12 | 10 |
tests/ui/traits/const-traits/spec-effectvar-ice.stderr+6-6| ... | ... | @@ -8,8 +8,8 @@ LL | impl<T> const Foo for T {} |
| 8 | 8 | = note: adding a non-const method body in the future would be a breaking change |
| 9 | 9 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 10 | 10 | | |
| 11 | LL | #[const_trait] trait Foo {} | |
| 12 | | ++++++++++++++ | |
| 11 | LL | const trait Foo {} | |
| 12 | | +++++ | |
| 13 | 13 | |
| 14 | 14 | error: const `impl` for trait `Foo` which is not `const` |
| 15 | 15 | --> $DIR/spec-effectvar-ice.rs:13:15 |
| ... | ... | @@ -21,8 +21,8 @@ LL | impl<T> const Foo for T where T: const Specialize {} |
| 21 | 21 | = note: adding a non-const method body in the future would be a breaking change |
| 22 | 22 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 23 | 23 | | |
| 24 | LL | #[const_trait] trait Foo {} | |
| 25 | | ++++++++++++++ | |
| 24 | LL | const trait Foo {} | |
| 25 | | +++++ | |
| 26 | 26 | |
| 27 | 27 | error: `const` can only be applied to `const` traits |
| 28 | 28 | --> $DIR/spec-effectvar-ice.rs:13:34 |
| ... | ... | @@ -32,8 +32,8 @@ LL | impl<T> const Foo for T where T: const Specialize {} |
| 32 | 32 | | |
| 33 | 33 | help: mark `Specialize` as `const` to allow it to have `const` implementations |
| 34 | 34 | | |
| 35 | LL | #[const_trait] trait Specialize {} | |
| 36 | | ++++++++++++++ | |
| 35 | LL | const trait Specialize {} | |
| 36 | | +++++ | |
| 37 | 37 | |
| 38 | 38 | error: specialization impl does not specialize any associated items |
| 39 | 39 | --> $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 @@ |
| 10 | 10 | #[rustc_specialization_trait] |
| 11 | 11 | trait Specialize {} |
| 12 | 12 | |
| 13 | #[const_trait] | |
| 14 | trait Foo {} | |
| 13 | const trait Foo {} | |
| 15 | 14 | |
| 16 | #[const_trait] | |
| 17 | trait Bar { | |
| 15 | const trait Bar { | |
| 18 | 16 | fn bar(); |
| 19 | 17 | } |
| 20 | 18 | |
| ... | ... | @@ -33,8 +31,7 @@ where |
| 33 | 31 | fn bar() {} |
| 34 | 32 | } |
| 35 | 33 | |
| 36 | #[const_trait] | |
| 37 | trait Baz { | |
| 34 | const trait Baz { | |
| 38 | 35 | fn baz(); |
| 39 | 36 | } |
| 40 | 37 |
tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr+2-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | / impl<T> const Bar for T |
| 5 | 5 | LL | | where |
| ... | ... | @@ -13,7 +13,7 @@ LL | | T: Specialize, |
| 13 | 13 | | |__________________^ conflicting implementation |
| 14 | 14 | |
| 15 | 15 | error[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 | |
| 17 | 17 | | |
| 18 | 18 | LL | / impl<T> const Baz for T |
| 19 | 19 | LL | | where |
tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs+1-2| ... | ... | @@ -6,8 +6,7 @@ |
| 6 | 6 | #![feature(const_trait_impl)] |
| 7 | 7 | #![feature(min_specialization)] |
| 8 | 8 | |
| 9 | #[const_trait] | |
| 10 | trait Value { | |
| 9 | const trait Value { | |
| 11 | 10 | fn value() -> u32; |
| 12 | 11 | } |
| 13 | 12 |
tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | impl<T> const Value for T { |
| 5 | 5 | | ------------------------- first implementation here |
tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs+1-2| ... | ... | @@ -6,8 +6,7 @@ |
| 6 | 6 | //[spec]~^ WARN the feature `specialization` is incomplete |
| 7 | 7 | #![cfg_attr(min_spec, feature(min_specialization))] |
| 8 | 8 | |
| 9 | #[const_trait] | |
| 10 | trait Value { | |
| 9 | const trait Value { | |
| 11 | 10 | fn value() -> u32; |
| 12 | 11 | } |
| 13 | 12 |
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))] |
| 9 | 9 | = note: `#[warn(incomplete_features)]` on by default |
| 10 | 10 | |
| 11 | 11 | error[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 | |
| 13 | 13 | | |
| 14 | 14 | LL | impl<T> const Value for T { |
| 15 | 15 | | ------------------------- first implementation here |
tests/ui/traits/const-traits/specialization/default-keyword.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | #![feature(min_specialization)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Foo { | |
| 6 | const trait Foo { | |
| 8 | 7 | fn foo(); |
| 9 | 8 | } |
| 10 | 9 |
tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs+3-6| ... | ... | @@ -11,11 +11,9 @@ |
| 11 | 11 | #[rustc_specialization_trait] |
| 12 | 12 | trait Specialize {} |
| 13 | 13 | |
| 14 | #[const_trait] | |
| 15 | trait Foo {} | |
| 14 | const trait Foo {} | |
| 16 | 15 | |
| 17 | #[const_trait] | |
| 18 | trait Bar { | |
| 16 | const trait Bar { | |
| 19 | 17 | fn bar(); |
| 20 | 18 | } |
| 21 | 19 | |
| ... | ... | @@ -34,8 +32,7 @@ where |
| 34 | 32 | fn bar() {} |
| 35 | 33 | } |
| 36 | 34 | |
| 37 | #[const_trait] | |
| 38 | trait Baz { | |
| 35 | const trait Baz { | |
| 39 | 36 | fn baz(); |
| 40 | 37 | } |
| 41 | 38 |
tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs+1-2| ... | ... | @@ -6,8 +6,7 @@ |
| 6 | 6 | #![feature(const_trait_impl)] |
| 7 | 7 | #![feature(min_specialization)] |
| 8 | 8 | |
| 9 | #[const_trait] | |
| 10 | trait Value { | |
| 9 | const trait Value { | |
| 11 | 10 | fn value() -> u32; |
| 12 | 11 | } |
| 13 | 12 |
tests/ui/traits/const-traits/specialization/specialize-on-conditionally-const.rs+3-6| ... | ... | @@ -7,12 +7,10 @@ |
| 7 | 7 | #![feature(rustc_attrs)] |
| 8 | 8 | #![feature(min_specialization)] |
| 9 | 9 | |
| 10 | #[const_trait] | |
| 11 | 10 | #[rustc_specialization_trait] |
| 12 | trait Specialize {} | |
| 11 | const trait Specialize {} | |
| 13 | 12 | |
| 14 | #[const_trait] | |
| 15 | trait Foo { | |
| 13 | const trait Foo { | |
| 16 | 14 | fn foo(); |
| 17 | 15 | } |
| 18 | 16 | |
| ... | ... | @@ -27,8 +25,7 @@ where |
| 27 | 25 | fn foo() {} |
| 28 | 26 | } |
| 29 | 27 | |
| 30 | #[const_trait] | |
| 31 | trait Bar { | |
| 28 | const trait Bar { | |
| 32 | 29 | fn bar() {} |
| 33 | 30 | } |
| 34 | 31 |
tests/ui/traits/const-traits/specializing-constness-2.rs+2-4| ... | ... | @@ -1,13 +1,11 @@ |
| 1 | 1 | #![feature(const_trait_impl, min_specialization, rustc_attrs)] |
| 2 | 2 | //@ known-bug: #110395 |
| 3 | 3 | #[rustc_specialization_trait] |
| 4 | #[const_trait] | |
| 5 | pub trait Sup {} | |
| 4 | pub const trait Sup {} | |
| 6 | 5 | |
| 7 | 6 | impl const Sup for () {} |
| 8 | 7 | |
| 9 | #[const_trait] | |
| 10 | pub trait A { | |
| 8 | pub const trait A { | |
| 11 | 9 | fn a() -> u32; |
| 12 | 10 | } |
| 13 | 11 |
tests/ui/traits/const-traits/specializing-constness-2.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | <T as A>::a(); |
| 5 | 5 | | ^ |
tests/ui/traits/const-traits/specializing-constness.rs+3-6| ... | ... | @@ -1,18 +1,15 @@ |
| 1 | 1 | #![feature(const_trait_impl, min_specialization, rustc_attrs)] |
| 2 | 2 | |
| 3 | 3 | #[rustc_specialization_trait] |
| 4 | #[const_trait] | |
| 5 | pub trait Sup {} | |
| 4 | pub const trait Sup {} | |
| 6 | 5 | |
| 7 | 6 | impl const Sup for () {} |
| 8 | 7 | |
| 9 | #[const_trait] | |
| 10 | pub trait A { | |
| 8 | pub const trait A { | |
| 11 | 9 | fn a() -> u32; |
| 12 | 10 | } |
| 13 | 11 | |
| 14 | #[const_trait] | |
| 15 | pub trait Spec {} | |
| 12 | pub const trait Spec {} | |
| 16 | 13 | |
| 17 | 14 | impl<T: [const] Spec> const A for T { |
| 18 | 15 | default fn a() -> u32 { |
tests/ui/traits/const-traits/specializing-constness.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[E0119]: conflicting implementations of trait `A` |
| 2 | --> $DIR/specializing-constness.rs:23:1 | |
| 2 | --> $DIR/specializing-constness.rs:20:1 | |
| 3 | 3 | | |
| 4 | 4 | LL | impl<T: [const] Spec> const A for T { |
| 5 | 5 | | ----------------------------------- first implementation here |
tests/ui/traits/const-traits/staged-api.rs+2-4| ... | ... | @@ -86,13 +86,11 @@ const fn implicitly_stable_const_context() { |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | 88 | // check that const stability of impls and traits must match |
| 89 | #[const_trait] | |
| 90 | 89 | #[rustc_const_unstable(feature = "beef", issue = "none")] |
| 91 | trait U {} | |
| 90 | const trait U {} | |
| 92 | 91 | |
| 93 | #[const_trait] | |
| 94 | 92 | #[rustc_const_stable(since = "0.0.0", feature = "beef2")] |
| 95 | trait S {} | |
| 93 | const trait S {} | |
| 96 | 94 | |
| 97 | 95 | // implied stable |
| 98 | 96 | impl const U for u8 {} |
tests/ui/traits/const-traits/staged-api.stderr+17-17| ... | ... | @@ -1,22 +1,22 @@ |
| 1 | 1 | error: 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 | |
| 3 | 3 | | |
| 4 | 4 | LL | impl const U for u8 {} |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^^^ |
| 6 | 6 | | |
| 7 | 7 | note: this impl is (implicitly) stable... |
| 8 | --> $DIR/staged-api.rs:98:1 | |
| 8 | --> $DIR/staged-api.rs:96:1 | |
| 9 | 9 | | |
| 10 | 10 | LL | impl const U for u8 {} |
| 11 | 11 | | ^^^^^^^^^^^^^^^^^^^^^^ |
| 12 | 12 | note: ...but the trait is unstable |
| 13 | --> $DIR/staged-api.rs:91:7 | |
| 13 | --> $DIR/staged-api.rs:90:13 | |
| 14 | 14 | | |
| 15 | LL | trait U {} | |
| 16 | | ^ | |
| 15 | LL | const trait U {} | |
| 16 | | ^ | |
| 17 | 17 | |
| 18 | 18 | error: trait implementations cannot be const stable yet |
| 19 | --> $DIR/staged-api.rs:102:1 | |
| 19 | --> $DIR/staged-api.rs:100:1 | |
| 20 | 20 | | |
| 21 | 21 | LL | impl const U for u16 {} |
| 22 | 22 | | ^^^^^^^^^^^^^^^^^^^^^^^ |
| ... | ... | @@ -24,24 +24,24 @@ LL | impl const U for u16 {} |
| 24 | 24 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 25 | 25 | |
| 26 | 26 | error: 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 | |
| 28 | 28 | | |
| 29 | 29 | LL | impl const U for u16 {} |
| 30 | 30 | | ^^^^^^^^^^^^^^^^^^^^^^^ |
| 31 | 31 | | |
| 32 | 32 | note: this impl is (implicitly) stable... |
| 33 | --> $DIR/staged-api.rs:102:1 | |
| 33 | --> $DIR/staged-api.rs:100:1 | |
| 34 | 34 | | |
| 35 | 35 | LL | impl const U for u16 {} |
| 36 | 36 | | ^^^^^^^^^^^^^^^^^^^^^^^ |
| 37 | 37 | note: ...but the trait is unstable |
| 38 | --> $DIR/staged-api.rs:91:7 | |
| 38 | --> $DIR/staged-api.rs:90:13 | |
| 39 | 39 | | |
| 40 | LL | trait U {} | |
| 41 | | ^ | |
| 40 | LL | const trait U {} | |
| 41 | | ^ | |
| 42 | 42 | |
| 43 | 43 | error: trait implementations cannot be const stable yet |
| 44 | --> $DIR/staged-api.rs:113:1 | |
| 44 | --> $DIR/staged-api.rs:111:1 | |
| 45 | 45 | | |
| 46 | 46 | LL | impl const S for u16 {} |
| 47 | 47 | | ^^^^^^^^^^^^^^^^^^^^^^^ |
| ... | ... | @@ -49,21 +49,21 @@ LL | impl const S for u16 {} |
| 49 | 49 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 50 | 50 | |
| 51 | 51 | error: 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 | |
| 53 | 53 | | |
| 54 | 54 | LL | impl const S for u32 {} |
| 55 | 55 | | ^^^^^^^^^^^^^^^^^^^^^^^ |
| 56 | 56 | | |
| 57 | 57 | note: this impl is unstable... |
| 58 | --> $DIR/staged-api.rs:117:1 | |
| 58 | --> $DIR/staged-api.rs:115:1 | |
| 59 | 59 | | |
| 60 | 60 | LL | impl const S for u32 {} |
| 61 | 61 | | ^^^^^^^^^^^^^^^^^^^^^^^ |
| 62 | 62 | note: ...but the trait is stable |
| 63 | --> $DIR/staged-api.rs:95:7 | |
| 63 | --> $DIR/staged-api.rs:93:13 | |
| 64 | 64 | | |
| 65 | LL | trait S {} | |
| 66 | | ^ | |
| 65 | LL | const trait S {} | |
| 66 | | ^ | |
| 67 | 67 | |
| 68 | 68 | error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` |
| 69 | 69 | --> $DIR/staged-api.rs:38:5 |
tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr+29-30| ... | ... | @@ -1,69 +1,68 @@ |
| 1 | 1 | error: `[const]` is not allowed here |
| 2 | --> $DIR/super-traits-fail-2.rs:11:12 | |
| 2 | --> $DIR/super-traits-fail-2.rs:14:32 | |
| 3 | 3 | | |
| 4 | LL | trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 4 | LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | LL | trait Bar: [const] Foo {} | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 10 | LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 12 | 12 | |
| 13 | 13 | error: `[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 | |
| 15 | 15 | | |
| 16 | LL | trait Bar: [const] Foo {} | |
| 17 | | ^^^^^^^ can't be applied to `Foo` | |
| 16 | LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} | |
| 17 | | ^^^^^^^ can't be applied to `Foo` | |
| 18 | 18 | | |
| 19 | 19 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 20 | 20 | | |
| 21 | LL | #[const_trait] trait Foo { | |
| 22 | | ++++++++++++++ | |
| 21 | LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } | |
| 22 | | +++++ | |
| 23 | 23 | |
| 24 | 24 | error: `[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 | |
| 26 | 26 | | |
| 27 | LL | trait Bar: [const] Foo {} | |
| 28 | | ^^^^^^^ can't be applied to `Foo` | |
| 27 | LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} | |
| 28 | | ^^^^^^^ can't be applied to `Foo` | |
| 29 | 29 | | |
| 30 | 30 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 31 | 31 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 32 | 32 | | |
| 33 | LL | #[const_trait] trait Foo { | |
| 34 | | ++++++++++++++ | |
| 33 | LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } | |
| 34 | | +++++ | |
| 35 | 35 | |
| 36 | 36 | error: `[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 | |
| 38 | 38 | | |
| 39 | LL | trait Bar: [const] Foo {} | |
| 40 | | ^^^^^^^ can't be applied to `Foo` | |
| 39 | LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} | |
| 40 | | ^^^^^^^ can't be applied to `Foo` | |
| 41 | 41 | | |
| 42 | 42 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 43 | 43 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 44 | 44 | | |
| 45 | LL | #[const_trait] trait Foo { | |
| 46 | | ++++++++++++++ | |
| 45 | LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } | |
| 46 | | +++++ | |
| 47 | 47 | |
| 48 | 48 | error[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 | |
| 50 | 50 | | |
| 51 | 51 | LL | x.a(); |
| 52 | 52 | | ^^^ |
| 53 | 53 | | |
| 54 | 54 | note: 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 | |
| 56 | 56 | | |
| 57 | LL | trait Foo { | |
| 58 | | ^^^^^^^^^ this trait is not const | |
| 59 | LL | fn a(&self); | |
| 60 | | ------------ this method is not const | |
| 57 | LL | #[cfg(any(ny, nn))] trait Foo { fn a(&self); } | |
| 58 | | ^^^^^^^^^ ------------ this method is not const | |
| 59 | | | | |
| 60 | | this trait is not const | |
| 61 | 61 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants |
| 62 | 62 | help: consider making trait `Foo` const |
| 63 | 63 | | |
| 64 | LL + #[const_trait] | |
| 65 | LL | trait Foo { | |
| 66 | | | |
| 64 | LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } | |
| 65 | | +++++ | |
| 67 | 66 | |
| 68 | 67 | error: aborting due to 5 previous errors |
| 69 | 68 |
tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr+33-34| ... | ... | @@ -1,81 +1,80 @@ |
| 1 | 1 | error: `[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 | |
| 3 | 3 | | |
| 4 | LL | trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ can't be applied to `Foo` | |
| 4 | LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ can't be applied to `Foo` | |
| 6 | 6 | | |
| 7 | 7 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 8 | 8 | | |
| 9 | LL | #[const_trait] trait Foo { | |
| 10 | | ++++++++++++++ | |
| 9 | LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } | |
| 10 | | +++++ | |
| 11 | 11 | |
| 12 | 12 | error: `[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 | |
| 14 | 14 | | |
| 15 | LL | trait Bar: [const] Foo {} | |
| 16 | | ^^^^^^^ can't be applied to `Foo` | |
| 15 | LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {} | |
| 16 | | ^^^^^^^ can't be applied to `Foo` | |
| 17 | 17 | | |
| 18 | 18 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 19 | 19 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 20 | 20 | | |
| 21 | LL | #[const_trait] trait Foo { | |
| 22 | | ++++++++++++++ | |
| 21 | LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } | |
| 22 | | +++++ | |
| 23 | 23 | |
| 24 | 24 | error: `[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 | |
| 26 | 26 | | |
| 27 | LL | trait Bar: [const] Foo {} | |
| 28 | | ^^^^^^^ can't be applied to `Foo` | |
| 27 | LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {} | |
| 28 | | ^^^^^^^ can't be applied to `Foo` | |
| 29 | 29 | | |
| 30 | 30 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 31 | 31 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 32 | 32 | | |
| 33 | LL | #[const_trait] trait Foo { | |
| 34 | | ++++++++++++++ | |
| 33 | LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } | |
| 34 | | +++++ | |
| 35 | 35 | |
| 36 | 36 | error: `[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 | |
| 38 | 38 | | |
| 39 | LL | trait Bar: [const] Foo {} | |
| 40 | | ^^^^^^^ can't be applied to `Foo` | |
| 39 | LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {} | |
| 40 | | ^^^^^^^ can't be applied to `Foo` | |
| 41 | 41 | | |
| 42 | 42 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 43 | 43 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 44 | 44 | | |
| 45 | LL | #[const_trait] trait Foo { | |
| 46 | | ++++++++++++++ | |
| 45 | LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } | |
| 46 | | +++++ | |
| 47 | 47 | |
| 48 | 48 | error: `[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 | |
| 50 | 50 | | |
| 51 | LL | trait Bar: [const] Foo {} | |
| 52 | | ^^^^^^^ can't be applied to `Foo` | |
| 51 | LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {} | |
| 52 | | ^^^^^^^ can't be applied to `Foo` | |
| 53 | 53 | | |
| 54 | 54 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 55 | 55 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 56 | 56 | | |
| 57 | LL | #[const_trait] trait Foo { | |
| 58 | | ++++++++++++++ | |
| 57 | LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } | |
| 58 | | +++++ | |
| 59 | 59 | |
| 60 | 60 | error[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 | |
| 62 | 62 | | |
| 63 | 63 | LL | x.a(); |
| 64 | 64 | | ^^^ |
| 65 | 65 | | |
| 66 | 66 | note: 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 | |
| 68 | 68 | | |
| 69 | LL | trait Foo { | |
| 70 | | ^^^^^^^^^ this trait is not const | |
| 71 | LL | fn a(&self); | |
| 72 | | ------------ this method is not const | |
| 69 | LL | #[cfg(any(ny, nn))] trait Foo { fn a(&self); } | |
| 70 | | ^^^^^^^^^ ------------ this method is not const | |
| 71 | | | | |
| 72 | | this trait is not const | |
| 73 | 73 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants |
| 74 | 74 | help: consider making trait `Foo` const |
| 75 | 75 | | |
| 76 | LL + #[const_trait] | |
| 77 | LL | trait Foo { | |
| 78 | | | |
| 76 | LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } | |
| 77 | | +++++ | |
| 79 | 78 | |
| 80 | 79 | error: aborting due to 6 previous errors |
| 81 | 80 |
tests/ui/traits/const-traits/super-traits-fail-2.rs+11-10| ... | ... | @@ -2,19 +2,20 @@ |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | //@ revisions: yy yn ny nn |
| 4 | 4 | |
| 5 | #[cfg_attr(any(yy, yn), const_trait)] | |
| 6 | trait 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); } | |
| 9 | 7 | |
| 10 | #[cfg_attr(any(yy, ny), const_trait)] | |
| 11 | trait 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 | |
| 15 | 12 | //[ny]~| ERROR: `[const]` can only be applied to `const` traits |
| 16 | 13 | //[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 | |
| 18 | 19 | |
| 19 | 20 | const fn foo<T: Bar>(x: &T) { |
| 20 | 21 | x.a(); |
tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr+7-7| ... | ... | @@ -1,17 +1,17 @@ |
| 1 | 1 | error: `[const]` is not allowed here |
| 2 | --> $DIR/super-traits-fail-2.rs:11:12 | |
| 2 | --> $DIR/super-traits-fail-2.rs:14:32 | |
| 3 | 3 | | |
| 4 | LL | trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 4 | LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | LL | trait Bar: [const] Foo {} | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 10 | LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 12 | 12 | |
| 13 | 13 | error[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 | |
| 15 | 15 | | |
| 16 | 16 | LL | x.a(); |
| 17 | 17 | | ^ |
tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | x.a(); |
| 5 | 5 | | ^ |
tests/ui/traits/const-traits/super-traits-fail-3.nnn.stderr+71-42| ... | ... | @@ -1,27 +1,57 @@ |
| 1 | 1 | error: `[const]` is not allowed here |
| 2 | --> $DIR/super-traits-fail-3.rs:23:12 | |
| 2 | --> $DIR/super-traits-fail-3.rs:27:44 | |
| 3 | 3 | | |
| 4 | LL | trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 4 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | LL | trait Bar: [const] Foo {} | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 10 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 12 | 12 | |
| 13 | 13 | error[E0658]: const trait impls are experimental |
| 14 | --> $DIR/super-traits-fail-3.rs:23:12 | |
| 14 | --> $DIR/super-traits-fail-3.rs:15:33 | |
| 15 | 15 | | |
| 16 | LL | trait Bar: [const] Foo {} | |
| 17 | | ^^^^^^^ | |
| 16 | LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); } | |
| 17 | | ^^^^^ | |
| 18 | 18 | | |
| 19 | 19 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 20 | 20 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 21 | 21 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 22 | 22 | |
| 23 | 23 | error[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 | | | |
| 26 | LL | #[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 | ||
| 33 | error[E0658]: const trait impls are experimental | |
| 34 | --> $DIR/super-traits-fail-3.rs:19:50 | |
| 35 | | | |
| 36 | LL | #[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 | ||
| 43 | error[E0658]: const trait impls are experimental | |
| 44 | --> $DIR/super-traits-fail-3.rs:27:44 | |
| 45 | | | |
| 46 | LL | #[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 | ||
| 53 | error[E0658]: const trait impls are experimental | |
| 54 | --> $DIR/super-traits-fail-3.rs:34:17 | |
| 25 | 55 | | |
| 26 | 56 | LL | const fn foo<T: [const] Bar>(x: &T) { |
| 27 | 57 | | ^^^^^^^ |
| ... | ... | @@ -31,53 +61,53 @@ LL | const fn foo<T: [const] Bar>(x: &T) { |
| 31 | 61 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 32 | 62 | |
| 33 | 63 | error: `[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 | |
| 35 | 65 | | |
| 36 | LL | trait Bar: [const] Foo {} | |
| 37 | | ^^^^^^^ can't be applied to `Foo` | |
| 66 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 67 | | ^^^^^^^ can't be applied to `Foo` | |
| 38 | 68 | | |
| 39 | 69 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations |
| 40 | 70 | | |
| 41 | LL | #[const_trait] trait Foo { | |
| 42 | | ++++++++++++++ | |
| 71 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 72 | | +++++ | |
| 43 | 73 | |
| 44 | 74 | error: `[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 | |
| 46 | 76 | | |
| 47 | LL | trait Bar: [const] Foo {} | |
| 48 | | ^^^^^^^ can't be applied to `Foo` | |
| 77 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 78 | | ^^^^^^^ can't be applied to `Foo` | |
| 49 | 79 | | |
| 50 | 80 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 51 | 81 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations |
| 52 | 82 | | |
| 53 | LL | #[const_trait] trait Foo { | |
| 54 | | ++++++++++++++ | |
| 83 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 84 | | +++++ | |
| 55 | 85 | |
| 56 | 86 | error: `[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 | |
| 58 | 88 | | |
| 59 | LL | trait Bar: [const] Foo {} | |
| 60 | | ^^^^^^^ can't be applied to `Foo` | |
| 89 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 90 | | ^^^^^^^ can't be applied to `Foo` | |
| 61 | 91 | | |
| 62 | 92 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 63 | 93 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations |
| 64 | 94 | | |
| 65 | LL | #[const_trait] trait Foo { | |
| 66 | | ++++++++++++++ | |
| 95 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 96 | | +++++ | |
| 67 | 97 | |
| 68 | 98 | error: `[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 | |
| 70 | 100 | | |
| 71 | 101 | LL | const fn foo<T: [const] Bar>(x: &T) { |
| 72 | 102 | | ^^^^^^^ can't be applied to `Bar` |
| 73 | 103 | | |
| 74 | 104 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations |
| 75 | 105 | | |
| 76 | LL | #[const_trait] trait Bar: [const] Foo {} | |
| 77 | | ++++++++++++++ | |
| 106 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} | |
| 107 | | +++++ | |
| 78 | 108 | |
| 79 | 109 | error: `[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 | |
| 81 | 111 | | |
| 82 | 112 | LL | const fn foo<T: [const] Bar>(x: &T) { |
| 83 | 113 | | ^^^^^^^ can't be applied to `Bar` |
| ... | ... | @@ -85,31 +115,30 @@ LL | const fn foo<T: [const] Bar>(x: &T) { |
| 85 | 115 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 86 | 116 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations |
| 87 | 117 | | |
| 88 | LL | #[const_trait] trait Bar: [const] Foo {} | |
| 89 | | ++++++++++++++ | |
| 118 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} | |
| 119 | | +++++ | |
| 90 | 120 | |
| 91 | 121 | error[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 | |
| 93 | 123 | | |
| 94 | 124 | LL | x.a(); |
| 95 | 125 | | ^^^ |
| 96 | 126 | | |
| 97 | 127 | note: 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 | |
| 99 | 129 | | |
| 100 | LL | trait Foo { | |
| 101 | | ^^^^^^^^^ this trait is not const | |
| 102 | LL | fn a(&self); | |
| 103 | | ------------ this method is not const | |
| 104 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]` | |
| 130 | LL | #[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 | |
| 105 | 135 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants |
| 106 | 136 | help: consider making trait `Foo` const |
| 107 | 137 | | |
| 108 | LL + #[const_trait] | |
| 109 | LL | trait Foo { | |
| 110 | | | |
| 138 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 139 | | +++++ | |
| 111 | 140 | |
| 112 | error: aborting due to 9 previous errors | |
| 141 | error: aborting due to 12 previous errors | |
| 113 | 142 | |
| 114 | 143 | Some errors have detailed explanations: E0015, E0658. |
| 115 | 144 | For 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 @@ |
| 1 | error: `[const]` is not allowed here | |
| 2 | --> $DIR/super-traits-fail-3.rs:23:12 | |
| 1 | error[E0658]: const trait impls are experimental | |
| 2 | --> $DIR/super-traits-fail-3.rs:15:33 | |
| 3 | | | |
| 4 | LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); } | |
| 5 | | ^^^^^ | |
| 3 | 6 | | |
| 4 | LL | 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 | ||
| 11 | error[E0658]: const trait impls are experimental | |
| 12 | --> $DIR/super-traits-fail-3.rs:19:33 | |
| 6 | 13 | | |
| 7 | note: this trait is not `const`, so it cannot have `[const]` trait bounds | |
| 8 | --> $DIR/super-traits-fail-3.rs:23:1 | |
| 14 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 15 | | ^^^^^ | |
| 9 | 16 | | |
| 10 | LL | 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 | |
| 12 | 20 | |
| 13 | 21 | error[E0658]: const trait impls are experimental |
| 14 | --> $DIR/super-traits-fail-3.rs:23:12 | |
| 22 | --> $DIR/super-traits-fail-3.rs:19:50 | |
| 15 | 23 | | |
| 16 | LL | trait Bar: [const] Foo {} | |
| 17 | | ^^^^^^^ | |
| 24 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 25 | | ^^^^^^^ | |
| 18 | 26 | | |
| 19 | 27 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 20 | 28 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 21 | 29 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 22 | 30 | |
| 23 | 31 | error[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 | | | |
| 34 | LL | #[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 | ||
| 41 | error[E0658]: const trait impls are experimental | |
| 42 | --> $DIR/super-traits-fail-3.rs:34:17 | |
| 25 | 43 | | |
| 26 | 44 | LL | const fn foo<T: [const] Bar>(x: &T) { |
| 27 | 45 | | ^^^^^^^ |
| ... | ... | @@ -31,85 +49,85 @@ LL | const fn foo<T: [const] Bar>(x: &T) { |
| 31 | 49 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 32 | 50 | |
| 33 | 51 | error: `[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 | |
| 35 | 53 | | |
| 36 | LL | trait Bar: [const] Foo {} | |
| 37 | | ^^^^^^^ can't be applied to `Foo` | |
| 54 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 55 | | ^^^^^^^ can't be applied to `Foo` | |
| 38 | 56 | | |
| 39 | 57 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations |
| 40 | 58 | | |
| 41 | LL | #[const_trait] trait Foo { | |
| 42 | | ++++++++++++++ | |
| 59 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 60 | | +++++ | |
| 43 | 61 | |
| 44 | 62 | error: `[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 | |
| 46 | 64 | | |
| 47 | LL | trait Bar: [const] Foo {} | |
| 48 | | ^^^^^^^ can't be applied to `Foo` | |
| 65 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 66 | | ^^^^^^^ can't be applied to `Foo` | |
| 49 | 67 | | |
| 50 | 68 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 51 | 69 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations |
| 52 | 70 | | |
| 53 | LL | #[const_trait] trait Foo { | |
| 54 | | ++++++++++++++ | |
| 71 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 72 | | +++++ | |
| 55 | 73 | |
| 56 | 74 | error: `[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 | |
| 58 | 76 | | |
| 59 | LL | trait Bar: [const] Foo {} | |
| 60 | | ^^^^^^^ can't be applied to `Foo` | |
| 77 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 78 | | ^^^^^^^ can't be applied to `Foo` | |
| 61 | 79 | | |
| 62 | 80 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 63 | 81 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations |
| 64 | 82 | | |
| 65 | LL | #[const_trait] trait Foo { | |
| 66 | | ++++++++++++++ | |
| 83 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 84 | | +++++ | |
| 67 | 85 | |
| 68 | 86 | error: `[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 | |
| 70 | 88 | | |
| 71 | LL | const fn foo<T: [const] Bar>(x: &T) { | |
| 72 | | ^^^^^^^ can't be applied to `Bar` | |
| 89 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 90 | | ^^^^^^^ can't be applied to `Foo` | |
| 73 | 91 | | |
| 74 | help: 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` | |
| 93 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | |
| 75 | 94 | | |
| 76 | LL | #[const_trait] trait Bar: [const] Foo {} | |
| 77 | | ++++++++++++++ | |
| 95 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 96 | | +++++ | |
| 78 | 97 | |
| 79 | 98 | error: `[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 | |
| 81 | 100 | | |
| 82 | LL | const fn foo<T: [const] Bar>(x: &T) { | |
| 83 | | ^^^^^^^ can't be applied to `Bar` | |
| 101 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 102 | | ^^^^^^^ can't be applied to `Foo` | |
| 84 | 103 | | |
| 85 | 104 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 86 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations | |
| 105 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | |
| 87 | 106 | | |
| 88 | LL | #[const_trait] trait Bar: [const] Foo {} | |
| 89 | | ++++++++++++++ | |
| 107 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 108 | | +++++ | |
| 90 | 109 | |
| 91 | 110 | error[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 | |
| 93 | 112 | | |
| 94 | 113 | LL | x.a(); |
| 95 | 114 | | ^^^ |
| 96 | 115 | | |
| 97 | 116 | note: 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 | |
| 99 | 118 | | |
| 100 | LL | trait Foo { | |
| 101 | | ^^^^^^^^^ this trait is not const | |
| 102 | LL | fn a(&self); | |
| 103 | | ------------ this method is not const | |
| 104 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]` | |
| 119 | LL | #[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 | |
| 105 | 124 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants |
| 106 | 125 | help: consider making trait `Foo` const |
| 107 | 126 | | |
| 108 | LL + #[const_trait] | |
| 109 | LL | trait Foo { | |
| 110 | | | |
| 127 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 128 | | +++++ | |
| 111 | 129 | |
| 112 | error: aborting due to 9 previous errors | |
| 130 | error: aborting due to 11 previous errors | |
| 113 | 131 | |
| 114 | 132 | Some errors have detailed explanations: E0015, E0658. |
| 115 | 133 | For 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 @@ |
| 1 | error: `[const]` is not allowed here | |
| 2 | --> $DIR/super-traits-fail-3.rs:27:44 | |
| 3 | | | |
| 4 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 6 | | | |
| 7 | note: this trait is not `const`, so it cannot have `[const]` trait bounds | |
| 8 | --> $DIR/super-traits-fail-3.rs:27:33 | |
| 9 | | | |
| 10 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 12 | ||
| 1 | 13 | error[E0658]: const trait impls are experimental |
| 2 | --> $DIR/super-traits-fail-3.rs:23:12 | |
| 14 | --> $DIR/super-traits-fail-3.rs:15:33 | |
| 3 | 15 | | |
| 4 | LL | trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 16 | LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); } | |
| 17 | | ^^^^^ | |
| 6 | 18 | | |
| 7 | 19 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 8 | 20 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 9 | 21 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 10 | 22 | |
| 11 | 23 | error[E0658]: const trait impls are experimental |
| 12 | --> $DIR/super-traits-fail-3.rs:32:17 | |
| 24 | --> $DIR/super-traits-fail-3.rs:19:33 | |
| 13 | 25 | | |
| 14 | LL | const fn foo<T: [const] Bar>(x: &T) { | |
| 15 | | ^^^^^^^ | |
| 26 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 27 | | ^^^^^ | |
| 16 | 28 | | |
| 17 | 29 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 18 | 30 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 19 | 31 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 20 | 32 | |
| 21 | error[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 | |
| 33 | error[E0658]: const trait impls are experimental | |
| 34 | --> $DIR/super-traits-fail-3.rs:19:50 | |
| 23 | 35 | | |
| 24 | LL | #[cfg_attr(any(yyy, yyn, nyy, nyn), const_trait)] | |
| 25 | | ^^^^^^^^^^^ | |
| 36 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 37 | | ^^^^^^^ | |
| 26 | 38 | | |
| 27 | 39 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 28 | 40 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 29 | 41 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 30 | 42 | |
| 31 | error[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 | |
| 43 | error[E0658]: const trait impls are experimental | |
| 44 | --> $DIR/super-traits-fail-3.rs:27:44 | |
| 33 | 45 | | |
| 34 | LL | #[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)] | |
| 35 | | ^^^^^^^^^^^ | |
| 46 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 47 | | ^^^^^^^ | |
| 36 | 48 | | |
| 37 | 49 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 38 | 50 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 39 | 51 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 40 | 52 | |
| 41 | error[E0658]: cannot call conditionally-const method `<T as Foo>::a` in constant functions | |
| 42 | --> $DIR/super-traits-fail-3.rs:36:7 | |
| 53 | error[E0658]: const trait impls are experimental | |
| 54 | --> $DIR/super-traits-fail-3.rs:34:17 | |
| 43 | 55 | | |
| 44 | LL | x.a(); | |
| 45 | | ^^^ | |
| 56 | LL | const fn foo<T: [const] Bar>(x: &T) { | |
| 57 | | ^^^^^^^ | |
| 46 | 58 | | |
| 47 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants | |
| 48 | 59 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 49 | 60 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 50 | 61 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 51 | 62 | |
| 52 | error: aborting due to 5 previous errors | |
| 63 | error: `[const]` can only be applied to `const` traits | |
| 64 | --> $DIR/super-traits-fail-3.rs:34:17 | |
| 65 | | | |
| 66 | LL | const fn foo<T: [const] Bar>(x: &T) { | |
| 67 | | ^^^^^^^ can't be applied to `Bar` | |
| 68 | | | |
| 69 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations | |
| 70 | | | |
| 71 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} | |
| 72 | | +++++ | |
| 73 | ||
| 74 | error: `[const]` can only be applied to `const` traits | |
| 75 | --> $DIR/super-traits-fail-3.rs:34:17 | |
| 76 | | | |
| 77 | LL | 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` | |
| 81 | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations | |
| 82 | | | |
| 83 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} | |
| 84 | | +++++ | |
| 85 | ||
| 86 | error[E0015]: cannot call non-const method `<T as Foo>::a` in constant functions | |
| 87 | --> $DIR/super-traits-fail-3.rs:38:7 | |
| 88 | | | |
| 89 | LL | x.a(); | |
| 90 | | ^^^ | |
| 91 | | | |
| 92 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants | |
| 93 | ||
| 94 | error: aborting due to 9 previous errors | |
| 53 | 95 | |
| 54 | For more information about this error, try `rustc --explain E0658`. | |
| 96 | Some errors have detailed explanations: E0015, E0658. | |
| 97 | For 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 @@ |
| 1 | 1 | error[E0658]: const trait impls are experimental |
| 2 | --> $DIR/super-traits-fail-3.rs:23:12 | |
| 2 | --> $DIR/super-traits-fail-3.rs:15:33 | |
| 3 | 3 | | |
| 4 | LL | trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 4 | LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); } | |
| 5 | | ^^^^^ | |
| 6 | 6 | | |
| 7 | 7 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 8 | 8 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 9 | 9 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 10 | 10 | |
| 11 | 11 | error[E0658]: const trait impls are experimental |
| 12 | --> $DIR/super-traits-fail-3.rs:32:17 | |
| 12 | --> $DIR/super-traits-fail-3.rs:19:33 | |
| 13 | 13 | | |
| 14 | LL | const fn foo<T: [const] Bar>(x: &T) { | |
| 15 | | ^^^^^^^ | |
| 14 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 15 | | ^^^^^ | |
| 16 | 16 | | |
| 17 | 17 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 18 | 18 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 19 | 19 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 20 | 20 | |
| 21 | error[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 | |
| 21 | error[E0658]: const trait impls are experimental | |
| 22 | --> $DIR/super-traits-fail-3.rs:19:50 | |
| 23 | 23 | | |
| 24 | LL | #[cfg_attr(any(yyy, yyn, nyy, nyn), const_trait)] | |
| 25 | | ^^^^^^^^^^^ | |
| 24 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 25 | | ^^^^^^^ | |
| 26 | 26 | | |
| 27 | 27 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 28 | 28 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 29 | 29 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 30 | 30 | |
| 31 | error[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 | |
| 31 | error[E0658]: const trait impls are experimental | |
| 32 | --> $DIR/super-traits-fail-3.rs:27:44 | |
| 33 | 33 | | |
| 34 | LL | #[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)] | |
| 35 | | ^^^^^^^^^^^ | |
| 34 | LL | #[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 | ||
| 41 | error[E0658]: const trait impls are experimental | |
| 42 | --> $DIR/super-traits-fail-3.rs:34:17 | |
| 43 | | | |
| 44 | LL | const fn foo<T: [const] Bar>(x: &T) { | |
| 45 | | ^^^^^^^ | |
| 36 | 46 | | |
| 37 | 47 | = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information |
| 38 | 48 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 39 | 49 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 40 | 50 | |
| 41 | 51 | error[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 | |
| 43 | 53 | | |
| 44 | 54 | LL | x.a(); |
| 45 | 55 | | ^^^ |
| ... | ... | @@ -49,6 +59,6 @@ LL | x.a(); |
| 49 | 59 | = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable |
| 50 | 60 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 51 | 61 | |
| 52 | error: aborting due to 5 previous errors | |
| 62 | error: aborting due to 6 previous errors | |
| 53 | 63 | |
| 54 | 64 | For 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 @@ |
| 12 | 12 | /// nny: feature not enabled, Foo is not const, Bar is const |
| 13 | 13 | /// nnn: feature not enabled, Foo is not const, Bar is not const |
| 14 | 14 | |
| 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 | |
| 17 | trait 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); } | |
| 20 | 18 | |
| 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 | |
| 23 | trait 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 | |
| 31 | 33 | |
| 32 | 34 | const 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 | |
| 35 | 37 | //[nyy,nyn,nny,nnn]~^^^ ERROR: const trait impls are experimental |
| 36 | 38 | x.a(); |
| 37 | 39 | //[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 | |
| 40 | 42 | } |
| 41 | 43 | |
| 42 | 44 | fn main() {} |
tests/ui/traits/const-traits/super-traits-fail-3.ynn.stderr+35-36| ... | ... | @@ -1,63 +1,63 @@ |
| 1 | 1 | error: `[const]` is not allowed here |
| 2 | --> $DIR/super-traits-fail-3.rs:23:12 | |
| 2 | --> $DIR/super-traits-fail-3.rs:27:44 | |
| 3 | 3 | | |
| 4 | LL | trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 4 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | LL | trait Bar: [const] Foo {} | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 10 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 12 | 12 | |
| 13 | 13 | error: `[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 | |
| 15 | 15 | | |
| 16 | LL | trait Bar: [const] Foo {} | |
| 17 | | ^^^^^^^ can't be applied to `Foo` | |
| 16 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 17 | | ^^^^^^^ can't be applied to `Foo` | |
| 18 | 18 | | |
| 19 | 19 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 20 | 20 | | |
| 21 | LL | #[const_trait] trait Foo { | |
| 22 | | ++++++++++++++ | |
| 21 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 22 | | +++++ | |
| 23 | 23 | |
| 24 | 24 | error: `[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 | |
| 26 | 26 | | |
| 27 | LL | trait Bar: [const] Foo {} | |
| 28 | | ^^^^^^^ can't be applied to `Foo` | |
| 27 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 28 | | ^^^^^^^ can't be applied to `Foo` | |
| 29 | 29 | | |
| 30 | 30 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 31 | 31 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 32 | 32 | | |
| 33 | LL | #[const_trait] trait Foo { | |
| 34 | | ++++++++++++++ | |
| 33 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 34 | | +++++ | |
| 35 | 35 | |
| 36 | 36 | error: `[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 | |
| 38 | 38 | | |
| 39 | LL | trait Bar: [const] Foo {} | |
| 40 | | ^^^^^^^ can't be applied to `Foo` | |
| 39 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 40 | | ^^^^^^^ can't be applied to `Foo` | |
| 41 | 41 | | |
| 42 | 42 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 43 | 43 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 44 | 44 | | |
| 45 | LL | #[const_trait] trait Foo { | |
| 46 | | ++++++++++++++ | |
| 45 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 46 | | +++++ | |
| 47 | 47 | |
| 48 | 48 | error: `[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 | |
| 50 | 50 | | |
| 51 | 51 | LL | const fn foo<T: [const] Bar>(x: &T) { |
| 52 | 52 | | ^^^^^^^ can't be applied to `Bar` |
| 53 | 53 | | |
| 54 | 54 | help: mark `Bar` as `const` to allow it to have `const` implementations |
| 55 | 55 | | |
| 56 | LL | #[const_trait] trait Bar: [const] Foo {} | |
| 57 | | ++++++++++++++ | |
| 56 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} | |
| 57 | | +++++ | |
| 58 | 58 | |
| 59 | 59 | error: `[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 | |
| 61 | 61 | | |
| 62 | 62 | LL | const fn foo<T: [const] Bar>(x: &T) { |
| 63 | 63 | | ^^^^^^^ can't be applied to `Bar` |
| ... | ... | @@ -65,28 +65,27 @@ LL | const fn foo<T: [const] Bar>(x: &T) { |
| 65 | 65 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 66 | 66 | help: mark `Bar` as `const` to allow it to have `const` implementations |
| 67 | 67 | | |
| 68 | LL | #[const_trait] trait Bar: [const] Foo {} | |
| 69 | | ++++++++++++++ | |
| 68 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} | |
| 69 | | +++++ | |
| 70 | 70 | |
| 71 | 71 | error[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 | |
| 73 | 73 | | |
| 74 | 74 | LL | x.a(); |
| 75 | 75 | | ^^^ |
| 76 | 76 | | |
| 77 | 77 | note: 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 | |
| 79 | 79 | | |
| 80 | LL | trait Foo { | |
| 81 | | ^^^^^^^^^ this trait is not const | |
| 82 | LL | fn a(&self); | |
| 83 | | ------------ this method is not const | |
| 80 | LL | #[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); } | |
| 81 | | ^^^^^^^^^ ------------ this method is not const | |
| 82 | | | | |
| 83 | | this trait is not const | |
| 84 | 84 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants |
| 85 | 85 | help: consider making trait `Foo` const |
| 86 | 86 | | |
| 87 | LL + #[const_trait] | |
| 88 | LL | trait Foo { | |
| 89 | | | |
| 87 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 88 | | +++++ | |
| 90 | 89 | |
| 91 | 90 | error: aborting due to 7 previous errors |
| 92 | 91 |
tests/ui/traits/const-traits/super-traits-fail-3.yny.stderr+33-34| ... | ... | @@ -1,81 +1,80 @@ |
| 1 | 1 | error: `[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 | |
| 3 | 3 | | |
| 4 | LL | trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ can't be applied to `Foo` | |
| 4 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ can't be applied to `Foo` | |
| 6 | 6 | | |
| 7 | 7 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 8 | 8 | | |
| 9 | LL | #[const_trait] trait Foo { | |
| 10 | | ++++++++++++++ | |
| 9 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 10 | | +++++ | |
| 11 | 11 | |
| 12 | 12 | error: `[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 | |
| 14 | 14 | | |
| 15 | LL | trait Bar: [const] Foo {} | |
| 16 | | ^^^^^^^ can't be applied to `Foo` | |
| 15 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 16 | | ^^^^^^^ can't be applied to `Foo` | |
| 17 | 17 | | |
| 18 | 18 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 19 | 19 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 20 | 20 | | |
| 21 | LL | #[const_trait] trait Foo { | |
| 22 | | ++++++++++++++ | |
| 21 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 22 | | +++++ | |
| 23 | 23 | |
| 24 | 24 | error: `[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 | |
| 26 | 26 | | |
| 27 | LL | trait Bar: [const] Foo {} | |
| 28 | | ^^^^^^^ can't be applied to `Foo` | |
| 27 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 28 | | ^^^^^^^ can't be applied to `Foo` | |
| 29 | 29 | | |
| 30 | 30 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 31 | 31 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 32 | 32 | | |
| 33 | LL | #[const_trait] trait Foo { | |
| 34 | | ++++++++++++++ | |
| 33 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 34 | | +++++ | |
| 35 | 35 | |
| 36 | 36 | error: `[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 | |
| 38 | 38 | | |
| 39 | LL | trait Bar: [const] Foo {} | |
| 40 | | ^^^^^^^ can't be applied to `Foo` | |
| 39 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 40 | | ^^^^^^^ can't be applied to `Foo` | |
| 41 | 41 | | |
| 42 | 42 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 43 | 43 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 44 | 44 | | |
| 45 | LL | #[const_trait] trait Foo { | |
| 46 | | ++++++++++++++ | |
| 45 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 46 | | +++++ | |
| 47 | 47 | |
| 48 | 48 | error: `[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 | |
| 50 | 50 | | |
| 51 | LL | trait Bar: [const] Foo {} | |
| 52 | | ^^^^^^^ can't be applied to `Foo` | |
| 51 | LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} | |
| 52 | | ^^^^^^^ can't be applied to `Foo` | |
| 53 | 53 | | |
| 54 | 54 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 55 | 55 | help: mark `Foo` as `const` to allow it to have `const` implementations |
| 56 | 56 | | |
| 57 | LL | #[const_trait] trait Foo { | |
| 58 | | ++++++++++++++ | |
| 57 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 58 | | +++++ | |
| 59 | 59 | |
| 60 | 60 | error[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 | |
| 62 | 62 | | |
| 63 | 63 | LL | x.a(); |
| 64 | 64 | | ^^^ |
| 65 | 65 | | |
| 66 | 66 | note: 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 | |
| 68 | 68 | | |
| 69 | LL | trait Foo { | |
| 70 | | ^^^^^^^^^ this trait is not const | |
| 71 | LL | fn a(&self); | |
| 72 | | ------------ this method is not const | |
| 69 | LL | #[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); } | |
| 70 | | ^^^^^^^^^ ------------ this method is not const | |
| 71 | | | | |
| 72 | | this trait is not const | |
| 73 | 73 | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants |
| 74 | 74 | help: consider making trait `Foo` const |
| 75 | 75 | | |
| 76 | LL + #[const_trait] | |
| 77 | LL | trait Foo { | |
| 78 | | | |
| 76 | LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } | |
| 77 | | +++++ | |
| 79 | 78 | |
| 80 | 79 | error: aborting due to 6 previous errors |
| 81 | 80 |
tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr+13-13| ... | ... | @@ -1,28 +1,28 @@ |
| 1 | 1 | error: `[const]` is not allowed here |
| 2 | --> $DIR/super-traits-fail-3.rs:23:12 | |
| 2 | --> $DIR/super-traits-fail-3.rs:27:44 | |
| 3 | 3 | | |
| 4 | LL | trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 4 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 5 | | ^^^^^^^ | |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | LL | trait Bar: [const] Foo {} | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 10 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} | |
| 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 12 | 12 | |
| 13 | 13 | error: `[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 | |
| 15 | 15 | | |
| 16 | 16 | LL | const fn foo<T: [const] Bar>(x: &T) { |
| 17 | 17 | | ^^^^^^^ can't be applied to `Bar` |
| 18 | 18 | | |
| 19 | 19 | help: mark `Bar` as `const` to allow it to have `const` implementations |
| 20 | 20 | | |
| 21 | LL | #[const_trait] trait Bar: [const] Foo {} | |
| 22 | | ++++++++++++++ | |
| 21 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} | |
| 22 | | +++++ | |
| 23 | 23 | |
| 24 | 24 | error: `[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 | |
| 26 | 26 | | |
| 27 | 27 | LL | const fn foo<T: [const] Bar>(x: &T) { |
| 28 | 28 | | ^^^^^^^ can't be applied to `Bar` |
| ... | ... | @@ -30,11 +30,11 @@ LL | const fn foo<T: [const] Bar>(x: &T) { |
| 30 | 30 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 31 | 31 | help: mark `Bar` as `const` to allow it to have `const` implementations |
| 32 | 32 | | |
| 33 | LL | #[const_trait] trait Bar: [const] Foo {} | |
| 34 | | ++++++++++++++ | |
| 33 | LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} | |
| 34 | | +++++ | |
| 35 | 35 | |
| 36 | 36 | error[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 | |
| 38 | 38 | | |
| 39 | 39 | LL | x.a(); |
| 40 | 40 | | ^ |
tests/ui/traits/const-traits/super-traits-fail.rs+2-4| ... | ... | @@ -2,12 +2,10 @@ |
| 2 | 2 | |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Foo { | |
| 5 | const trait Foo { | |
| 7 | 6 | fn a(&self); |
| 8 | 7 | } |
| 9 | #[const_trait] | |
| 10 | trait Bar: [const] Foo {} | |
| 8 | const trait Bar: [const] Foo {} | |
| 11 | 9 | |
| 12 | 10 | struct S; |
| 13 | 11 | impl Foo for S { |
tests/ui/traits/const-traits/super-traits-fail.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | impl const Bar for S {} |
| 5 | 5 | | ^ |
tests/ui/traits/const-traits/super-traits.rs+2-4| ... | ... | @@ -2,13 +2,11 @@ |
| 2 | 2 | //@ compile-flags: -Znext-solver |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Foo { | |
| 5 | const trait Foo { | |
| 7 | 6 | fn a(&self); |
| 8 | 7 | } |
| 9 | 8 | |
| 10 | #[const_trait] | |
| 11 | trait Bar: [const] Foo {} | |
| 9 | const trait Bar: [const] Foo {} | |
| 12 | 10 | |
| 13 | 11 | struct S; |
| 14 | 12 | impl const Foo for S { |
tests/ui/traits/const-traits/syntactical-unstable.rs+1-2| ... | ... | @@ -9,8 +9,7 @@ use std::ops::Deref; |
| 9 | 9 | extern crate staged_api; |
| 10 | 10 | use staged_api::MyTrait; |
| 11 | 11 | |
| 12 | #[const_trait] | |
| 13 | trait Foo: [const] MyTrait { | |
| 12 | const trait Foo: [const] MyTrait { | |
| 14 | 13 | //~^ ERROR use of unstable const library feature `unstable` |
| 15 | 14 | type Item: [const] MyTrait; |
| 16 | 15 | //~^ ERROR use of unstable const library feature `unstable` |
tests/ui/traits/const-traits/syntactical-unstable.stderr+10-10| ... | ... | @@ -1,16 +1,16 @@ |
| 1 | 1 | error[E0658]: use of unstable const library feature `unstable` |
| 2 | --> $DIR/syntactical-unstable.rs:13:20 | |
| 2 | --> $DIR/syntactical-unstable.rs:12:26 | |
| 3 | 3 | | |
| 4 | LL | trait Foo: [const] MyTrait { | |
| 5 | | ------- ^^^^^^^ | |
| 6 | | | | |
| 7 | | trait is not stable as const yet | |
| 4 | LL | const trait Foo: [const] MyTrait { | |
| 5 | | ------- ^^^^^^^ | |
| 6 | | | | |
| 7 | | trait is not stable as const yet | |
| 8 | 8 | | |
| 9 | 9 | = help: add `#![feature(unstable)]` to the crate attributes to enable |
| 10 | 10 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 11 | 11 | |
| 12 | 12 | error[E0658]: use of unstable const library feature `unstable` |
| 13 | --> $DIR/syntactical-unstable.rs:19:45 | |
| 13 | --> $DIR/syntactical-unstable.rs:18:45 | |
| 14 | 14 | | |
| 15 | 15 | LL | const fn where_clause<T>() where T: [const] MyTrait {} |
| 16 | 16 | | ------- ^^^^^^^ |
| ... | ... | @@ -21,7 +21,7 @@ LL | const fn where_clause<T>() where T: [const] MyTrait {} |
| 21 | 21 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 22 | 22 | |
| 23 | 23 | error[E0658]: use of unstable const library feature `unstable` |
| 24 | --> $DIR/syntactical-unstable.rs:22:53 | |
| 24 | --> $DIR/syntactical-unstable.rs:21:53 | |
| 25 | 25 | | |
| 26 | 26 | LL | const fn nested<T>() where T: Deref<Target: [const] MyTrait> {} |
| 27 | 27 | | ------- ^^^^^^^ |
| ... | ... | @@ -32,7 +32,7 @@ LL | const fn nested<T>() where T: Deref<Target: [const] MyTrait> {} |
| 32 | 32 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 33 | 33 | |
| 34 | 34 | error[E0658]: use of unstable const library feature `unstable` |
| 35 | --> $DIR/syntactical-unstable.rs:25:33 | |
| 35 | --> $DIR/syntactical-unstable.rs:24:33 | |
| 36 | 36 | | |
| 37 | 37 | LL | const fn rpit() -> impl [const] MyTrait { Local } |
| 38 | 38 | | ------- ^^^^^^^ |
| ... | ... | @@ -43,7 +43,7 @@ LL | const fn rpit() -> impl [const] MyTrait { Local } |
| 43 | 43 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 44 | 44 | |
| 45 | 45 | error[E0658]: use of unstable const library feature `unstable` |
| 46 | --> $DIR/syntactical-unstable.rs:29:12 | |
| 46 | --> $DIR/syntactical-unstable.rs:28:12 | |
| 47 | 47 | | |
| 48 | 48 | LL | impl const MyTrait for Local { |
| 49 | 49 | | ^^^^^^^ trait is not stable as const yet |
| ... | ... | @@ -52,7 +52,7 @@ LL | impl const MyTrait for Local { |
| 52 | 52 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 53 | 53 | |
| 54 | 54 | error[E0658]: use of unstable const library feature `unstable` |
| 55 | --> $DIR/syntactical-unstable.rs:15:24 | |
| 55 | --> $DIR/syntactical-unstable.rs:14:24 | |
| 56 | 56 | | |
| 57 | 57 | LL | type Item: [const] MyTrait; |
| 58 | 58 | | ------- ^^^^^^^ |
tests/ui/traits/const-traits/trait-default-body-stability.rs+1-2| ... | ... | @@ -39,8 +39,7 @@ impl const FromResidual for T { |
| 39 | 39 | |
| 40 | 40 | #[stable(feature = "foo", since = "1.0")] |
| 41 | 41 | #[rustc_const_unstable(feature = "const_tr", issue = "none")] |
| 42 | #[const_trait] | |
| 43 | pub trait Tr { | |
| 42 | pub const trait Tr { | |
| 44 | 43 | #[stable(feature = "foo", since = "1.0")] |
| 45 | 44 | fn bar() -> T { |
| 46 | 45 | T? |
tests/ui/traits/const-traits/trait-fn-const.rs+1-2| ... | ... | @@ -1,8 +1,7 @@ |
| 1 | 1 | // Regression test for issue #113378. |
| 2 | 2 | #![feature(const_trait_impl)] |
| 3 | 3 | |
| 4 | #[const_trait] | |
| 5 | trait Trait { | |
| 4 | const trait Trait { | |
| 6 | 5 | const fn fun(); //~ ERROR functions in traits cannot be declared const |
| 7 | 6 | } |
| 8 | 7 |
tests/ui/traits/const-traits/trait-fn-const.stderr+9-11| ... | ... | @@ -1,9 +1,8 @@ |
| 1 | 1 | error[E0379]: functions in traits cannot be declared const |
| 2 | --> $DIR/trait-fn-const.rs:6:5 | |
| 2 | --> $DIR/trait-fn-const.rs:5:5 | |
| 3 | 3 | | |
| 4 | LL | #[const_trait] | |
| 5 | | -------------- this declares all associated functions implicitly const | |
| 6 | LL | trait Trait { | |
| 4 | LL | const trait Trait { | |
| 5 | | ----- this declares all associated functions implicitly const | |
| 7 | 6 | LL | const fn fun(); |
| 8 | 7 | | ^^^^^- |
| 9 | 8 | | | |
| ... | ... | @@ -11,7 +10,7 @@ LL | const fn fun(); |
| 11 | 10 | | help: remove the `const` |
| 12 | 11 | |
| 13 | 12 | error[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 | |
| 15 | 14 | | |
| 16 | 15 | LL | impl const Trait for () { |
| 17 | 16 | | ----- this declares all associated functions implicitly const |
| ... | ... | @@ -22,7 +21,7 @@ LL | const fn fun() {} |
| 22 | 21 | | help: remove the `const` |
| 23 | 22 | |
| 24 | 23 | error[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 | |
| 26 | 25 | | |
| 27 | 26 | LL | const fn fun() {} |
| 28 | 27 | | ^^^^^ functions in trait impls cannot be const |
| ... | ... | @@ -38,7 +37,7 @@ LL | impl const Trait for u32 { |
| 38 | 37 | | +++++ |
| 39 | 38 | |
| 40 | 39 | error[E0379]: functions in traits cannot be declared const |
| 41 | --> $DIR/trait-fn-const.rs:18:5 | |
| 40 | --> $DIR/trait-fn-const.rs:17:5 | |
| 42 | 41 | | |
| 43 | 42 | LL | const fn fun(); |
| 44 | 43 | | ^^^^^ functions in traits cannot be const |
| ... | ... | @@ -48,11 +47,10 @@ help: remove the `const` ... |
| 48 | 47 | LL - const fn fun(); |
| 49 | 48 | LL + fn fun(); |
| 50 | 49 | | |
| 51 | help: ... and declare the trait to be a `#[const_trait]` instead | |
| 52 | | | |
| 53 | LL + #[const_trait] | |
| 54 | LL | trait NonConst { | |
| 50 | help: ... and declare the trait to be const instead | |
| 55 | 51 | | |
| 52 | LL | const trait NonConst { | |
| 53 | | +++++ | |
| 56 | 54 | |
| 57 | 55 | error: aborting due to 4 previous errors |
| 58 | 56 |
tests/ui/traits/const-traits/trait-where-clause-const.rs+2-4| ... | ... | @@ -6,11 +6,9 @@ |
| 6 | 6 | |
| 7 | 7 | #![feature(const_trait_impl)] |
| 8 | 8 | |
| 9 | #[const_trait] | |
| 10 | trait Bar {} | |
| 9 | const trait Bar {} | |
| 11 | 10 | |
| 12 | #[const_trait] | |
| 13 | trait Foo { | |
| 11 | const trait Foo { | |
| 14 | 12 | fn a(); |
| 15 | 13 | fn b() where Self: [const] Bar; |
| 16 | 14 | fn c<T: [const] Bar>(); |
tests/ui/traits/const-traits/trait-where-clause-const.stderr+4-4| ... | ... | @@ -1,23 +1,23 @@ |
| 1 | 1 | error[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 | |
| 3 | 3 | | |
| 4 | 4 | LL | T::b(); |
| 5 | 5 | | ^ |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | 10 | LL | fn b() where Self: [const] Bar; |
| 11 | 11 | | ^^^^^^^^^^^ required by this bound in `Foo::b` |
| 12 | 12 | |
| 13 | 13 | error[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 | |
| 15 | 15 | | |
| 16 | 16 | LL | T::c::<T>(); |
| 17 | 17 | | ^ |
| 18 | 18 | | |
| 19 | 19 | note: 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 | |
| 21 | 21 | | |
| 22 | 22 | LL | fn c<T: [const] Bar>(); |
| 23 | 23 | | ^^^^^^^^^^^ required by this bound in `Foo::c` |
tests/ui/traits/const-traits/trait-where-clause-run.rs+2-4| ... | ... | @@ -3,13 +3,11 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Bar { | |
| 6 | const trait Bar { | |
| 8 | 7 | fn bar() -> u8; |
| 9 | 8 | } |
| 10 | 9 | |
| 11 | #[const_trait] | |
| 12 | trait Foo { | |
| 10 | const trait Foo { | |
| 13 | 11 | fn foo() -> u8 where Self: [const] Bar { |
| 14 | 12 | <Self as Bar>::bar() * 6 |
| 15 | 13 | } |
tests/ui/traits/const-traits/trait-where-clause-self-referential.rs+1-2| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | //@ compile-flags: -Znext-solver |
| 3 | 3 | #![feature(const_trait_impl)] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Foo { | |
| 5 | const trait Foo { | |
| 7 | 6 | fn bar() where Self: [const] Foo; |
| 8 | 7 | } |
| 9 | 8 |
tests/ui/traits/const-traits/trait-where-clause.rs+1-2| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | #![feature(const_trait_impl)] |
| 2 | 2 | |
| 3 | #[const_trait] | |
| 4 | trait Bar {} | |
| 3 | const trait Bar {} | |
| 5 | 4 | |
| 6 | 5 | trait Foo { |
| 7 | 6 | fn a(); |
tests/ui/traits/const-traits/trait-where-clause.stderr+8-8| ... | ... | @@ -1,35 +1,35 @@ |
| 1 | 1 | error: `[const]` is not allowed here |
| 2 | --> $DIR/trait-where-clause.rs:8:24 | |
| 2 | --> $DIR/trait-where-clause.rs:7:24 | |
| 3 | 3 | | |
| 4 | 4 | LL | fn b() where Self: [const] Bar; |
| 5 | 5 | | ^^^^^^^ |
| 6 | 6 | | |
| 7 | 7 | note: 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 | |
| 9 | 9 | | |
| 10 | 10 | LL | fn b() where Self: [const] Bar; |
| 11 | 11 | | ^ |
| 12 | 12 | |
| 13 | 13 | error: `[const]` is not allowed here |
| 14 | --> $DIR/trait-where-clause.rs:10:13 | |
| 14 | --> $DIR/trait-where-clause.rs:9:13 | |
| 15 | 15 | | |
| 16 | 16 | LL | fn c<T: [const] Bar>(); |
| 17 | 17 | | ^^^^^^^ |
| 18 | 18 | | |
| 19 | 19 | note: 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 | |
| 21 | 21 | | |
| 22 | 22 | LL | fn c<T: [const] Bar>(); |
| 23 | 23 | | ^ |
| 24 | 24 | |
| 25 | 25 | error[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 | |
| 27 | 27 | | |
| 28 | 28 | LL | T::b(); |
| 29 | 29 | | ^ the trait `Bar` is not implemented for `T` |
| 30 | 30 | | |
| 31 | 31 | note: required by a bound in `Foo::b` |
| 32 | --> $DIR/trait-where-clause.rs:8:24 | |
| 32 | --> $DIR/trait-where-clause.rs:7:24 | |
| 33 | 33 | | |
| 34 | 34 | LL | fn b() where Self: [const] Bar; |
| 35 | 35 | | ^^^^^^^^^^^ required by this bound in `Foo::b` |
| ... | ... | @@ -39,13 +39,13 @@ LL | fn test1<T: Foo + Bar>() { |
| 39 | 39 | | +++++ |
| 40 | 40 | |
| 41 | 41 | error[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 | |
| 43 | 43 | | |
| 44 | 44 | LL | T::c::<T>(); |
| 45 | 45 | | ^ the trait `Bar` is not implemented for `T` |
| 46 | 46 | | |
| 47 | 47 | note: required by a bound in `Foo::c` |
| 48 | --> $DIR/trait-where-clause.rs:10:13 | |
| 48 | --> $DIR/trait-where-clause.rs:9:13 | |
| 49 | 49 | | |
| 50 | 50 | LL | fn c<T: [const] Bar>(); |
| 51 | 51 | | ^^^^^^^^^^^ required by this bound in `Foo::c` |
tests/ui/traits/const-traits/unconstrained-var-specialization.rs+1-2| ... | ... | @@ -7,8 +7,7 @@ |
| 7 | 7 | // In the default impl below, `A` is constrained by the projection predicate, and if the host effect |
| 8 | 8 | // predicate for `const Foo` doesn't resolve vars, then specialization will fail. |
| 9 | 9 | |
| 10 | #[const_trait] | |
| 11 | trait Foo {} | |
| 10 | const trait Foo {} | |
| 12 | 11 | |
| 13 | 12 | pub trait Iterator { |
| 14 | 13 | type Item; |
tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs+1-2| ... | ... | @@ -7,8 +7,7 @@ |
| 7 | 7 | |
| 8 | 8 | fn require<T: const Trait>() {} |
| 9 | 9 | |
| 10 | #[const_trait] | |
| 11 | trait Trait { | |
| 10 | const trait Trait { | |
| 12 | 11 | fn make() -> u32; |
| 13 | 12 | } |
| 14 | 13 |
tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr+16-16| ... | ... | @@ -7,88 +7,88 @@ LL | #![feature(const_trait_impl, generic_const_exprs)] |
| 7 | 7 | = help: remove one of these features |
| 8 | 8 | |
| 9 | 9 | error[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 | |
| 11 | 11 | | |
| 12 | 12 | LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} |
| 13 | 13 | | ^^^^^^^^^^^^^ |
| 14 | 14 | | |
| 15 | 15 | note: ...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 | |
| 17 | 17 | | |
| 18 | 18 | LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} |
| 19 | 19 | | ^^^^^^^^^^^^^ |
| 20 | 20 | note: ...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 | |
| 22 | 22 | | |
| 23 | 23 | LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} |
| 24 | 24 | | ^^^^^^^^^^^^^ |
| 25 | 25 | note: ...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 | |
| 27 | 27 | | |
| 28 | 28 | LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} |
| 29 | 29 | | ^^^^^^^^^^^^^ |
| 30 | 30 | note: ...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 | |
| 32 | 32 | | |
| 33 | 33 | LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} |
| 34 | 34 | | ^^^^^^^^^^^^^ |
| 35 | 35 | note: ...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 | |
| 37 | 37 | | |
| 38 | 38 | LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} |
| 39 | 39 | | ^^^^^^^^^^^^^ |
| 40 | 40 | note: ...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 | |
| 42 | 42 | | |
| 43 | 43 | LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} |
| 44 | 44 | | ^^^^^^^^^^^^^ |
| 45 | 45 | = note: ...which again requires evaluating type-level constant, completing the cycle |
| 46 | 46 | note: 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 | |
| 48 | 48 | | |
| 49 | 49 | LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {} |
| 50 | 50 | | ^^^^^^^^^^^^^ |
| 51 | 51 | = 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 |
| 52 | 52 | |
| 53 | 53 | error[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 | |
| 55 | 55 | | |
| 56 | 56 | LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {} |
| 57 | 57 | | ^^^^^^^^^^^^^ |
| 58 | 58 | | |
| 59 | 59 | note: ...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 | |
| 61 | 61 | | |
| 62 | 62 | LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {} |
| 63 | 63 | | ^^^^^^^^^^^^^ |
| 64 | 64 | note: ...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 | |
| 66 | 66 | | |
| 67 | 67 | LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {} |
| 68 | 68 | | ^^^^^^^^^^^^^ |
| 69 | 69 | note: ...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 | |
| 71 | 71 | | |
| 72 | 72 | LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {} |
| 73 | 73 | | ^^^^^^^^^^^^^ |
| 74 | 74 | note: ...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 | |
| 76 | 76 | | |
| 77 | 77 | LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {} |
| 78 | 78 | | ^^^^^^^^^^^^^ |
| 79 | 79 | note: ...which requires evaluating type-level constant... |
| 80 | --> $DIR/unsatisfied-const-trait-bound.rs:33:49 | |
| 80 | --> $DIR/unsatisfied-const-trait-bound.rs:32:49 | |
| 81 | 81 | | |
| 82 | 82 | LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {} |
| 83 | 83 | | ^^^^^^^^^^^^^ |
| 84 | 84 | note: ...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 | |
| 86 | 86 | | |
| 87 | 87 | LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {} |
| 88 | 88 | | ^^^^^^^^^^^^^ |
| 89 | 89 | = note: ...which again requires checking if `accept1::{constant#0}` is a trivial const, completing the cycle |
| 90 | 90 | note: 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 | |
| 92 | 92 | | |
| 93 | 93 | LL | const fn accept1<T: [const] Trait>(_: Container<{ T::make() }>) {} |
| 94 | 94 | | ^^^^^^^^^^^^^ |
tests/ui/traits/const-traits/variance.rs+1-2| ... | ... | @@ -2,8 +2,7 @@ |
| 2 | 2 | #![allow(internal_features)] |
| 3 | 3 | #![rustc_variance_of_opaques] |
| 4 | 4 | |
| 5 | #[const_trait] | |
| 6 | trait Foo {} | |
| 5 | const trait Foo {} | |
| 7 | 6 | |
| 8 | 7 | impl const Foo for () {} |
| 9 | 8 |
tests/ui/traits/const-traits/variance.stderr+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | error: ['a: *] |
| 2 | --> $DIR/variance.rs:10:21 | |
| 2 | --> $DIR/variance.rs:9:21 | |
| 3 | 3 | | |
| 4 | 4 | LL | fn foo<'a: 'a>() -> impl const Foo {} |
| 5 | 5 | | ^^^^^^^^^^^^^^ |
tests/ui/traits/next-solver/canonical/effect-var.rs+1-2| ... | ... | @@ -3,8 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | #![feature(const_trait_impl)] |
| 5 | 5 | |
| 6 | #[const_trait] | |
| 7 | trait Foo { | |
| 6 | const trait Foo { | |
| 8 | 7 | fn foo(); |
| 9 | 8 | } |
| 10 | 9 |
triagebot.toml+1| ... | ... | @@ -1419,6 +1419,7 @@ compiler_leads = [ |
| 1419 | 1419 | ] |
| 1420 | 1420 | compiler = [ |
| 1421 | 1421 | "@BoxyUwU", |
| 1422 | "@chenyukang", | |
| 1422 | 1423 | "@compiler-errors", |
| 1423 | 1424 | "@davidtwco", |
| 1424 | 1425 | "@eholk", |