diff --git a/.mailmap b/.mailmap index c0638de4aeec5..5c765fc547e73 100644 --- a/.mailmap +++ b/.mailmap @@ -139,7 +139,6 @@ Christian Poveda <31802960+christianpoveda@users.noreply.github. Christian Poveda Christian Vallentin Christoffer Buchholz -Christopher Durham Clark Gaebel Clement Miao Clément Renault @@ -148,6 +147,7 @@ Clinton Ryan Taylor Cramer ember arlynx Crazycolorz5 +Crystal Durham csmoe <35686186+csmoe@users.noreply.github.com> Cyryl Płotnicki Damien Schoof diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 5e10c5a77d97d..7d618f16b26e5 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -290,7 +290,7 @@ ast_passes_trait_fn_const = *[false] {""} } .make_impl_const_sugg = ... and declare the impl to be const instead - .make_trait_const_sugg = ... and declare the trait to be a `#[const_trait]` instead + .make_trait_const_sugg = ... and declare the trait to be const instead ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 7a79accc66c2e..c203e5426b1e4 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -48,7 +48,7 @@ enum SelfSemantic { } enum TraitOrTraitImpl { - Trait { span: Span, constness: Const }, + Trait { vis: Span, constness: Const }, TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span }, } @@ -109,10 +109,10 @@ impl<'a> AstValidator<'a> { self.outer_trait_or_trait_impl = old; } - fn with_in_trait(&mut self, span: Span, constness: Const, f: impl FnOnce(&mut Self)) { + fn with_in_trait(&mut self, vis: Span, constness: Const, f: impl FnOnce(&mut Self)) { let old = mem::replace( &mut self.outer_trait_or_trait_impl, - Some(TraitOrTraitImpl::Trait { span, constness }), + Some(TraitOrTraitImpl::Trait { vis, constness }), ); f(self); self.outer_trait_or_trait_impl = old; @@ -265,10 +265,12 @@ impl<'a> AstValidator<'a> { None }; + let map = self.sess.source_map(); + let make_trait_const_sugg = if const_trait_impl - && let TraitOrTraitImpl::Trait { span, constness: ast::Const::No } = parent + && let &TraitOrTraitImpl::Trait { vis, constness: ast::Const::No } = parent { - Some(span.shrink_to_lo()) + Some(map.span_extend_while_whitespace(vis).shrink_to_hi()) } else { None }; @@ -279,7 +281,7 @@ impl<'a> AstValidator<'a> { in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }), const_context_label: parent_constness, remove_const_sugg: ( - self.sess.source_map().span_extend_while_whitespace(span), + map.span_extend_while_whitespace(span), match parent_constness { Some(_) => rustc_errors::Applicability::MachineApplicable, None => rustc_errors::Applicability::MaybeIncorrect, @@ -1165,13 +1167,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .. }) => { self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident); - // FIXME(const_trait_impl) remove this - let alt_const_trait_span = - attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span); - let constness = match (*constness, alt_const_trait_span) { - (Const::Yes(span), _) | (Const::No, Some(span)) => Const::Yes(span), - (Const::No, None) => Const::No, - }; if *is_auto == IsAuto::Yes { // Auto traits cannot have generics, super traits nor contain items. self.deny_generic_params(generics, ident.span); @@ -1188,7 +1183,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) }); - self.with_in_trait(item.span, constness, |this| { + self.with_in_trait(item.vis.span, *constness, |this| { walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait); }); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index fd75e999d1381..7c63b8e35999e 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -56,7 +56,7 @@ pub(crate) struct TraitFnConst { pub make_impl_const_sugg: Option, #[suggestion( ast_passes_make_trait_const_sugg, - code = "#[const_trait]\n", + code = "const ", applicability = "maybe-incorrect" )] pub make_trait_const_sugg: Option, diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index ced3bcad2293a..753892d1e9970 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -66,7 +66,8 @@ pub(crate) struct TypeConstParser; impl NoArgsAttributeParser for TypeConstParser { const PATH: &[Symbol] = &[sym::type_const]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocConst)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Const), Allow(Target::AssocConst)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst; } @@ -101,17 +102,6 @@ impl NoArgsAttributeParser for DoNotImplementViaObjectParser { const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject; } -// FIXME(const_trait_impl): remove this -// Const traits - -pub(crate) struct ConstTraitParser; -impl NoArgsAttributeParser for ConstTraitParser { - const PATH: &[Symbol] = &[sym::const_trait]; - const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); - const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstTrait; -} - // Specialization pub(crate) struct SpecializationTraitParser; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index a3473c675dd59..4789f27785cb9 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -64,7 +64,7 @@ use crate::attributes::stability::{ }; use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser}; use crate::attributes::traits::{ - AllowIncoherentImplParser, CoinductiveParser, ConstTraitParser, DenyExplicitImplParser, + AllowIncoherentImplParser, CoinductiveParser, DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, ParenSugarParser, PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser, UnsafeSpecializationMarkerParser, @@ -218,7 +218,6 @@ attribute_parsers!( Single>, Single>, Single>, - Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index d81b31b704b3d..f606158e40180 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -381,23 +381,21 @@ fn build_error_for_const_call<'tcx>( `{trait_name}` is not const", ), ); - if parent.is_local() && ccx.tcx.sess.is_nightly_build() { + if let Some(parent) = parent.as_local() + && ccx.tcx.sess.is_nightly_build() + { if !ccx.tcx.features().const_trait_impl() { err.help( "add `#![feature(const_trait_impl)]` to the crate attributes to \ - enable `#[const_trait]`", + enable const traits", ); } - let indentation = ccx - .tcx - .sess - .source_map() - .indentation_before(trait_span) - .unwrap_or_default(); + let span = ccx.tcx.hir_expect_item(parent).vis_span; + let span = ccx.tcx.sess.source_map().span_extend_while_whitespace(span); err.span_suggestion_verbose( - trait_span.shrink_to_lo(), + span.shrink_to_hi(), format!("consider making trait `{trait_name}` const"), - format!("#[const_trait]\n{indentation}"), + "const ".to_owned(), Applicability::MaybeIncorrect, ); } else if !ccx.tcx.sess.is_nightly_build() { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index a1bdede3c4f1b..4d50b9683fc57 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -846,14 +846,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::No, experimental!(register_tool), ), - // RFC 2632 - // FIXME(const_trait_impl) remove this - gated!( - const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl, - "`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." - ), // lang-team MCP 147 gated!( deprecated_safe, Normal, template!(List: &[r#"since = "version", note = "...""#]), ErrorFollowing, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index b1b872808c8f8..7ddd71c346006 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -499,9 +499,6 @@ pub enum AttributeKind { /// Represents `#[rustc_const_stable_indirect]`. ConstStabilityIndirect, - /// Represents `#[const_trait]`. - ConstTrait(Span), - /// Represents `#[coroutine]`. Coroutine(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index d59fccb3f1a0b..2ccfdc2ad983d 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -32,7 +32,6 @@ impl AttributeKind { ConstContinue(..) => No, ConstStability { .. } => Yes, ConstStabilityIndirect => No, - ConstTrait(..) => No, Coroutine(..) => No, Coverage(..) => No, CrateName { .. } => No, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 62013958c7e55..4cdfc752d9895 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3065,7 +3065,7 @@ macro_rules! expect_methods_self_kind { $( #[track_caller] pub fn $name(&self) -> $ret_ty { - let $pat = &self.kind else { expect_failed(stringify!($ident), self) }; + let $pat = &self.kind else { expect_failed(stringify!($name), self) }; $ret_val } )* @@ -3077,7 +3077,7 @@ macro_rules! expect_methods_self { $( #[track_caller] pub fn $name(&self) -> $ret_ty { - let $pat = self else { expect_failed(stringify!($ident), self) }; + let $pat = self else { expect_failed(stringify!($name), self) }; $ret_val } )* @@ -4790,6 +4790,11 @@ impl<'hir> Node<'hir> { ForeignItemKind::Static(ty, ..) => Some(ty), _ => None, }, + Node::GenericParam(param) => match param.kind { + GenericParamKind::Lifetime { .. } => None, + GenericParamKind::Type { default, .. } => default, + GenericParamKind::Const { ty, .. } => Some(ty), + }, _ => None, } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1e12adbbfc6e0..7fa8f9563622c 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -757,22 +757,18 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), } match tcx.def_kind(def_id) { - def_kind @ (DefKind::Static { .. } | DefKind::Const) => { + DefKind::Static { .. } => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); - match def_kind { - DefKind::Static { .. } => { - check_static_inhabited(tcx, def_id); - check_static_linkage(tcx, def_id); - let ty = tcx.type_of(def_id).instantiate_identity(); - res = res.and(wfcheck::check_static_item( - tcx, def_id, ty, /* should_check_for_sync */ true, - )); - } - DefKind::Const => res = res.and(wfcheck::check_const_item(tcx, def_id)), - _ => unreachable!(), - } + + check_static_inhabited(tcx, def_id); + check_static_linkage(tcx, def_id); + let ty = tcx.type_of(def_id).instantiate_identity(); + res = res.and(wfcheck::check_static_item( + tcx, def_id, ty, /* should_check_for_sync */ true, + )); + // Only `Node::Item` and `Node::ForeignItem` still have HIR based // checks. Returning early here does not miss any checks and // 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<(), // avoids this query from having a direct dependency edge on the HIR return res; } + DefKind::Const => { + tcx.ensure_ok().generics_of(def_id); + tcx.ensure_ok().type_of(def_id); + tcx.ensure_ok().predicates_of(def_id); + + res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| { + let ty = tcx.type_of(def_id).instantiate_identity(); + let ty_span = tcx.ty_span(def_id); + let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty); + wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into()); + wfcx.register_bound( + traits::ObligationCause::new( + ty_span, + def_id, + ObligationCauseCode::SizedConstOrStatic, + ), + tcx.param_env(def_id), + ty, + tcx.require_lang_item(LangItem::Sized, ty_span), + ); + check_where_clauses(wfcx, def_id); + + if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + wfcheck::check_type_const(wfcx, def_id, ty, true)?; + } + Ok(()) + })); + + // Only `Node::Item` and `Node::ForeignItem` still have HIR based + // checks. Returning early here does not miss any checks and + // avoids this query from having a direct dependency edge on the HIR + return res; + } DefKind::TyAlias => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); @@ -920,6 +949,11 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), })); check_variances_for_type_defn(tcx, def_id); } + + // Only `Node::Item` and `Node::ForeignItem` still have HIR based + // checks. Returning early here does not miss any checks and + // avoids this query from having a direct dependency edge on the HIR + return res; } DefKind::ForeignMod => { let it = tcx.hir_expect_item(def_id); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 74bf68362fc5f..6a07d2988fdfc 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -6,9 +6,10 @@ use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err}; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::VisitorExt; -use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; +use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, find_attr, intravisit}; use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -1984,12 +1985,46 @@ fn compare_impl_const<'tcx>( trait_const_item: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { + compare_type_const(tcx, impl_const_item, trait_const_item)?; compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?; compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?; check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?; compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref) } +fn compare_type_const<'tcx>( + tcx: TyCtxt<'tcx>, + impl_const_item: ty::AssocItem, + trait_const_item: ty::AssocItem, +) -> Result<(), ErrorGuaranteed> { + let impl_is_type_const = + find_attr!(tcx.get_all_attrs(impl_const_item.def_id), AttributeKind::TypeConst(_)); + let trait_type_const_span = find_attr!( + tcx.get_all_attrs(trait_const_item.def_id), + AttributeKind::TypeConst(sp) => *sp + ); + + if let Some(trait_type_const_span) = trait_type_const_span + && !impl_is_type_const + { + return Err(tcx + .dcx() + .struct_span_err( + tcx.def_span(impl_const_item.def_id), + "implementation of `#[type_const]` const must be marked with `#[type_const]`", + ) + .with_span_note( + MultiSpan::from_spans(vec![ + tcx.def_span(trait_const_item.def_id), + trait_type_const_span, + ]), + "trait declaration of const is marked with `#[type_const]`", + ) + .emit()); + } + Ok(()) +} + /// The equivalent of [compare_method_predicate_entailment], but for associated constants /// instead of associated functions. // FIXME(generic_const_items): If possible extract the common parts of `compare_{type,const}_predicate_entailment`. diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f3d6398b20853..ccae524352a59 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -6,10 +6,11 @@ use rustc_abi::ExternAbi; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{AmbigArg, ItemKind}; +use rustc_hir::{AmbigArg, ItemKind, find_attr}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin, TyCtxtInferExt}; use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION; @@ -925,11 +926,11 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er #[instrument(level = "debug", skip(tcx))] pub(crate) fn check_associated_item( tcx: TyCtxt<'_>, - item_id: LocalDefId, + def_id: LocalDefId, ) -> Result<(), ErrorGuaranteed> { - let loc = Some(WellFormedLoc::Ty(item_id)); - enter_wf_checking_ctxt(tcx, item_id, |wfcx| { - let item = tcx.associated_item(item_id); + let loc = Some(WellFormedLoc::Ty(def_id)); + enter_wf_checking_ctxt(tcx, def_id, |wfcx| { + let item = tcx.associated_item(def_id); // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. @@ -942,27 +943,36 @@ pub(crate) fn check_associated_item( } }; - let span = tcx.def_span(item_id); + let span = tcx.def_span(def_id); match item.kind { ty::AssocKind::Const { .. } => { - let ty = tcx.type_of(item.def_id).instantiate_identity(); - let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); + let ty = tcx.type_of(def_id).instantiate_identity(); + let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); - check_sized_if_body( - wfcx, - item.def_id.expect_local(), - ty, - Some(span), - ObligationCauseCode::SizedConstOrStatic, - ); + + let has_value = item.defaultness(tcx).has_value(); + if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + check_type_const(wfcx, def_id, ty, has_value)?; + } + + if has_value { + let code = ObligationCauseCode::SizedConstOrStatic; + wfcx.register_bound( + ObligationCause::new(span, def_id, code), + wfcx.param_env, + ty, + tcx.require_lang_item(LangItem::Sized, span), + ); + } + Ok(()) } ty::AssocKind::Fn { .. } => { - let sig = tcx.fn_sig(item.def_id).instantiate_identity(); + let sig = tcx.fn_sig(def_id).instantiate_identity(); let hir_sig = - tcx.hir_node_by_def_id(item_id).fn_sig().expect("bad signature for method"); - check_fn_or_method(wfcx, sig, hir_sig.decl, item_id); + tcx.hir_node_by_def_id(def_id).fn_sig().expect("bad signature for method"); + check_fn_or_method(wfcx, sig, hir_sig.decl, def_id); check_method_receiver(wfcx, hir_sig, item, self_ty) } ty::AssocKind::Type { .. } => { @@ -970,8 +980,8 @@ pub(crate) fn check_associated_item( check_associated_type_bounds(wfcx, item, span) } if item.defaultness(tcx).has_value() { - let ty = tcx.type_of(item.def_id).instantiate_identity(); - let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); + let ty = tcx.type_of(def_id).instantiate_identity(); + let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); } Ok(()) @@ -1222,28 +1232,36 @@ pub(crate) fn check_static_item<'tcx>( }) } -pub(crate) fn check_const_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { - enter_wf_checking_ctxt(tcx, def_id, |wfcx| { - let ty = tcx.type_of(def_id).instantiate_identity(); - let ty_span = tcx.ty_span(def_id); - let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty); +#[instrument(level = "debug", skip(wfcx))] +pub(super) fn check_type_const<'tcx>( + wfcx: &WfCheckingCtxt<'_, 'tcx>, + def_id: LocalDefId, + item_ty: Ty<'tcx>, + has_value: bool, +) -> Result<(), ErrorGuaranteed> { + let tcx = wfcx.tcx(); + let span = tcx.def_span(def_id); - wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into()); - wfcx.register_bound( - traits::ObligationCause::new( - ty_span, - wfcx.body_def_id, - ObligationCauseCode::SizedConstOrStatic, - ), - wfcx.param_env, - ty, - tcx.require_lang_item(LangItem::Sized, ty_span), - ); + wfcx.register_bound( + ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)), + wfcx.param_env, + item_ty, + tcx.require_lang_item(LangItem::ConstParamTy, span), + ); - check_where_clauses(wfcx, def_id); + if has_value { + let raw_ct = tcx.const_of_item(def_id).instantiate_identity(); + let norm_ct = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), raw_ct); + wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(def_id)), norm_ct.into()); - Ok(()) - }) + wfcx.register_obligation(Obligation::new( + tcx, + ObligationCause::new(span, def_id, ObligationCauseCode::WellFormed(None)), + wfcx.param_env, + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(norm_ct, item_ty)), + )); + } + Ok(()) } #[instrument(level = "debug", skip(tcx, impl_))] @@ -1583,33 +1601,16 @@ fn check_fn_or_method<'tcx>( } // If the function has a body, additionally require that the return type is sized. - check_sized_if_body( - wfcx, - def_id, - sig.output(), - match hir_decl.output { - hir::FnRetTy::Return(ty) => Some(ty.span), - hir::FnRetTy::DefaultReturn(_) => None, - }, - ObligationCauseCode::SizedReturnType, - ); -} - -fn check_sized_if_body<'tcx>( - wfcx: &WfCheckingCtxt<'_, 'tcx>, - def_id: LocalDefId, - ty: Ty<'tcx>, - maybe_span: Option, - code: ObligationCauseCode<'tcx>, -) { - let tcx = wfcx.tcx(); if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) { - let span = maybe_span.unwrap_or(body.value.span); + let span = match hir_decl.output { + hir::FnRetTy::Return(ty) => ty.span, + hir::FnRetTy::DefaultReturn(_) => body.value.span, + }; wfcx.register_bound( - ObligationCause::new(span, def_id, code), + ObligationCause::new(span, def_id, ObligationCauseCode::SizedReturnType), wfcx.param_env, - ty, + sig.output(), tcx.require_lang_item(LangItem::Sized, span), ); } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 162ea80ed8aa7..a929a9215b3c7 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -891,15 +891,6 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { }; let attrs = tcx.get_all_attrs(def_id); - // Only regular traits can be const. - // FIXME(const_trait_impl): remove this - let constness = if constness == hir::Constness::Const - || !is_alias && find_attr!(attrs, AttributeKind::ConstTrait(_)) - { - hir::Constness::Const - } else { - hir::Constness::NotConst - }; let paren_sugar = find_attr!(attrs, AttributeKind::ParenSugar(_)); if paren_sugar && !tcx.features().unboxed_closures() { @@ -1382,22 +1373,27 @@ fn check_impl_constness( } let trait_name = tcx.item_name(trait_def_id).to_string(); - let (local_trait_span, suggestion_pre) = - match (trait_def_id.is_local(), tcx.sess.is_nightly_build()) { - (true, true) => ( - Some(tcx.def_span(trait_def_id).shrink_to_lo()), + let (suggestion, suggestion_pre) = match (trait_def_id.as_local(), tcx.sess.is_nightly_build()) + { + (Some(trait_def_id), true) => { + let span = tcx.hir_expect_item(trait_def_id).vis_span; + let span = tcx.sess.source_map().span_extend_while_whitespace(span); + + ( + Some(span.shrink_to_hi()), if tcx.features().const_trait_impl() { "" } else { "enable `#![feature(const_trait_impl)]` in your crate and " }, - ), - (false, _) | (_, false) => (None, ""), - }; + ) + } + (None, _) | (_, false) => (None, ""), + }; tcx.dcx().emit_err(errors::ConstImplForNonConstTrait { trait_ref_span: hir_trait_ref.path.span, trait_name, - local_trait_span, + suggestion, suggestion_pre, marking: (), adding: (), @@ -1615,8 +1611,12 @@ fn const_of_item<'tcx>( }; let ct_arg = match ct_rhs { hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg, - hir::ConstItemRhs::Body(body_id) => { - bug!("cannot call const_of_item on a non-type_const {body_id:?}") + hir::ConstItemRhs::Body(_) => { + let e = tcx.dcx().span_delayed_bug( + tcx.def_span(def_id), + "cannot call const_of_item on a non-type_const", + ); + return ty::EarlyBinder::bind(Const::new_error(tcx, e)); } }; let icx = ItemCtxt::new(tcx, def_id); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index dbad98fd79528..209b0156de323 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -500,13 +500,8 @@ pub(crate) struct ConstImplForNonConstTrait { #[label] pub trait_ref_span: Span, pub trait_name: String, - #[suggestion( - applicability = "machine-applicable", - // FIXME(const_trait_impl) fix this suggestion - code = "#[const_trait] ", - style = "verbose" - )] - pub local_trait_span: Option, + #[suggestion(applicability = "machine-applicable", code = "const ", style = "verbose")] + pub suggestion: Option, pub suggestion_pre: &'static str, #[note] pub marking: (), @@ -523,14 +518,9 @@ pub(crate) struct ConstBoundForNonConstTrait { pub modifier: &'static str, #[note] pub def_span: Option, - pub suggestion_pre: &'static str, - #[suggestion( - applicability = "machine-applicable", - // FIXME(const_trait_impl) fix this suggestion - code = "#[const_trait] ", - style = "verbose" - )] + #[suggestion(applicability = "machine-applicable", code = "const ", style = "verbose")] pub suggestion: Option, + pub suggestion_pre: &'static str, pub trait_name: String, } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index de65e4c6addf9..79f3d7f2ff8f5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -881,28 +881,33 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness - && !self.tcx().is_const_trait(trait_def_id) + && !tcx.is_const_trait(trait_def_id) { let (def_span, suggestion, suggestion_pre) = - match (trait_def_id.is_local(), self.tcx().sess.is_nightly_build()) { - (true, true) => ( - None, - Some(tcx.def_span(trait_def_id).shrink_to_lo()), - if self.tcx().features().const_trait_impl() { - "" - } else { - "enable `#![feature(const_trait_impl)]` in your crate and " - }, - ), - (false, _) | (_, false) => (Some(tcx.def_span(trait_def_id)), None, ""), + match (trait_def_id.as_local(), tcx.sess.is_nightly_build()) { + (Some(trait_def_id), true) => { + let span = tcx.hir_expect_item(trait_def_id).vis_span; + let span = tcx.sess.source_map().span_extend_while_whitespace(span); + + ( + None, + Some(span.shrink_to_hi()), + if self.tcx().features().const_trait_impl() { + "" + } else { + "enable `#![feature(const_trait_impl)]` in your crate and " + }, + ) + } + (None, _) | (_, false) => (Some(tcx.def_span(trait_def_id)), None, ""), }; self.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait { span, modifier: constness.as_str(), def_span, - trait_name: self.tcx().def_path_str(trait_def_id), - suggestion_pre, + trait_name: tcx.def_path_str(trait_def_id), suggestion, + suggestion_pre, }); } else { match predicate_filter { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 463338ee1fb5d..347e103af9378 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -150,9 +150,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::ProcMacroDerive { .. }) => { self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } - &Attribute::Parsed(AttributeKind::TypeConst(attr_span)) => { - self.check_type_const(hir_id, attr_span, target) - } Attribute::Parsed( AttributeKind::Stability { span: attr_span, @@ -235,7 +232,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::Marker(..) | AttributeKind::SkipDuringMethodDispatch { .. } | AttributeKind::Coinductive(..) - | AttributeKind::ConstTrait(..) | AttributeKind::DenyExplicitImpl(..) | AttributeKind::DoNotImplementViaObject(..) | AttributeKind::SpecializationTrait(..) @@ -243,6 +239,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::ParenSugar(..) | AttributeKind::AllowIncoherentImpl(..) | AttributeKind::Confusables { .. } + | AttributeKind::TypeConst{..} // `#[doc]` is actually a lot more than just doc comments, so is checked below | AttributeKind::DocComment {..} // handled below this loop and elsewhere @@ -2115,16 +2112,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_type_const(&self, _hir_id: HirId, attr_span: Span, target: Target) { - if matches!(target, Target::AssocConst | Target::Const) { - return; - } else { - self.dcx() - .struct_span_err(attr_span, "`#[type_const]` must only be applied to const items") - .emit(); - } - } - fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) { if !find_attr!(attrs, AttributeKind::Repr { reprs, .. } => reprs.iter().any(|(r, _)| r == &ReprAttr::ReprTransparent)) .unwrap_or(false) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b6d1ff2432d6b..0912bad459da7 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -750,7 +750,6 @@ symbols! { const_raw_ptr_to_usize_cast, const_refs_to_cell, const_refs_to_static, - const_trait, const_trait_bound_opt_out, const_trait_impl, const_try, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index d2f2c92dda080..c282f42042600 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1286,12 +1286,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty: Ty<'tcx>, obligation: &PredicateObligation<'tcx>, ) -> Diag<'a> { - let param = obligation.cause.body_id; - let hir::GenericParamKind::Const { ty: &hir::Ty { span, .. }, .. } = - self.tcx.hir_node_by_def_id(param).expect_generic_param().kind - else { - bug!() - }; + let def_id = obligation.cause.body_id; + let span = self.tcx.ty_span(def_id); let mut file = None; let ty_str = self.tcx.short_string(ty, &mut file); diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index c2c7ccf0daa23..ec79a657e58e2 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -132,9 +132,8 @@ where #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] impl const Eq for [T; N] {} -#[const_trait] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] -trait SpecArrayEq: Sized { +const trait SpecArrayEq: Sized { fn spec_eq(a: &[Self; N], b: &[Other; N]) -> bool; fn spec_ne(a: &[Self; N], b: &[Other; N]) -> bool; } diff --git a/library/core/src/cmp/bytewise.rs b/library/core/src/cmp/bytewise.rs index 2265fa7a3531c..f0f5f656405a9 100644 --- a/library/core/src/cmp/bytewise.rs +++ b/library/core/src/cmp/bytewise.rs @@ -17,8 +17,7 @@ use crate::num::NonZero; /// - Neither `Self` nor `Rhs` have provenance, so integer comparisons are correct. /// - `>::{eq,ne}` are equivalent to comparing the bytes. #[rustc_specialization_trait] -#[const_trait] // FIXME(const_trait_impl): Migrate to `const unsafe trait` once #146122 is fixed. -pub(crate) unsafe trait BytewiseEq: +pub(crate) const unsafe trait BytewiseEq: [const] PartialEq + Sized { } diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index d781f3f7ace4a..a0b74ff383ea4 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -816,9 +816,8 @@ impl Bound<&T> { /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. #[stable(feature = "collections_range", since = "1.28.0")] #[rustc_diagnostic_item = "RangeBounds"] -#[const_trait] #[rustc_const_unstable(feature = "const_range", issue = "none")] -pub trait RangeBounds { +pub const trait RangeBounds { /// Start index bound. /// /// Returns the start value as a `Bound`. @@ -954,9 +953,8 @@ pub trait RangeBounds { /// `IntoBounds` is implemented by Rust’s built-in range types, produced /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. #[unstable(feature = "range_into_bounds", issue = "136903")] -#[const_trait] #[rustc_const_unstable(feature = "const_range", issue = "none")] -pub trait IntoBounds: [const] RangeBounds { +pub const trait IntoBounds: [const] RangeBounds { /// Convert this range into the start and end bounds. /// Returns `(start_bound, end_bound)`. /// @@ -1319,9 +1317,8 @@ pub enum OneSidedRangeBound { /// Types that implement `OneSidedRange` must return `Bound::Unbounded` /// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`. #[unstable(feature = "one_sided_range", issue = "69780")] -#[const_trait] #[rustc_const_unstable(feature = "const_range", issue = "none")] -pub trait OneSidedRange: RangeBounds { +pub const trait OneSidedRange: RangeBounds { /// An internal-only helper function for `split_off` and /// `split_off_mut` that returns the bound of the one-sided range. fn bound(self) -> (OneSidedRangeBound, T); diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 103630aba0f79..fd1ca23fb79c5 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -155,18 +155,16 @@ where } #[doc(hidden)] -#[const_trait] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] // intermediate trait for specialization of slice's PartialOrd -trait SlicePartialOrd: Sized { +const trait SlicePartialOrd: Sized { fn partial_compare(left: &[Self], right: &[Self]) -> Option; } #[doc(hidden)] -#[const_trait] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] // intermediate trait for specialization of slice's PartialOrd chaining methods -trait SliceChain: Sized { +const trait SliceChain: Sized { fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow; fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow; fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow; @@ -244,9 +242,8 @@ impl const SlicePartialOrd for A { } #[rustc_specialization_trait] -#[const_trait] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] -trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {} +const trait AlwaysApplicableOrd: [const] SliceOrd + [const] Ord {} macro_rules! always_applicable_ord { ($([$($p:tt)*] $t:ty,)*) => { @@ -265,10 +262,9 @@ always_applicable_ord! { } #[doc(hidden)] -#[const_trait] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] // intermediate trait for specialization of slice's Ord -trait SliceOrd: Sized { +const trait SliceOrd: Sized { fn compare(left: &[Self], right: &[Self]) -> Ordering; } @@ -292,8 +288,7 @@ impl SliceOrd for A { /// * For every `x` and `y` of this type, `Ord(x, y)` must return the same /// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`. #[rustc_specialization_trait] -#[const_trait] -unsafe trait UnsignedBytewiseOrd: [const] Ord {} +const unsafe trait UnsignedBytewiseOrd: [const] Ord {} #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] unsafe impl const UnsignedBytewiseOrd for bool {} diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 1a4dcebf36483..d8ed521f44353 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -159,9 +159,8 @@ mod private_slice_index { message = "the type `{T}` cannot be indexed by `{Self}`", label = "slice indices are of type `usize` or ranges of `usize`" )] -#[const_trait] // FIXME(const_trait_impl): Migrate to `const unsafe trait` once #146122 is fixed. #[rustc_const_unstable(feature = "const_index", issue = "143775")] -pub unsafe trait SliceIndex: private_slice_index::Sealed { +pub const unsafe trait SliceIndex: private_slice_index::Sealed { /// The output type returned by methods. #[stable(feature = "slice_get_slice", since = "1.28.0")] type Output: ?Sized; diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 9af3e5f63ffb4..7efb7ad8ee8b3 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -22,7 +22,7 @@ use crate::io::try_set_output_capture; use crate::mem::{self, ManuallyDrop}; use crate::panic::{BacktraceStyle, PanicHookInfo}; use crate::sync::atomic::{Atomic, AtomicBool, Ordering}; -use crate::sync::{PoisonError, RwLock}; +use crate::sync::nonpoison::RwLock; use crate::sys::backtrace; use crate::sys::stdio::panic_output; use crate::{fmt, intrinsics, process, thread}; @@ -144,13 +144,9 @@ pub fn set_hook(hook: Box) + 'static + Sync + Send>) { panic!("cannot modify the panic hook from a panicking thread"); } - let new = Hook::Custom(hook); - let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner); - let old = mem::replace(&mut *hook, new); - drop(hook); - // Only drop the old hook after releasing the lock to avoid deadlocking - // if its destructor panics. - drop(old); + // Drop the old hook after changing the hook to avoid deadlocking if its + // destructor panics. + drop(HOOK.replace(Hook::Custom(hook))); } /// Unregisters the current panic hook and returns it, registering the default hook @@ -188,11 +184,7 @@ pub fn take_hook() -> Box) + 'static + Sync + Send> { panic!("cannot modify the panic hook from a panicking thread"); } - let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner); - let old_hook = mem::take(&mut *hook); - drop(hook); - - old_hook.into_box() + HOOK.replace(Hook::Default).into_box() } /// Atomic combination of [`take_hook`] and [`set_hook`]. Use this to replace the panic handler with @@ -238,7 +230,7 @@ where panic!("cannot modify the panic hook from a panicking thread"); } - let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner); + let mut hook = HOOK.write(); let prev = mem::take(&mut *hook).into_box(); *hook = Hook::Custom(Box::new(move |info| hook_fn(&prev, info))); } @@ -822,7 +814,7 @@ fn panic_with_hook( crate::process::abort(); } - match *HOOK.read().unwrap_or_else(PoisonError::into_inner) { + match *HOOK.read() { // Some platforms (like wasm) know that printing to stderr won't ever actually // print anything, and if that's the case we can skip the default // hook. Since string formatting happens lazily when calling `payload` diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index faada9a111db8..c670ae88fc549 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -430,6 +430,7 @@ pub fn linker_flags( match builder.config.bootstrap_override_lld { BootstrapOverrideLld::External => { args.push("-Clinker-features=+lld".to_string()); + args.push("-Clink-self-contained=-linker".to_string()); args.push("-Zunstable-options".to_string()); } BootstrapOverrideLld::SelfContained => { diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index e90a7ef42324a..55eba6c696c5f 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -306,6 +306,14 @@ impl<'a> Renderer<'a> { ); } + fn render_report(&self, report: &Report) { + let &Report { total_time, compilation_time } = report; + // Should match `write_merged_doctest_times` in `library/test/src/formatters/pretty.rs`. + println!( + "all doctests ran in {total_time:.2}s; merged doctests compilation took {compilation_time:.2}s" + ); + } + fn render_message(&mut self, message: Message) { match message { Message::Suite(SuiteMessage::Started { test_count }) => { @@ -323,6 +331,9 @@ impl<'a> Renderer<'a> { Message::Suite(SuiteMessage::Failed(outcome)) => { self.render_suite_outcome(Outcome::Failed, &outcome); } + Message::Report(report) => { + self.render_report(&report); + } Message::Bench(outcome) => { // The formatting for benchmarks doesn't replicate 1:1 the formatting libtest // outputs, mostly because libtest's formatting is broken in terse mode, which is @@ -435,6 +446,7 @@ enum Message { Suite(SuiteMessage), Test(TestMessage), Bench(BenchOutcome), + Report(Report), } #[derive(serde_derive::Deserialize)] @@ -481,3 +493,10 @@ struct TestOutcome { stdout: Option, message: Option, } + +/// Emitted when running doctests. +#[derive(serde_derive::Deserialize)] +struct Report { + total_time: f64, + compilation_time: f64, +} diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index f32013d75e500..1771d1382f073 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -993,7 +993,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT [clang-kcfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-kcfi [clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html -[clan-rtsan]: https://clang.llvm.org/docs/RealtimeSanitizer.html +[clang-rtsan]: https://clang.llvm.org/docs/RealtimeSanitizer.html [clang-safestack]: https://clang.llvm.org/docs/SafeStack.html [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index 0716f4add9d0d..0f04397b72d22 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -52,18 +52,6 @@ fn show_version() { println!(); } -fn forward_patched_extern_arg(args: &mut impl Iterator, cmd: &mut Command) { - cmd.arg("--extern"); // always forward flag, but adjust filename: - let path = args.next().expect("`--extern` should be followed by a filename"); - if let Some(lib) = path.strip_suffix(".rlib") { - // If this is an rlib, make it an rmeta. - cmd.arg(format!("{lib}.rmeta")); - } else { - // Some other extern file (e.g. a `.so`). Forward unchanged. - cmd.arg(path); - } -} - pub fn phase_cargo_miri(mut args: impl Iterator) { // Require a subcommand before any flags. // We cannot know which of those flags take arguments and which do not, @@ -276,7 +264,7 @@ pub enum RustcPhase { Rustdoc, } -pub fn phase_rustc(mut args: impl Iterator, phase: RustcPhase) { +pub fn phase_rustc(args: impl Iterator, phase: RustcPhase) { /// Determines if we are being invoked (as rustc) to build a crate for /// the "target" architecture, in contrast to the "host" architecture. /// 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, phase: RustcPhase) { } let mut cmd = miri(); - let mut emit_link_hack = false; // Arguments are treated very differently depending on whether this crate is // for interpretation by Miri, or for use by a build script / proc macro. if target_crate { @@ -455,7 +442,7 @@ pub fn phase_rustc(mut args: impl Iterator, phase: RustcPhase) { } // Forward arguments, but patched. - let emit_flag = "--emit"; + // This hack helps bootstrap run standard library tests in Miri. The issue is as follows: // when running `cargo miri test` on libcore, cargo builds a local copy of core and makes it // 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, phase: RustcPhase) { let replace_librs = env::var_os("MIRI_REPLACE_LIBRS_IF_NOT_TEST").is_some() && !runnable_crate && phase == RustcPhase::Build; - while let Some(arg) = args.next() { - // Patch `--emit`: remove "link" from "--emit" to make this a check-only build. - if let Some(val) = arg.strip_prefix(emit_flag) { - // Patch this argument. First, extract its value. - let val = - val.strip_prefix('=').expect("`cargo` should pass `--emit=X` as one argument"); - let mut val: Vec<_> = val.split(',').collect(); - // Now make sure "link" is not in there, but "metadata" is. - if let Some(i) = val.iter().position(|&s| s == "link") { - emit_link_hack = true; - val.remove(i); - if !val.contains(&"metadata") { - val.push("metadata"); - } - } - cmd.arg(format!("{emit_flag}={}", val.join(","))); - continue; - } - // Patch `--extern` filenames, since Cargo sometimes passes stub `.rlib` files: - // https://github.com/rust-lang/miri/issues/1705 - if arg == "--extern" { - forward_patched_extern_arg(&mut args, &mut cmd); - continue; - } + for arg in args { // If the REPLACE_LIBRS hack is enabled and we are building a `lib.rs` file, and a // `lib.miri.rs` file exists, then build that instead. if replace_librs { @@ -543,17 +507,6 @@ pub fn phase_rustc(mut args: impl Iterator, phase: RustcPhase) { eprintln!("[cargo-miri rustc] target_crate={target_crate} runnable_crate={runnable_crate}"); } - // Create a stub .rlib file if "link" was requested by cargo. - // This is necessary to prevent cargo from doing rebuilds all the time. - if emit_link_hack { - for filename in out_filenames() { - if verbose > 0 { - eprintln!("[cargo-miri rustc] creating fake lib file at `{}`", filename.display()); - } - File::create(filename).expect("failed to create fake lib file"); - } - } - debug_cmd("[cargo-miri rustc]", verbose, &cmd); exec(cmd); } @@ -624,17 +577,11 @@ pub fn phase_runner(mut binary_args: impl Iterator, phase: Runner cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap()); } // Forward rustc arguments. - // We need to patch "--extern" filenames because we forced a check-only - // build without cargo knowing about that: replace `.rlib` suffix by - // `.rmeta`. - // We also need to remove `--error-format` as cargo specifies that to be JSON, + // We need to remove `--error-format` as cargo specifies that to be JSON, // but when we run here, cargo does not interpret the JSON any more. `--json` // then also needs to be dropped. - let mut args = info.args.iter(); - while let Some(arg) = args.next() { - if arg == "--extern" { - forward_patched_extern_arg(&mut (&mut args).cloned(), &mut cmd); - } else if let Some(suffix) = arg.strip_prefix("--error-format") { + for arg in &info.args { + if let Some(suffix) = arg.strip_prefix("--error-format") { assert!(suffix.starts_with('=')); // Drop this argument. } else if let Some(suffix) = arg.strip_prefix("--json") { @@ -668,7 +615,7 @@ pub fn phase_runner(mut binary_args: impl Iterator, phase: Runner } } -pub fn phase_rustdoc(mut args: impl Iterator) { +pub fn phase_rustdoc(args: impl Iterator) { let verbose = env::var("MIRI_VERBOSE") .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer")); @@ -676,15 +623,7 @@ pub fn phase_rustdoc(mut args: impl Iterator) { // of the old value into MIRI_ORIG_RUSTDOC. So that's what we have to invoke now. let rustdoc = env::var("MIRI_ORIG_RUSTDOC").unwrap_or("rustdoc".to_string()); let mut cmd = Command::new(rustdoc); - - while let Some(arg) = args.next() { - if arg == "--extern" { - // Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files. - forward_patched_extern_arg(&mut args, &mut cmd); - } else { - cmd.arg(arg); - } - } + cmd.args(args); // Doctests of `proc-macro` crates (and their dependencies) are always built for the host, // so we are not able to run them in Miri. diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs index e399f66fbc9cd..c7682093663ed 100644 --- a/src/tools/miri/cargo-miri/src/setup.rs +++ b/src/tools/miri/cargo-miri/src/setup.rs @@ -160,7 +160,7 @@ pub fn setup( // Do the build. let status = SysrootBuilder::new(&sysroot_dir, target) - .build_mode(BuildMode::Check) + .build_mode(BuildMode::Build) // not a real build, since we use dummy codegen .rustc_version(rustc_version.clone()) .sysroot_config(sysroot_config) .rustflags(rustflags) diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index f1b5229312325..5a8bf76befd6e 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -57,7 +57,9 @@ impl MiriEnv { .arg("--") .args(&["miri", "setup", "--print-sysroot"]) .args(target_flag); - cmd.set_quiet(quiet); + if quiet { + cmd = cmd.arg("--quiet"); + } let output = cmd.read()?; self.sh.set_var("MIRI_SYSROOT", &output); Ok(output.into()) @@ -112,8 +114,8 @@ impl Command { Command::Check { features, flags } => Self::check(features, flags), Command::Test { bless, target, coverage, features, flags } => Self::test(bless, target, coverage, features, flags), - Command::Run { dep, verbose, target, edition, features, flags } => - Self::run(dep, verbose, target, edition, features, flags), + Command::Run { dep, quiet, target, edition, features, flags } => + Self::run(dep, quiet, target, edition, features, flags), Command::Doc { features, flags } => Self::doc(features, flags), Command::Fmt { flags } => Self::fmt(flags), Command::Clippy { features, flags } => Self::clippy(features, flags), @@ -458,7 +460,7 @@ impl Command { fn run( dep: bool, - verbose: bool, + quiet: bool, target: Option, edition: Option, features: Vec, @@ -468,7 +470,7 @@ impl Command { // Preparation: get a sysroot, and get the miri binary. let miri_sysroot = - e.build_miri_sysroot(/* quiet */ !verbose, target.as_deref(), &features)?; + e.build_miri_sysroot(/* quiet */ quiet, target.as_deref(), &features)?; let miri_bin = e .build_get_binary(".", &features) .context("failed to get filename of miri executable")?; @@ -492,7 +494,7 @@ impl Command { // Compute flags. let miri_flags = e.sh.var("MIRIFLAGS").unwrap_or_default(); let miri_flags = flagsplit(&miri_flags); - let quiet_flag = if verbose { None } else { Some("--quiet") }; + let quiet_flag = if quiet { Some("--quiet") } else { None }; // Run Miri. // The basic command that executes the Miri driver. @@ -506,7 +508,7 @@ impl Command { } else { cmd!(e.sh, "{miri_bin}") }; - cmd.set_quiet(!verbose); + cmd.set_quiet(quiet); // Add Miri flags let mut cmd = cmd.args(&miri_flags).args(&early_flags).args(&flags); // For `--dep` we also need to set the target in the env var. diff --git a/src/tools/miri/miri-script/src/main.rs b/src/tools/miri/miri-script/src/main.rs index 761ec5979fafe..e307014496886 100644 --- a/src/tools/miri/miri-script/src/main.rs +++ b/src/tools/miri/miri-script/src/main.rs @@ -78,9 +78,9 @@ pub enum Command { /// Build the program with the dependencies declared in `tests/deps/Cargo.toml`. #[arg(long)] dep: bool, - /// Show build progress. + /// Hide build progress. #[arg(long, short)] - verbose: bool, + quiet: bool, /// The cross-interpretation target. #[arg(long)] target: Option, diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 036282b12f5de..1ce491a50eae4 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -5f9dd05862d2e4bceb3be1031b6c936e35671501 +ceb7df7e6f17c92c7d49f7e4f02df0e68bc9b38b diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 6ef6e340b3d92..920fc29481916 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -16,7 +16,6 @@ extern crate rustc_hir; extern crate rustc_hir_analysis; extern crate rustc_interface; extern crate rustc_log; -extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; @@ -26,10 +25,8 @@ mod log; use std::env; use std::num::NonZero; use std::ops::Range; -use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; -use std::sync::Arc; use std::sync::atomic::{AtomicI32, AtomicU32, Ordering}; use miri::{ @@ -51,10 +48,8 @@ use rustc_middle::middle::exported_symbols::{ use rustc_middle::query::LocalCrate; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::util::Providers; use rustc_session::EarlyDiagCtxt; use rustc_session::config::{CrateType, ErrorOutputType, OptLevel}; -use rustc_session::search_paths::PathKind; use rustc_span::def_id::DefId; use crate::log::setup::{deinit_loggers, init_early_loggers, init_late_loggers}; @@ -126,21 +121,6 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) { } impl rustc_driver::Callbacks for MiriCompilerCalls { - fn config(&mut self, config: &mut Config) { - config.override_queries = Some(|_, providers| { - providers.extern_queries.used_crate_source = |tcx, cnum| { - let mut providers = Providers::default(); - rustc_metadata::provide(&mut providers); - let mut crate_source = (providers.extern_queries.used_crate_source)(tcx, cnum); - // HACK: rustc will emit "crate ... required to be available in rlib format, but - // was not found in this form" errors once we use `tcx.dependency_formats()` if - // there's no rlib provided, so setting a dummy path here to workaround those errors. - Arc::make_mut(&mut crate_source).rlib = Some((PathBuf::new(), PathKind::All)); - crate_source - }; - }); - } - fn after_analysis<'tcx>( &mut self, _: &rustc_interface::interface::Compiler, @@ -253,12 +233,26 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls { #[allow(rustc::potential_query_instability)] // rustc_codegen_ssa (where this code is copied from) also allows this lint fn config(&mut self, config: &mut Config) { if config.opts.prints.is_empty() && self.target_crate { + #[allow(rustc::bad_opt_access)] // tcx does not exist yet + { + let any_crate_types = !config.opts.crate_types.is_empty(); + // Avoid warnings about unsupported crate types. + config + .opts + .crate_types + .retain(|&c| c == CrateType::Executable || c == CrateType::Rlib); + if any_crate_types { + // Assert that we didn't remove all crate types if any crate type was passed on + // the cli. Otherwise we might silently change what kind of crate we are building. + assert!(!config.opts.crate_types.is_empty()); + } + } + // Queries overridden here affect the data stored in `rmeta` files of dependencies, // which will be used later in non-`MIRI_BE_RUSTC` mode. config.override_queries = Some(|_, local_providers| { - // `exported_non_generic_symbols` and `reachable_non_generics` provided by rustc always returns - // an empty result if `tcx.sess.opts.output_types.should_codegen()` is false. - // In addition we need to add #[used] symbols to exported_symbols for `lookup_link_section`. + // We need to add #[used] symbols to exported_symbols for `lookup_link_section`. + // FIXME handle this somehow in rustc itself to avoid this hack. local_providers.exported_non_generic_symbols = |tcx, LocalCrate| { let reachable_set = tcx.with_stable_hashing_context(|hcx| { tcx.reachable_set(()).to_sorted(&hcx, true) diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 89bd93edae127..ebca7377fdbcc 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -11,6 +11,22 @@ use crate::*; pub mod stacked_borrows; pub mod tree_borrows; +/// Indicates which kind of access is being performed. +#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] +pub enum AccessKind { + Read, + Write, +} + +impl fmt::Display for AccessKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AccessKind::Read => write!(f, "read access"), + AccessKind::Write => write!(f, "write access"), + } + } +} + /// Tracking pointer provenance #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct BorTag(NonZero); @@ -115,15 +131,6 @@ impl VisitProvenance for GlobalStateInner { /// We need interior mutable access to the global state. pub type GlobalState = RefCell; -impl fmt::Display for AccessKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - AccessKind::Read => write!(f, "read access"), - AccessKind::Write => write!(f, "write access"), - } - } -} - /// Policy on whether to recurse into fields to retag #[derive(Copy, Clone, Debug)] pub enum RetagFields { diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index 997d7799a5f1c..36e574c8e57f7 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_span::{Span, SpanData}; use smallvec::SmallVec; -use crate::borrow_tracker::{GlobalStateInner, ProtectorKind}; +use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind}; use crate::*; /// Error reporting diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 76ede552baa2d..fa60f27185f83 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -21,7 +21,7 @@ pub use self::stack::Stack; use crate::borrow_tracker::stacked_borrows::diagnostics::{ AllocHistory, DiagnosticCx, DiagnosticCxBuilder, }; -use crate::borrow_tracker::{GlobalStateInner, ProtectorKind}; +use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind}; use crate::concurrency::data_race::{NaReadType, NaWriteType}; use crate::*; diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs index 00f921b0f8afb..f2410a08625dd 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -4,10 +4,10 @@ use std::ops::Range; use rustc_data_structures::fx::FxHashMap; use rustc_span::{Span, SpanData}; -use crate::borrow_tracker::ProtectorKind; use crate::borrow_tracker::tree_borrows::perms::{PermTransition, Permission}; use crate::borrow_tracker::tree_borrows::tree::LocationState; use crate::borrow_tracker::tree_borrows::unimap::UniIndex; +use crate::borrow_tracker::{AccessKind, ProtectorKind}; use crate::*; /// Cause of an access: either a real access or one diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 5c905fc161f0f..720c5b239495e 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::{self, Ty}; use self::foreign_access_skipping::IdempotentForeignAccess; use self::tree::LocationState; -use crate::borrow_tracker::{GlobalState, GlobalStateInner, ProtectorKind}; +use crate::borrow_tracker::{AccessKind, GlobalState, GlobalStateInner, ProtectorKind}; use crate::concurrency::data_race::NaReadType; use crate::*; diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 968e4961a6355..b84ebd51656c0 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -1,7 +1,7 @@ use std::cmp::{Ordering, PartialOrd}; use std::fmt; -use crate::AccessKind; +use crate::borrow_tracker::AccessKind; use crate::borrow_tracker::tree_borrows::diagnostics::TransitionError; use crate::borrow_tracker::tree_borrows::tree::AccessRelatedness; diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index 740483844e795..e337fe05e135d 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -25,7 +25,7 @@ use crate::borrow_tracker::tree_borrows::diagnostics::{ use crate::borrow_tracker::tree_borrows::foreign_access_skipping::IdempotentForeignAccess; use crate::borrow_tracker::tree_borrows::perms::PermTransition; use crate::borrow_tracker::tree_borrows::unimap::{UniIndex, UniKeyMap, UniValMap}; -use crate::borrow_tracker::{GlobalState, ProtectorKind}; +use crate::borrow_tracker::{AccessKind, GlobalState, ProtectorKind}; use crate::*; mod tests; diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs index daea20b3779b2..5c3541ffbe4c1 100644 --- a/src/tools/miri/src/concurrency/init_once.rs +++ b/src/tools/miri/src/concurrency/init_once.rs @@ -57,6 +57,10 @@ impl InitOnceRef { pub fn begin(&self) { self.0.borrow_mut().begin(); } + + pub fn queue_is_empty(&self) -> bool { + self.0.borrow().waiters.is_empty() + } } impl VisitProvenance for InitOnceRef { diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index e4e7fb1d725fe..c529ed5145edd 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -1,3 +1,4 @@ +use std::any::Any; use std::cell::RefCell; use std::collections::VecDeque; use std::collections::hash_map::Entry; @@ -5,6 +6,7 @@ use std::default::Default; use std::ops::Not; use std::rc::Rc; use std::time::Duration; +use std::{fmt, iter}; use rustc_abi::Size; use rustc_data_structures::fx::FxHashMap; @@ -12,6 +14,52 @@ use rustc_data_structures::fx::FxHashMap; use super::vector_clock::VClock; use crate::*; +/// Indicates which kind of access is being performed. +#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] +pub enum AccessKind { + Read, + Write, + Dealloc, +} + +impl fmt::Display for AccessKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AccessKind::Read => write!(f, "read"), + AccessKind::Write => write!(f, "write"), + AccessKind::Dealloc => write!(f, "deallocation"), + } + } +} + +/// A trait for the synchronization metadata that can be attached to a memory location. +pub trait SyncObj: Any { + /// Determines whether reads/writes to this object's location are currently permitted. + fn on_access<'tcx>(&self, _access_kind: AccessKind) -> InterpResult<'tcx> { + interp_ok(()) + } + + /// Determines whether this object's metadata shall be deleted when a write to its + /// location occurs. + fn delete_on_write(&self) -> bool { + false + } +} + +impl dyn SyncObj { + #[inline(always)] + pub fn downcast_ref(&self) -> Option<&T> { + let x: &dyn Any = self; + x.downcast_ref() + } +} + +impl fmt::Debug for dyn SyncObj { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SyncObj").finish_non_exhaustive() + } +} + /// The mutex state. #[derive(Default, Debug)] struct Mutex { @@ -37,6 +85,10 @@ impl MutexRef { pub fn owner(&self) -> Option { self.0.borrow().owner } + + pub fn queue_is_empty(&self) -> bool { + self.0.borrow().queue.is_empty() + } } impl VisitProvenance for MutexRef { @@ -113,6 +165,11 @@ impl RwLockRef { pub fn is_write_locked(&self) -> bool { self.0.borrow().is_write_locked() } + + pub fn queue_is_empty(&self) -> bool { + let inner = self.0.borrow(); + inner.reader_queue.is_empty() && inner.writer_queue.is_empty() + } } impl VisitProvenance for RwLockRef { @@ -140,8 +197,8 @@ impl CondvarRef { Self(Default::default()) } - pub fn is_awaited(&self) -> bool { - !self.0.borrow().waiters.is_empty() + pub fn queue_is_empty(&self) -> bool { + self.0.borrow().waiters.is_empty() } } @@ -214,127 +271,141 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { impl<'tcx> AllocExtra<'tcx> { fn get_sync(&self, offset: Size) -> Option<&T> { - self.sync.get(&offset).and_then(|s| s.downcast_ref::()) + self.sync_objs.get(&offset).and_then(|s| s.downcast_ref::()) } } -/// We designate an `init`` field in all primitives. -/// If `init` is set to this, we consider the primitive initialized. -pub const LAZY_INIT_COOKIE: u32 = 0xcafe_affe; - -// Public interface to synchronization primitives. Please note that in most +// Public interface to synchronization objects. Please note that in most // cases, the function calls are infallible and it is the client's (shim // implementation's) responsibility to detect and deal with erroneous // situations. impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - /// Helper for lazily initialized `alloc_extra.sync` data: - /// this forces an immediate init. - /// Return a reference to the data in the machine state. - fn lazy_sync_init<'a, T: 'static>( + /// Get the synchronization object associated with the given pointer, + /// or initialize a new one. + /// + /// Return `None` if this pointer does not point to at least 1 byte of mutable memory. + fn get_sync_or_init<'a, T: SyncObj>( &'a mut self, - primitive: &MPlaceTy<'tcx>, - init_offset: Size, - data: T, - ) -> InterpResult<'tcx, &'a T> + ptr: Pointer, + new: impl FnOnce(&'a mut MiriMachine<'tcx>) -> T, + ) -> Option<&'a T> where 'tcx: 'a, { let this = self.eval_context_mut(); + if !this.ptr_try_get_alloc_id(ptr, 0).ok().is_some_and(|(alloc_id, offset, ..)| { + let info = this.get_alloc_info(alloc_id); + info.kind == AllocKind::LiveData && info.mutbl.is_mut() && offset < info.size + }) { + return None; + } + // This cannot fail now. + let (alloc, offset, _) = this.ptr_get_alloc_id(ptr, 0).unwrap(); + let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc).unwrap(); + // Due to borrow checker reasons, we have to do the lookup twice. + if alloc_extra.get_sync::(offset).is_none() { + let new = new(machine); + alloc_extra.sync_objs.insert(offset, Box::new(new)); + } + Some(alloc_extra.get_sync::(offset).unwrap()) + } - let (alloc, offset, _) = this.ptr_get_alloc_id(primitive.ptr(), 0)?; - let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc)?; - alloc_extra.sync.insert(offset, Box::new(data)); - // Mark this as "initialized". - let init_field = primitive.offset(init_offset, this.machine.layouts.u32, this)?; - this.write_scalar_atomic( - Scalar::from_u32(LAZY_INIT_COOKIE), - &init_field, - AtomicWriteOrd::Relaxed, - )?; - interp_ok(this.get_alloc_extra(alloc)?.get_sync::(offset).unwrap()) - } - - /// Helper for lazily initialized `alloc_extra.sync` data: - /// Checks if the primitive is initialized: - /// - If yes, fetches the data from `alloc_extra.sync`, or calls `missing_data` if that fails - /// and stores that in `alloc_extra.sync`. - /// - Otherwise, calls `new_data` to initialize the primitive. + /// Helper for "immovable" synchronization objects: the expected protocol for these objects is + /// that they use a static initializer of `uninit_val`, and we set them to `init_val` upon + /// initialization. At that point we also register a synchronization object, which is expected + /// to have `delete_on_write() == true`. So in the future, if we still see the object, we know + /// the location must still contain `init_val`. If the object is copied somewhere, that will + /// show up as a non-`init_val` value without a synchronization object, which we can then use to + /// error. /// - /// Return a reference to the data in the machine state. - fn lazy_sync_get_data<'a, T: 'static>( + /// `new_meta_obj` gets invoked when there is not yet an initialization object. + /// It has to ensure that the in-memory representation indeed matches `uninit_val`. + /// + /// The point of storing an `init_val` is so that if this memory gets copied somewhere else, + /// it does not look like the static initializer (i.e., `uninit_val`) any more. For some + /// objects we could just entirely forbid reading their bytes to ensure they don't get copied, + /// but that does not work for objects without a destructor (Windows `InitOnce`, macOS + /// `os_unfair_lock`). + fn get_immovable_sync_with_static_init<'a, T: SyncObj>( &'a mut self, - primitive: &MPlaceTy<'tcx>, + obj: &MPlaceTy<'tcx>, init_offset: Size, - missing_data: impl FnOnce() -> InterpResult<'tcx, T>, - new_data: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>, + uninit_val: u8, + init_val: u8, + new_meta_obj: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>, ) -> InterpResult<'tcx, &'a T> where 'tcx: 'a, { + assert!(init_val != uninit_val); let this = self.eval_context_mut(); + this.check_ptr_access(obj.ptr(), obj.layout.size, CheckInAllocMsg::Dereferenceable)?; + assert!(init_offset < obj.layout.size); // ensure our 1-byte flag fits + let init_field = obj.offset(init_offset, this.machine.layouts.u8, this)?; + + let (alloc, offset, _) = this.ptr_get_alloc_id(init_field.ptr(), 0)?; + let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc)?; + // Due to borrow checker reasons, we have to do the lookup twice. + if alloc_extra.get_sync::(offset).is_some() { + let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc).unwrap(); + return interp_ok(alloc_extra.get_sync::(offset).unwrap()); + } - // Check if this is already initialized. Needs to be atomic because we can race with another - // thread initializing. Needs to be an RMW operation to ensure we read the *latest* value. - // So we just try to replace MUTEX_INIT_COOKIE with itself. - let init_cookie = Scalar::from_u32(LAZY_INIT_COOKIE); - let init_field = primitive.offset(init_offset, this.machine.layouts.u32, this)?; - let (_init, success) = this + // There's no sync object there yet. Create one, and try a CAS for uninit_val to init_val. + let meta_obj = new_meta_obj(this)?; + let (old_init, success) = this .atomic_compare_exchange_scalar( &init_field, - &ImmTy::from_scalar(init_cookie, this.machine.layouts.u32), - init_cookie, + &ImmTy::from_scalar(Scalar::from_u8(uninit_val), this.machine.layouts.u8), + Scalar::from_u8(init_val), AtomicRwOrd::Relaxed, AtomicReadOrd::Relaxed, /* can_fail_spuriously */ false, )? .to_scalar_pair(); - - if success.to_bool()? { - // If it is initialized, it must be found in the "sync primitive" table, - // or else it has been moved illegally. - let (alloc, offset, _) = this.ptr_get_alloc_id(primitive.ptr(), 0)?; - let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc)?; - // Due to borrow checker reasons, we have to do the lookup twice. - if alloc_extra.get_sync::(offset).is_none() { - let data = missing_data()?; - alloc_extra.sync.insert(offset, Box::new(data)); - } - interp_ok(alloc_extra.get_sync::(offset).unwrap()) - } else { - let data = new_data(this)?; - this.lazy_sync_init(primitive, init_offset, data) + if !success.to_bool()? { + // This can happen for the macOS lock if it is already marked as initialized. + assert_eq!( + old_init.to_u8()?, + init_val, + "`new_meta_obj` should have ensured that this CAS succeeds" + ); } + + let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc).unwrap(); + assert!(meta_obj.delete_on_write()); + alloc_extra.sync_objs.insert(offset, Box::new(meta_obj)); + interp_ok(alloc_extra.get_sync::(offset).unwrap()) } - /// Get the synchronization primitive associated with the given pointer, - /// or initialize a new one. - /// - /// Return `None` if this pointer does not point to at least 1 byte of mutable memory. - fn get_sync_or_init<'a, T: 'static>( + /// Explicitly initializes an object that would usually be implicitly initialized with + /// `get_immovable_sync_with_static_init`. + fn init_immovable_sync<'a, T: SyncObj>( &'a mut self, - ptr: Pointer, - new: impl FnOnce(&'a mut MiriMachine<'tcx>) -> T, - ) -> Option<&'a T> + obj: &MPlaceTy<'tcx>, + init_offset: Size, + init_val: u8, + new_meta_obj: T, + ) -> InterpResult<'tcx, Option<&'a T>> where 'tcx: 'a, { let this = self.eval_context_mut(); - if !this.ptr_try_get_alloc_id(ptr, 0).ok().is_some_and(|(alloc_id, offset, ..)| { - let info = this.get_alloc_info(alloc_id); - info.kind == AllocKind::LiveData && info.mutbl.is_mut() && offset < info.size - }) { - return None; - } - // This cannot fail now. - let (alloc, offset, _) = this.ptr_get_alloc_id(ptr, 0).unwrap(); - let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc).unwrap(); - // Due to borrow checker reasons, we have to do the lookup twice. - if alloc_extra.get_sync::(offset).is_none() { - let new = new(machine); - alloc_extra.sync.insert(offset, Box::new(new)); - } - Some(alloc_extra.get_sync::(offset).unwrap()) + this.check_ptr_access(obj.ptr(), obj.layout.size, CheckInAllocMsg::Dereferenceable)?; + assert!(init_offset < obj.layout.size); // ensure our 1-byte flag fits + let init_field = obj.offset(init_offset, this.machine.layouts.u8, this)?; + + // Zero the entire object, and then store `init_val` directly. + this.write_bytes_ptr(obj.ptr(), iter::repeat_n(0, obj.layout.size.bytes_usize()))?; + this.write_scalar(Scalar::from_u8(init_val), &init_field)?; + + // Create meta-level initialization object. + let (alloc, offset, _) = this.ptr_get_alloc_id(init_field.ptr(), 0)?; + let (alloc_extra, _machine) = this.get_alloc_extra_mut(alloc).unwrap(); + assert!(new_meta_obj.delete_on_write()); + alloc_extra.sync_objs.insert(offset, Box::new(new_meta_obj)); + interp_ok(Some(alloc_extra.get_sync::(offset).unwrap())) } /// Lock by setting the mutex owner and increasing the lock count. diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index d0cfb9c805e15..2ddb3ff49d85e 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -128,7 +128,7 @@ pub enum NonHaltingDiagnostic { PoppedPointerTag(Item, String), TrackingAlloc(AllocId, Size, Align), FreedAlloc(AllocId), - AccessedAlloc(AllocId, AllocRange, AccessKind), + AccessedAlloc(AllocId, AllocRange, borrow_tracker::AccessKind), RejectedIsolatedOp(String), ProgressReport { block_count: u64, // how many basic blocks have been run so far diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 7e1fdfa8cdf26..18e16ddf1a5da 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -22,13 +22,6 @@ use rustc_symbol_mangling::mangle_internal_symbol; use crate::*; -/// Indicates which kind of access is being performed. -#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] -pub enum AccessKind { - Read, - Write, -} - /// Gets an instance for a path. /// /// A `None` namespace indicates we are looking for a module. diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index b756fbb901bc6..4a48672660ae1 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -139,7 +139,7 @@ pub use crate::diagnostics::{ EvalContextExt as _, NonHaltingDiagnostic, TerminationInfo, report_error, }; pub use crate::eval::{MiriConfig, MiriEntryFnType, create_ecx, eval_entry}; -pub use crate::helpers::{AccessKind, EvalContextExt as _, ToU64 as _, ToUsize as _}; +pub use crate::helpers::{EvalContextExt as _, ToU64 as _, ToUsize as _}; pub use crate::intrinsics::EvalContextExt as _; pub use crate::machine::{ AlignmentCheck, AllocExtra, BacktraceStyle, DynMachineCallback, FloatRoundingErrorMode, @@ -165,6 +165,7 @@ pub use crate::shims::unwind::{CatchUnwindData, EvalContextExt as _}; /// Also disable the MIR pass that inserts an alignment check on every pointer dereference. Miri /// does that too, and with a better error message. pub const MIRI_DEFAULT_ARGS: &[&str] = &[ + "-Zcodegen-backend=dummy", "--cfg=miri", "-Zalways-encode-mir", "-Zextra-const-ub-checks", diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 3bbad01207dbc..304ae00b01a92 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1,9 +1,9 @@ //! Global machine state as well as implementation of the interpreter engine //! `Machine` trait. -use std::any::Any; use std::borrow::Cow; use std::cell::{Cell, RefCell}; +use std::collections::BTreeMap; use std::path::Path; use std::rc::Rc; use std::{fmt, process}; @@ -36,6 +36,7 @@ use rustc_target::spec::Arch; use crate::alloc_addresses::EvalContextExt; use crate::concurrency::cpu_affinity::{self, CpuAffinityMask}; use crate::concurrency::data_race::{self, NaReadType, NaWriteType}; +use crate::concurrency::sync::SyncObj; use crate::concurrency::{ AllocDataRaceHandler, GenmcCtx, GenmcEvalContextExt as _, GlobalDataRaceHandler, weak_memory, }; @@ -399,11 +400,11 @@ pub struct AllocExtra<'tcx> { /// if this allocation is leakable. The backtrace is not /// pruned yet; that should be done before printing it. pub backtrace: Option>>, - /// Synchronization primitives like to attach extra data to particular addresses. We store that + /// Synchronization objects like to attach extra data to particular addresses. We store that /// inside the relevant allocation, to ensure that everything is removed when the allocation is /// freed. /// This maps offsets to synchronization-primitive-specific data. - pub sync: FxHashMap>, + pub sync_objs: BTreeMap>, } // We need a `Clone` impl because the machine passes `Allocation` through `Cow`... @@ -416,7 +417,7 @@ impl<'tcx> Clone for AllocExtra<'tcx> { impl VisitProvenance for AllocExtra<'_> { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { - let AllocExtra { borrow_tracker, data_race, backtrace: _, sync: _ } = self; + let AllocExtra { borrow_tracker, data_race, backtrace: _, sync_objs: _ } = self; borrow_tracker.visit_provenance(visit); data_race.visit_provenance(visit); @@ -991,7 +992,12 @@ impl<'tcx> MiriMachine<'tcx> { .insert(id, (ecx.machine.current_user_relevant_span(), None)); } - interp_ok(AllocExtra { borrow_tracker, data_race, backtrace, sync: FxHashMap::default() }) + interp_ok(AllocExtra { + borrow_tracker, + data_race, + backtrace, + sync_objs: BTreeMap::default(), + }) } } @@ -1516,7 +1522,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { machine.emit_diagnostic(NonHaltingDiagnostic::AccessedAlloc( alloc_id, range, - AccessKind::Read, + borrow_tracker::AccessKind::Read, )); } // 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> { if let Some(borrow_tracker) = &alloc_extra.borrow_tracker { borrow_tracker.before_memory_read(alloc_id, prov_extra, range, machine)?; } + // Check if there are any sync objects that would like to prevent reading this memory. + for (_offset, obj) in alloc_extra.sync_objs.range(range.start..range.end()) { + obj.on_access(concurrency::sync::AccessKind::Read)?; + } + interp_ok(()) } @@ -1552,7 +1563,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { machine.emit_diagnostic(NonHaltingDiagnostic::AccessedAlloc( alloc_id, range, - AccessKind::Write, + borrow_tracker::AccessKind::Write, )); } match &machine.data_race { @@ -1576,6 +1587,20 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker { borrow_tracker.before_memory_write(alloc_id, prov_extra, range, machine)?; } + // Delete sync objects that don't like writes. + // Most of the time, we can just skip this. + if !alloc_extra.sync_objs.is_empty() { + let mut to_delete = vec![]; + for (offset, obj) in alloc_extra.sync_objs.range(range.start..range.end()) { + obj.on_access(concurrency::sync::AccessKind::Write)?; + if obj.delete_on_write() { + to_delete.push(*offset); + } + } + for offset in to_delete { + alloc_extra.sync_objs.remove(&offset); + } + } interp_ok(()) } @@ -1612,6 +1637,11 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker { borrow_tracker.before_memory_deallocation(alloc_id, prove_extra, size, machine)?; } + // Check if there are any sync objects that would like to prevent freeing this memory. + for obj in alloc_extra.sync_objs.values() { + obj.on_access(concurrency::sync::AccessKind::Dealloc)?; + } + if let Some((_, deallocated_at)) = machine.allocation_spans.borrow_mut().get_mut(&alloc_id) { *deallocated_at = Some(machine.current_user_relevant_span()); diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index a92d8f87af818..bffe633f77979 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -800,10 +800,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Target-specific shims name if name.starts_with("llvm.x86.") - && matches!( - this.tcx.sess.target.arch, - Arch::X86 | Arch::X86_64 - ) => + && matches!(this.tcx.sess.target.arch, Arch::X86 | Arch::X86_64) => { return shims::x86::EvalContextExt::emulate_x86_intrinsic( this, link_name, abi, args, dest, diff --git a/src/tools/miri/src/shims/unix/freebsd/sync.rs b/src/tools/miri/src/shims/unix/freebsd/sync.rs index 13d30e05573af..bd1ee31553727 100644 --- a/src/tools/miri/src/shims/unix/freebsd/sync.rs +++ b/src/tools/miri/src/shims/unix/freebsd/sync.rs @@ -4,13 +4,15 @@ use core::time::Duration; use rustc_abi::FieldIdx; -use crate::concurrency::sync::FutexRef; +use crate::concurrency::sync::{FutexRef, SyncObj}; use crate::*; pub struct FreeBsdFutex { futex: FutexRef, } +impl SyncObj for FreeBsdFutex {} + /// Extended variant of the `timespec` struct. pub struct UmtxTime { timeout: Duration, diff --git a/src/tools/miri/src/shims/unix/linux_like/sync.rs b/src/tools/miri/src/shims/unix/linux_like/sync.rs index 5f032c52deeb7..8ff7fe0a4563b 100644 --- a/src/tools/miri/src/shims/unix/linux_like/sync.rs +++ b/src/tools/miri/src/shims/unix/linux_like/sync.rs @@ -1,4 +1,4 @@ -use crate::concurrency::sync::FutexRef; +use crate::concurrency::sync::{FutexRef, SyncObj}; use crate::shims::sig::check_min_vararg_count; use crate::*; @@ -6,6 +6,8 @@ struct LinuxFutex { futex: FutexRef, } +impl SyncObj for LinuxFutex {} + /// Implementation of the SYS_futex syscall. /// `args` is the arguments *including* the syscall number. pub fn futex<'tcx>( diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index c4ddff7805ed2..d69d373b572bd 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -13,15 +13,32 @@ use std::cell::Cell; use std::time::Duration; -use rustc_abi::Size; +use rustc_abi::{Endian, FieldIdx, Size}; -use crate::concurrency::sync::FutexRef; +use crate::concurrency::sync::{AccessKind, FutexRef, SyncObj}; use crate::*; #[derive(Clone)] enum MacOsUnfairLock { - Poisoned, Active { mutex_ref: MutexRef }, + PermanentlyLocked, +} + +impl SyncObj for MacOsUnfairLock { + fn on_access<'tcx>(&self, access_kind: AccessKind) -> InterpResult<'tcx> { + if let MacOsUnfairLock::Active { mutex_ref } = self + && !mutex_ref.queue_is_empty() + { + throw_ub_format!( + "{access_kind} of `os_unfair_lock` is forbidden while the queue is non-empty" + ); + } + interp_ok(()) + } + + fn delete_on_write(&self) -> bool { + true + } } pub enum MacOsFutexTimeout<'a, 'tcx> { @@ -44,6 +61,8 @@ struct MacOsFutex { shared: Cell, } +impl SyncObj for MacOsFutex {} + impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { fn os_unfair_lock_get_data<'a>( @@ -53,22 +72,35 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { where 'tcx: 'a, { + // `os_unfair_lock_s` wraps a single `u32` field. We use the first byte to store the "init" + // flag. Due to macOS always being little endian, that's the least significant byte. let this = self.eval_context_mut(); + assert!(this.tcx.data_layout.endian == Endian::Little); + let lock = this.deref_pointer_as(lock_ptr, this.libc_ty_layout("os_unfair_lock_s"))?; - this.lazy_sync_get_data( + this.get_immovable_sync_with_static_init( &lock, Size::ZERO, // offset for init tracking - || { - // If we get here, due to how we reset things to zero in `os_unfair_lock_unlock`, - // this means the lock was moved while locked. This can happen with a `std` lock, - // but then any future attempt to unlock will just deadlock. In practice, terrible - // things can probably happen if you swap two locked locks, since they'd wake up - // from the wrong queue... we just won't catch all UB of this library API then (we - // would need to store some unique identifer in-memory for this, instead of a static - // LAZY_INIT_COOKIE). This can't be hit via `std::sync::Mutex`. - interp_ok(MacOsUnfairLock::Poisoned) + /* uninit_val */ 0, + /* init_val */ 1, + |this| { + let field = this.project_field(&lock, FieldIdx::from_u32(0))?; + let val = this.read_scalar(&field)?.to_u32()?; + if val == 0 { + interp_ok(MacOsUnfairLock::Active { mutex_ref: MutexRef::new() }) + } else if val == 1 { + // This is a lock that got copied while it is initialized. We de-initialize + // locks when they get released, so it got copied while locked. Unfortunately + // that is something `std` needs to support (the guard could have been leaked). + // On the plus side, we know nobody was queued for the lock while it got copied; + // that would have been rejected by our `on_access`. So we behave like a + // futex-based lock would in this case: any attempt to acquire the lock will + // just wait forever, since there's nobody to wake us up. + interp_ok(MacOsUnfairLock::PermanentlyLocked) + } else { + throw_ub_format!("`os_unfair_lock` was not properly initialized at this location, or it got overwritten"); + } }, - |_| interp_ok(MacOsUnfairLock::Active { mutex_ref: MutexRef::new() }), ) } } @@ -332,7 +364,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let MacOsUnfairLock::Active { mutex_ref } = this.os_unfair_lock_get_data(lock_op)? else { - // The lock is poisoned, who knows who owns it... we'll pretend: someone else. + // A perma-locked lock is definitely not held by us. throw_machine_stop!(TerminationInfo::Abort( "attempted to unlock an os_unfair_lock not owned by the current thread".to_owned() )); @@ -361,7 +393,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let MacOsUnfairLock::Active { mutex_ref } = this.os_unfair_lock_get_data(lock_op)? else { - // The lock is poisoned, who knows who owns it... we'll pretend: someone else. + // A perma-locked lock is definitely not held by us. throw_machine_stop!(TerminationInfo::Abort( "called os_unfair_lock_assert_owner on an os_unfair_lock not owned by the current thread".to_owned() )); @@ -383,7 +415,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let MacOsUnfairLock::Active { mutex_ref } = this.os_unfair_lock_get_data(lock_op)? else { - // The lock is poisoned, who knows who owns it... we'll pretend: someone else. + // A perma-locked lock is definitely not held by us. return interp_ok(()); }; let mutex_ref = mutex_ref.clone(); diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index a712279d57628..57dbe2cd333b1 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -1,13 +1,11 @@ use rustc_abi::Size; -use crate::concurrency::sync::LAZY_INIT_COOKIE; +use crate::concurrency::sync::{AccessKind, SyncObj}; use crate::*; -/// Do a bytewise comparison of the two places, using relaxed atomic reads. This is used to check if +/// Do a bytewise comparison of the two places. This is used to check if /// a synchronization primitive matches its static initializer value. -/// -/// The reads happen in chunks of 4, so all racing accesses must also use that access size. -fn bytewise_equal_atomic_relaxed<'tcx>( +fn bytewise_equal<'tcx>( ecx: &MiriInterpCx<'tcx>, left: &MPlaceTy<'tcx>, right: &MPlaceTy<'tcx>, @@ -15,25 +13,16 @@ fn bytewise_equal_atomic_relaxed<'tcx>( let size = left.layout.size; assert_eq!(size, right.layout.size); - // We do this in chunks of 4, so that we are okay to race with (sufficiently aligned) - // 4-byte atomic accesses. - assert!(size.bytes().is_multiple_of(4)); - for i in 0..(size.bytes() / 4) { - let offset = Size::from_bytes(i.strict_mul(4)); - let load = |place: &MPlaceTy<'tcx>| { - let byte = place.offset(offset, ecx.machine.layouts.u32, ecx)?; - ecx.read_scalar_atomic(&byte, AtomicReadOrd::Relaxed)?.to_u32() - }; - let left = load(left)?; - let right = load(right)?; - if left != right { - return interp_ok(false); - } - } + let left_bytes = ecx.read_bytes_ptr_strip_provenance(left.ptr(), size)?; + let right_bytes = ecx.read_bytes_ptr_strip_provenance(right.ptr(), size)?; - interp_ok(true) + interp_ok(left_bytes == right_bytes) } +// The in-memory marker values we use to indicate whether objects have been initialized. +const PTHREAD_UNINIT: u8 = 0; +const PTHREAD_INIT: u8 = 1; + // # pthread_mutexattr_t // We store some data directly inside the type, ignoring the platform layout: // - kind: i32 @@ -103,7 +92,7 @@ fn mutexattr_translate_kind<'tcx>( // # pthread_mutex_t // We store some data directly inside the type, ignoring the platform layout: -// - init: u32 +// - init: u8 /// The mutex kind. #[derive(Debug, Clone, Copy)] @@ -120,6 +109,21 @@ struct PthreadMutex { kind: MutexKind, } +impl SyncObj for PthreadMutex { + fn on_access<'tcx>(&self, access_kind: AccessKind) -> InterpResult<'tcx> { + if !self.mutex_ref.queue_is_empty() { + throw_ub_format!( + "{access_kind} of `pthread_mutex_t` is forbidden while the queue is non-empty" + ); + } + interp_ok(()) + } + + fn delete_on_write(&self) -> bool { + true + } +} + /// To ensure an initialized mutex that was moved somewhere else can be distinguished from /// a statically initialized mutex that is used the first time, we pick some offset within /// `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> let check_static_initializer = |name| { let static_initializer = ecx.eval_path(&["libc", name]); let init_field = - static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap(); - let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap(); - assert_ne!( - init, LAZY_INIT_COOKIE, - "{name} is incompatible with our initialization cookie" + static_initializer.offset(offset, ecx.machine.layouts.u8, ecx).unwrap(); + let init = ecx.read_scalar(&init_field).unwrap().to_u8().unwrap(); + assert_eq!( + init, PTHREAD_UNINIT, + "{name} is incompatible with our initialization logic" ); }; @@ -172,7 +176,7 @@ fn mutex_create<'tcx>( ) -> InterpResult<'tcx, PthreadMutex> { let mutex = ecx.deref_pointer_as(mutex_ptr, ecx.libc_ty_layout("pthread_mutex_t"))?; let data = PthreadMutex { mutex_ref: MutexRef::new(), kind }; - ecx.lazy_sync_init(&mutex, mutex_init_offset(ecx)?, data.clone())?; + ecx.init_immovable_sync(&mutex, mutex_init_offset(ecx)?, PTHREAD_INIT, data.clone())?; interp_ok(data) } @@ -186,10 +190,11 @@ where 'tcx: 'a, { let mutex = ecx.deref_pointer_as(mutex_ptr, ecx.libc_ty_layout("pthread_mutex_t"))?; - ecx.lazy_sync_get_data( + ecx.get_immovable_sync_with_static_init( &mutex, mutex_init_offset(ecx)?, - || throw_ub_format!("`pthread_mutex_t` can't be moved after first use"), + PTHREAD_UNINIT, + PTHREAD_INIT, |ecx| { let kind = mutex_kind_from_static_initializer(ecx, &mutex)?; interp_ok(PthreadMutex { mutex_ref: MutexRef::new(), kind }) @@ -203,8 +208,7 @@ fn mutex_kind_from_static_initializer<'tcx>( mutex: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, MutexKind> { // All the static initializers recognized here *must* be checked in `mutex_init_offset`! - let is_initializer = - |name| bytewise_equal_atomic_relaxed(ecx, mutex, &ecx.eval_path(&["libc", name])); + let is_initializer = |name| bytewise_equal(ecx, mutex, &ecx.eval_path(&["libc", name])); // PTHREAD_MUTEX_INITIALIZER is recognized on all targets. if is_initializer("PTHREAD_MUTEX_INITIALIZER")? { @@ -220,18 +224,35 @@ fn mutex_kind_from_static_initializer<'tcx>( }, _ => {} } - throw_unsup_format!("unsupported static initializer used for `pthread_mutex_t`"); + throw_ub_format!( + "`pthread_mutex_t` was not properly initialized at this location, or it got overwritten" + ); } // # pthread_rwlock_t // We store some data directly inside the type, ignoring the platform layout: -// - init: u32 +// - init: u8 #[derive(Debug, Clone)] struct PthreadRwLock { rwlock_ref: RwLockRef, } +impl SyncObj for PthreadRwLock { + fn on_access<'tcx>(&self, access_kind: AccessKind) -> InterpResult<'tcx> { + if !self.rwlock_ref.queue_is_empty() { + throw_ub_format!( + "{access_kind} of `pthread_rwlock_t` is forbidden while the queue is non-empty" + ); + } + interp_ok(()) + } + + fn delete_on_write(&self) -> bool { + true + } +} + fn rwlock_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> { let offset = match &*ecx.tcx.sess.target.os { "linux" | "illumos" | "solaris" | "freebsd" | "android" => 0, @@ -245,11 +266,11 @@ fn rwlock_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size // the `init` field must start out not equal to LAZY_INIT_COOKIE. if !ecx.machine.pthread_rwlock_sanity.replace(true) { let static_initializer = ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]); - let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap(); - let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap(); - assert_ne!( - init, LAZY_INIT_COOKIE, - "PTHREAD_RWLOCK_INITIALIZER is incompatible with our initialization cookie" + let init_field = static_initializer.offset(offset, ecx.machine.layouts.u8, ecx).unwrap(); + let init = ecx.read_scalar(&init_field).unwrap().to_u8().unwrap(); + assert_eq!( + init, PTHREAD_UNINIT, + "PTHREAD_RWLOCK_INITIALIZER is incompatible with our initialization logic" ); } @@ -264,17 +285,20 @@ where 'tcx: 'a, { let rwlock = ecx.deref_pointer_as(rwlock_ptr, ecx.libc_ty_layout("pthread_rwlock_t"))?; - ecx.lazy_sync_get_data( + ecx.get_immovable_sync_with_static_init( &rwlock, rwlock_init_offset(ecx)?, - || throw_ub_format!("`pthread_rwlock_t` can't be moved after first use"), + PTHREAD_UNINIT, + PTHREAD_INIT, |ecx| { - if !bytewise_equal_atomic_relaxed( + if !bytewise_equal( ecx, &rwlock, &ecx.eval_path(&["libc", "PTHREAD_RWLOCK_INITIALIZER"]), )? { - throw_unsup_format!("unsupported static initializer used for `pthread_rwlock_t`"); + throw_ub_format!( + "`pthread_rwlock_t` was not properly initialized at this location, or it got overwritten" + ); } interp_ok(PthreadRwLock { rwlock_ref: RwLockRef::new() }) }, @@ -322,7 +346,7 @@ fn condattr_set_clock_id<'tcx>( // # pthread_cond_t // We store some data directly inside the type, ignoring the platform layout: -// - init: u32 +// - init: u8 fn cond_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> { let offset = match &*ecx.tcx.sess.target.os { @@ -337,11 +361,11 @@ fn cond_init_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, Size> // the `init` field must start out not equal to LAZY_INIT_COOKIE. if !ecx.machine.pthread_condvar_sanity.replace(true) { let static_initializer = ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]); - let init_field = static_initializer.offset(offset, ecx.machine.layouts.u32, ecx).unwrap(); - let init = ecx.read_scalar(&init_field).unwrap().to_u32().unwrap(); - assert_ne!( - init, LAZY_INIT_COOKIE, - "PTHREAD_COND_INITIALIZER is incompatible with our initialization cookie" + let init_field = static_initializer.offset(offset, ecx.machine.layouts.u8, ecx).unwrap(); + let init = ecx.read_scalar(&init_field).unwrap().to_u8().unwrap(); + assert_eq!( + init, PTHREAD_UNINIT, + "PTHREAD_COND_INITIALIZER is incompatible with our initialization logic" ); } @@ -354,6 +378,21 @@ struct PthreadCondvar { clock: TimeoutClock, } +impl SyncObj for PthreadCondvar { + fn on_access<'tcx>(&self, access_kind: AccessKind) -> InterpResult<'tcx> { + if !self.condvar_ref.queue_is_empty() { + throw_ub_format!( + "{access_kind} of `pthread_cond_t` is forbidden while the queue is non-empty" + ); + } + interp_ok(()) + } + + fn delete_on_write(&self) -> bool { + true + } +} + fn cond_create<'tcx>( ecx: &mut MiriInterpCx<'tcx>, cond_ptr: &OpTy<'tcx>, @@ -361,7 +400,7 @@ fn cond_create<'tcx>( ) -> InterpResult<'tcx, PthreadCondvar> { let cond = ecx.deref_pointer_as(cond_ptr, ecx.libc_ty_layout("pthread_cond_t"))?; let data = PthreadCondvar { condvar_ref: CondvarRef::new(), clock }; - ecx.lazy_sync_init(&cond, cond_init_offset(ecx)?, data.clone())?; + ecx.init_immovable_sync(&cond, cond_init_offset(ecx)?, PTHREAD_INIT, data.clone())?; interp_ok(data) } @@ -373,17 +412,20 @@ where 'tcx: 'a, { let cond = ecx.deref_pointer_as(cond_ptr, ecx.libc_ty_layout("pthread_cond_t"))?; - ecx.lazy_sync_get_data( + ecx.get_immovable_sync_with_static_init( &cond, cond_init_offset(ecx)?, - || throw_ub_format!("`pthread_cond_t` can't be moved after first use"), + PTHREAD_UNINIT, + PTHREAD_INIT, |ecx| { - if !bytewise_equal_atomic_relaxed( + if !bytewise_equal( ecx, &cond, &ecx.eval_path(&["libc", "PTHREAD_COND_INITIALIZER"]), )? { - throw_unsup_format!("unsupported static initializer used for `pthread_cond_t`"); + throw_ub_format!( + "`pthread_cond_t` was not properly initialized at this location, or it got overwritten" + ); } // This used the static initializer. The clock there is always CLOCK_REALTIME. interp_ok(PthreadCondvar { @@ -575,11 +617,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_ub_format!("destroyed a locked mutex"); } + // This write also deletes the interpreter state for this mutex. // This might lead to false positives, see comment in pthread_mutexattr_destroy - this.write_uninit( - &this.deref_pointer_as(mutex_op, this.libc_ty_layout("pthread_mutex_t"))?, - )?; - // FIXME: delete interpreter state associated with this mutex. + let mutex_place = + this.deref_pointer_as(mutex_op, this.libc_ty_layout("pthread_mutex_t"))?; + this.write_uninit(&mutex_place)?; interp_ok(()) } @@ -693,11 +735,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_ub_format!("destroyed a locked rwlock"); } + // This write also deletes the interpreter state for this rwlock. // This might lead to false positives, see comment in pthread_mutexattr_destroy - this.write_uninit( - &this.deref_pointer_as(rwlock_op, this.libc_ty_layout("pthread_rwlock_t"))?, - )?; - // FIXME: delete interpreter state associated with this rwlock. + let rwlock_place = + this.deref_pointer_as(rwlock_op, this.libc_ty_layout("pthread_rwlock_t"))?; + this.write_uninit(&rwlock_place)?; interp_ok(()) } @@ -885,13 +927,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Reading the field also has the side-effect that we detect double-`destroy` // since we make the field uninit below. let condvar = &cond_get_data(this, cond_op)?.condvar_ref; - if condvar.is_awaited() { + if !condvar.queue_is_empty() { throw_ub_format!("destroying an awaited conditional variable"); } + // This write also deletes the interpreter state for this mutex. // This might lead to false positives, see comment in pthread_mutexattr_destroy - this.write_uninit(&this.deref_pointer_as(cond_op, this.libc_ty_layout("pthread_cond_t"))?)?; - // FIXME: delete interpreter state associated with this condvar. + let cond_place = this.deref_pointer_as(cond_op, this.libc_ty_layout("pthread_cond_t"))?; + this.write_uninit(&cond_place)?; interp_ok(()) } diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index a893999ef8e52..db1860bdfd309 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -1,9 +1,9 @@ use std::time::Duration; -use rustc_abi::Size; +use rustc_abi::{FieldIdx, Size}; use crate::concurrency::init_once::{EvalContextExt as _, InitOnceStatus}; -use crate::concurrency::sync::FutexRef; +use crate::concurrency::sync::{AccessKind, FutexRef, SyncObj}; use crate::*; #[derive(Clone)] @@ -11,14 +11,31 @@ struct WindowsInitOnce { init_once: InitOnceRef, } +impl SyncObj for WindowsInitOnce { + fn on_access<'tcx>(&self, access_kind: AccessKind) -> InterpResult<'tcx> { + if !self.init_once.queue_is_empty() { + throw_ub_format!( + "{access_kind} of `INIT_ONCE` is forbidden while the queue is non-empty" + ); + } + interp_ok(()) + } + + fn delete_on_write(&self) -> bool { + true + } +} + struct WindowsFutex { futex: FutexRef, } +impl SyncObj for WindowsFutex {} + impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Windows sync primitives are pointer sized. - // We only use the first 4 bytes for the id. + // We only use the first byte for the "init" flag. fn init_once_get_data<'a>( &'a mut self, @@ -33,13 +50,19 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.deref_pointer_as(init_once_ptr, this.windows_ty_layout("INIT_ONCE"))?; let init_offset = Size::ZERO; - this.lazy_sync_get_data( + this.get_immovable_sync_with_static_init( &init_once, init_offset, - || throw_ub_format!("`INIT_ONCE` can't be moved after first use"), - |_| { - // TODO: check that this is still all-zero. - interp_ok(WindowsInitOnce { init_once: InitOnceRef::new() }) + /* uninit_val */ 0, + /* init_val */ 1, + |this| { + let ptr_field = this.project_field(&init_once, FieldIdx::from_u32(0))?; + let val = this.read_target_usize(&ptr_field)?; + if val == 0 { + interp_ok(WindowsInitOnce { init_once: InitOnceRef::new() }) + } else { + throw_ub_format!("`INIT_ONCE` was not properly initialized at this location, or it got overwritten"); + } }, ) } diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs index ec365aa1b45e4..636d308d78d98 100644 --- a/src/tools/miri/src/shims/x86/avx.rs +++ b/src/tools/miri/src/shims/x86/avx.rs @@ -1,14 +1,12 @@ use rustc_abi::CanonAbi; use rustc_apfloat::ieee::{Double, Single}; -use rustc_middle::mir; use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; use super::{ FloatBinOp, FloatUnaryOp, bin_op_simd_float_all, conditional_dot_product, convert_float_to_int, - horizontal_bin_op, mask_load, mask_store, round_all, test_bits_masked, test_high_bits_masked, - unary_op_ps, + mask_load, mask_store, round_all, test_bits_masked, test_high_bits_masked, unary_op_ps, }; use crate::*; @@ -93,21 +91,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { conditional_dot_product(this, left, right, imm, dest)?; } - // Used to implement the _mm256_h{add,sub}_p{s,d} functions. - // Horizontally add/subtract adjacent floating point values - // in `left` and `right`. - "hadd.ps.256" | "hadd.pd.256" | "hsub.ps.256" | "hsub.pd.256" => { - let [left, right] = - this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; - - let which = match unprefixed_name { - "hadd.ps.256" | "hadd.pd.256" => mir::BinOp::Add, - "hsub.ps.256" | "hsub.pd.256" => mir::BinOp::Sub, - _ => unreachable!(), - }; - - horizontal_bin_op(this, which, /*saturating*/ false, left, right, dest)?; - } // Used to implement the _mm256_cmp_ps function. // Performs a comparison operation on each component of `left` // and `right`. For each component, returns 0 if false or u32::MAX @@ -251,40 +234,31 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Unaligned copy, which is what we want. this.mem_copy(src_ptr, dest.ptr(), dest.layout.size, /*nonoverlapping*/ true)?; } - // Used to implement the _mm256_testz_si256, _mm256_testc_si256 and - // _mm256_testnzc_si256 functions. - // Tests `op & mask == 0`, `op & mask == mask` or - // `op & mask != 0 && op & mask != mask` - "ptestz.256" | "ptestc.256" | "ptestnzc.256" => { + // Used to implement the _mm256_testnzc_si256 function. + // Tests `op & mask != 0 && op & mask != mask` + "ptestnzc.256" => { let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (all_zero, masked_set) = test_bits_masked(this, op, mask)?; - let res = match unprefixed_name { - "ptestz.256" => all_zero, - "ptestc.256" => masked_set, - "ptestnzc.256" => !all_zero && !masked_set, - _ => unreachable!(), - }; + let res = !all_zero && !masked_set; this.write_scalar(Scalar::from_i32(res.into()), dest)?; } // Used to implement the _mm256_testz_pd, _mm256_testc_pd, _mm256_testnzc_pd - // _mm_testz_pd, _mm_testc_pd, _mm_testnzc_pd, _mm256_testz_ps, - // _mm256_testc_ps, _mm256_testnzc_ps, _mm_testz_ps, _mm_testc_ps and + // _mm_testnzc_pd, _mm256_testz_ps, _mm256_testc_ps, _mm256_testnzc_ps and // _mm_testnzc_ps functions. // Calculates two booleans: // `direct`, which is true when the highest bit of each element of `op & mask` is zero. // `negated`, which is true when the highest bit of each element of `!op & mask` is zero. // Return `direct` (testz), `negated` (testc) or `!direct & !negated` (testnzc) - "vtestz.pd.256" | "vtestc.pd.256" | "vtestnzc.pd.256" | "vtestz.pd" | "vtestc.pd" - | "vtestnzc.pd" | "vtestz.ps.256" | "vtestc.ps.256" | "vtestnzc.ps.256" - | "vtestz.ps" | "vtestc.ps" | "vtestnzc.ps" => { + "vtestz.pd.256" | "vtestc.pd.256" | "vtestnzc.pd.256" | "vtestnzc.pd" + | "vtestz.ps.256" | "vtestc.ps.256" | "vtestnzc.ps.256" | "vtestnzc.ps" => { let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (direct, negated) = test_high_bits_masked(this, op, mask)?; let res = match unprefixed_name { - "vtestz.pd.256" | "vtestz.pd" | "vtestz.ps.256" | "vtestz.ps" => direct, - "vtestc.pd.256" | "vtestc.pd" | "vtestc.ps.256" | "vtestc.ps" => negated, + "vtestz.pd.256" | "vtestz.ps.256" => direct, + "vtestc.pd.256" | "vtestc.ps.256" => negated, "vtestnzc.pd.256" | "vtestnzc.pd" | "vtestnzc.ps.256" | "vtestnzc.ps" => !direct && !negated, _ => unreachable!(), diff --git a/src/tools/miri/src/shims/x86/avx2.rs b/src/tools/miri/src/shims/x86/avx2.rs index ca80c0eba1e5c..01e1ac6de59d3 100644 --- a/src/tools/miri/src/shims/x86/avx2.rs +++ b/src/tools/miri/src/shims/x86/avx2.rs @@ -5,8 +5,8 @@ use rustc_span::Symbol; use rustc_target::callconv::FnAbi; use super::{ - ShiftOp, horizontal_bin_op, int_abs, mask_load, mask_store, mpsadbw, packssdw, packsswb, - packusdw, packuswb, pmulhrsw, psign, shift_simd_by_scalar, shift_simd_by_simd, + ShiftOp, horizontal_bin_op, mask_load, mask_store, mpsadbw, packssdw, packsswb, packusdw, + packuswb, pmulhrsw, psign, shift_simd_by_scalar, shift_simd_by_simd, }; use crate::*; @@ -25,29 +25,20 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.avx2.").unwrap(); match unprefixed_name { - // Used to implement the _mm256_abs_epi{8,16,32} functions. - // Calculates the absolute value of packed 8/16/32-bit integers. - "pabs.b" | "pabs.w" | "pabs.d" => { - let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; - - int_abs(this, op, dest)?; - } - // Used to implement the _mm256_h{add,adds,sub}_epi{16,32} functions. - // Horizontally add / add with saturation / subtract adjacent 16/32-bit + // Used to implement the _mm256_h{adds,subs}_epi16 functions. + // Horizontally add / subtract with saturation adjacent 16-bit // integer values in `left` and `right`. - "phadd.w" | "phadd.sw" | "phadd.d" | "phsub.w" | "phsub.sw" | "phsub.d" => { + "phadd.sw" | "phsub.sw" => { let [left, right] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; - let (which, saturating) = match unprefixed_name { - "phadd.w" | "phadd.d" => (mir::BinOp::Add, false), - "phadd.sw" => (mir::BinOp::Add, true), - "phsub.w" | "phsub.d" => (mir::BinOp::Sub, false), - "phsub.sw" => (mir::BinOp::Sub, true), + let which = match unprefixed_name { + "phadd.sw" => mir::BinOp::Add, + "phsub.sw" => mir::BinOp::Sub, _ => unreachable!(), }; - horizontal_bin_op(this, which, saturating, left, right, dest)?; + horizontal_bin_op(this, which, /*saturating*/ true, left, right, dest)?; } // Used to implement `_mm{,_mask}_{i32,i64}gather_{epi32,epi64,pd,ps}` functions // Gathers elements from `slice` using `offsets * scale` as indices. @@ -110,42 +101,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_int(0, dest.layout.size), &dest)?; } } - // Used to implement the _mm256_madd_epi16 function. - // Multiplies packed signed 16-bit integers in `left` and `right`, producing - // intermediate signed 32-bit integers. Horizontally add adjacent pairs of - // intermediate 32-bit integers, and pack the results in `dest`. - "pmadd.wd" => { - let [left, right] = - this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; - - let (left, left_len) = this.project_to_simd(left)?; - let (right, right_len) = this.project_to_simd(right)?; - let (dest, dest_len) = this.project_to_simd(dest)?; - - assert_eq!(left_len, right_len); - assert_eq!(dest_len.strict_mul(2), left_len); - - for i in 0..dest_len { - let j1 = i.strict_mul(2); - let left1 = this.read_scalar(&this.project_index(&left, j1)?)?.to_i16()?; - let right1 = this.read_scalar(&this.project_index(&right, j1)?)?.to_i16()?; - - let j2 = j1.strict_add(1); - let left2 = this.read_scalar(&this.project_index(&left, j2)?)?.to_i16()?; - let right2 = this.read_scalar(&this.project_index(&right, j2)?)?.to_i16()?; - - let dest = this.project_index(&dest, i)?; - - // Multiplications are i16*i16->i32, which will not overflow. - let mul1 = i32::from(left1).strict_mul(right1.into()); - let mul2 = i32::from(left2).strict_mul(right2.into()); - // However, this addition can overflow in the most extreme case - // (-0x8000)*(-0x8000)+(-0x8000)*(-0x8000) = 0x80000000 - let res = mul1.wrapping_add(mul2); - - this.write_scalar(Scalar::from_i32(res), &dest)?; - } - } // Used to implement the _mm256_maddubs_epi16 function. // Multiplies packed 8-bit unsigned integers from `left` and packed // signed 8-bit integers from `right` into 16-bit signed integers. Then, @@ -285,39 +240,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.copy_op(&left, &dest)?; } } - // Used to implement the _mm256_permute2x128_si256 function. - // Shuffles 128-bit blocks of `a` and `b` using `imm` as pattern. - "vperm2i128" => { - let [left, right, imm] = - this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; - - assert_eq!(left.layout.size.bits(), 256); - assert_eq!(right.layout.size.bits(), 256); - assert_eq!(dest.layout.size.bits(), 256); - - // Transmute to `[i128; 2]` - - let array_layout = - this.layout_of(Ty::new_array(this.tcx.tcx, this.tcx.types.i128, 2))?; - let left = left.transmute(array_layout, this)?; - let right = right.transmute(array_layout, this)?; - let dest = dest.transmute(array_layout, this)?; - - let imm = this.read_scalar(imm)?.to_u8()?; - - for i in 0..2 { - let dest = this.project_index(&dest, i)?; - let src = match (imm >> i.strict_mul(4)) & 0b11 { - 0 => this.project_index(&left, 0)?, - 1 => this.project_index(&left, 1)?, - 2 => this.project_index(&right, 0)?, - 3 => this.project_index(&right, 1)?, - _ => unreachable!(), - }; - - this.copy_op(&src, &dest)?; - } - } // Used to implement the _mm256_sad_epu8 function. // Compute the absolute differences of packed unsigned 8-bit integers // in `left` and `right`, then horizontally sum each consecutive 8 diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 016cb762cece1..63d2b2d044b42 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -42,9 +42,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarry-u32-addcarry-u64.html // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/subborrow-u32-subborrow-u64.html "addcarry.32" | "addcarry.64" | "subborrow.32" | "subborrow.64" => { - if unprefixed_name.ends_with("64") - && this.tcx.sess.target.arch != Arch::X86_64 - { + if unprefixed_name.ends_with("64") && this.tcx.sess.target.arch != Arch::X86_64 { return interp_ok(EmulateItemResult::NotSupported); } @@ -61,28 +59,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_immediate(*sum, &this.project_field(dest, FieldIdx::ONE)?)?; } - // Used to implement the `_addcarryx_u{32, 64}` functions. They are semantically identical with the `_addcarry_u{32, 64}` functions, - // except for a slightly different type signature and the requirement for the "adx" target feature. - // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarryx-u32-addcarryx-u64.html - "addcarryx.u32" | "addcarryx.u64" => { - this.expect_target_feature_for_intrinsic(link_name, "adx")?; - - let is_u64 = unprefixed_name.ends_with("64"); - if is_u64 && this.tcx.sess.target.arch != Arch::X86_64 { - return interp_ok(EmulateItemResult::NotSupported); - } - let [c_in, a, b, out] = - this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; - let out = this.deref_pointer_as( - out, - if is_u64 { this.machine.layouts.u64 } else { this.machine.layouts.u32 }, - )?; - - let (sum, c_out) = carrying_add(this, c_in, a, b, mir::BinOp::AddWithOverflow)?; - this.write_scalar(c_out, dest)?; - this.write_immediate(*sum, &out)?; - } - // Used to implement the `_mm_pause` function. // The intrinsic is used to hint the processor that the code is in a spin-loop. // It is compiled down to a `pause` instruction. When SSE2 is not available, @@ -721,36 +697,6 @@ fn convert_float_to_int<'tcx>( interp_ok(()) } -/// Calculates absolute value of integers in `op` and stores the result in `dest`. -/// -/// In case of overflow (when the operand is the minimum value), the operation -/// will wrap around. -fn int_abs<'tcx>( - ecx: &mut crate::MiriInterpCx<'tcx>, - op: &OpTy<'tcx>, - dest: &MPlaceTy<'tcx>, -) -> InterpResult<'tcx, ()> { - let (op, op_len) = ecx.project_to_simd(op)?; - let (dest, dest_len) = ecx.project_to_simd(dest)?; - - assert_eq!(op_len, dest_len); - - let zero = ImmTy::from_int(0, op.layout.field(ecx, 0)); - - for i in 0..dest_len { - let op = ecx.read_immediate(&ecx.project_index(&op, i)?)?; - let dest = ecx.project_index(&dest, i)?; - - let lt_zero = ecx.binary_op(mir::BinOp::Lt, &op, &zero)?; - let res = - if lt_zero.to_scalar().to_bool()? { ecx.unary_op(mir::UnOp::Neg, &op)? } else { op }; - - ecx.write_immediate(*res, &dest)?; - } - - interp_ok(()) -} - /// Splits `op` (which must be a SIMD vector) into 128-bit chunks. /// /// Returns a tuple where: diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index 6d8def5b53fca..309fbb61de5a7 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -180,29 +180,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_immediate(*res, dest)?; } - // Used to implement the _mm_cvtsi32_ss and _mm_cvtsi64_ss functions. - // Converts `right` from i32/i64 to f32. Returns a SIMD vector with - // the result in the first component and the remaining components - // are copied from `left`. - // https://www.felixcloutier.com/x86/cvtsi2ss - "cvtsi2ss" | "cvtsi642ss" => { - let [left, right] = - this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; - - let (left, left_len) = this.project_to_simd(left)?; - let (dest, dest_len) = this.project_to_simd(dest)?; - - assert_eq!(dest_len, left_len); - - let right = this.read_immediate(right)?; - let dest0 = this.project_index(&dest, 0)?; - let res0 = this.int_to_int_or_float(&right, dest0.layout)?; - this.write_immediate(*res0, &dest0)?; - - for i in 1..dest_len { - this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?; - } - } _ => return interp_ok(EmulateItemResult::NotSupported), } interp_ok(EmulateItemResult::NeedsReturn) diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index 8f53adfb5ecf3..9af7f05d3b27e 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -36,42 +36,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Intrinsincs sufixed with "epiX" or "epuX" operate with X-bit signed or unsigned // vectors. match unprefixed_name { - // Used to implement the _mm_madd_epi16 function. - // Multiplies packed signed 16-bit integers in `left` and `right`, producing - // intermediate signed 32-bit integers. Horizontally add adjacent pairs of - // intermediate 32-bit integers, and pack the results in `dest`. - "pmadd.wd" => { - let [left, right] = - this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; - - let (left, left_len) = this.project_to_simd(left)?; - let (right, right_len) = this.project_to_simd(right)?; - let (dest, dest_len) = this.project_to_simd(dest)?; - - assert_eq!(left_len, right_len); - assert_eq!(dest_len.strict_mul(2), left_len); - - for i in 0..dest_len { - let j1 = i.strict_mul(2); - let left1 = this.read_scalar(&this.project_index(&left, j1)?)?.to_i16()?; - let right1 = this.read_scalar(&this.project_index(&right, j1)?)?.to_i16()?; - - let j2 = j1.strict_add(1); - let left2 = this.read_scalar(&this.project_index(&left, j2)?)?.to_i16()?; - let right2 = this.read_scalar(&this.project_index(&right, j2)?)?.to_i16()?; - - let dest = this.project_index(&dest, i)?; - - // Multiplications are i16*i16->i32, which will not overflow. - let mul1 = i32::from(left1).strict_mul(right1.into()); - let mul2 = i32::from(left2).strict_mul(right2.into()); - // However, this addition can overflow in the most extreme case - // (-0x8000)*(-0x8000)+(-0x8000)*(-0x8000) = 0x80000000 - let res = mul1.wrapping_add(mul2); - - this.write_scalar(Scalar::from_i32(res), &dest)?; - } - } // Used to implement the _mm_sad_epu8 function. // Computes the absolute differences of packed unsigned 8-bit integers in `a` // and `b`, then horizontally sum each consecutive 8 differences to produce @@ -320,10 +284,10 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_immediate(*res, dest)?; } - // Used to implement the _mm_cvtsd_ss and _mm_cvtss_sd functions. - // Converts the first f64/f32 from `right` to f32/f64 and copies - // the remaining elements from `left` - "cvtsd2ss" | "cvtss2sd" => { + // Used to implement the _mm_cvtsd_ss function. + // Converts the first f64 from `right` to f32 and copies the remaining + // elements from `left` + "cvtsd2ss" => { let [left, right] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; @@ -336,8 +300,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Convert first element of `right` let right0 = this.read_immediate(&this.project_index(&right, 0)?)?; let dest0 = this.project_index(&dest, 0)?; - // `float_to_float_or_int` here will convert from f64 to f32 (cvtsd2ss) or - // from f32 to f64 (cvtss2sd). let res0 = this.float_to_float_or_int(&right0, dest0.layout)?; this.write_immediate(*res0, &dest0)?; diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs index 0fd8c3bc389b0..17c8360d33998 100644 --- a/src/tools/miri/src/shims/x86/sse3.rs +++ b/src/tools/miri/src/shims/x86/sse3.rs @@ -1,10 +1,8 @@ use rustc_abi::CanonAbi; -use rustc_middle::mir; use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; -use super::horizontal_bin_op; use crate::*; impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} @@ -22,21 +20,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse3.").unwrap(); match unprefixed_name { - // Used to implement the _mm_h{add,sub}_p{s,d} functions. - // Horizontally add/subtract adjacent floating point values - // in `left` and `right`. - "hadd.ps" | "hadd.pd" | "hsub.ps" | "hsub.pd" => { - let [left, right] = - this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; - - let which = match unprefixed_name { - "hadd.ps" | "hadd.pd" => mir::BinOp::Add, - "hsub.ps" | "hsub.pd" => mir::BinOp::Sub, - _ => unreachable!(), - }; - - horizontal_bin_op(this, which, /*saturating*/ false, left, right, dest)?; - } // Used to implement the _mm_lddqu_si128 function. // Reads a 128-bit vector from an unaligned pointer. This intrinsic // is expected to perform better than a regular unaligned read when diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs index 7736b5e443d0c..1e8b0f34428d1 100644 --- a/src/tools/miri/src/shims/x86/sse41.rs +++ b/src/tools/miri/src/shims/x86/sse41.rs @@ -157,20 +157,13 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { mpsadbw(this, left, right, imm, dest)?; } - // Used to implement the _mm_testz_si128, _mm_testc_si128 - // and _mm_testnzc_si128 functions. - // Tests `(op & mask) == 0`, `(op & mask) == mask` or - // `(op & mask) != 0 && (op & mask) != mask` - "ptestz" | "ptestc" | "ptestnzc" => { + // Used to implement the _mm_testnzc_si128 function. + // Tests `(op & mask) != 0 && (op & mask) != mask` + "ptestnzc" => { let [op, mask] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; let (all_zero, masked_set) = test_bits_masked(this, op, mask)?; - let res = match unprefixed_name { - "ptestz" => all_zero, - "ptestc" => masked_set, - "ptestnzc" => !all_zero && !masked_set, - _ => unreachable!(), - }; + let res = !all_zero && !masked_set; this.write_scalar(Scalar::from_i32(res.into()), dest)?; } diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs index 52ad6bd441992..398f538e1ba03 100644 --- a/src/tools/miri/src/shims/x86/ssse3.rs +++ b/src/tools/miri/src/shims/x86/ssse3.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; -use super::{horizontal_bin_op, int_abs, pmulhrsw, psign}; +use super::{horizontal_bin_op, pmulhrsw, psign}; use crate::*; impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} @@ -22,13 +22,6 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.ssse3.").unwrap(); match unprefixed_name { - // Used to implement the _mm_abs_epi{8,16,32} functions. - // Calculates the absolute value of packed 8/16/32-bit integers. - "pabs.b.128" | "pabs.w.128" | "pabs.d.128" => { - let [op] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; - - int_abs(this, op, dest)?; - } // Used to implement the _mm_shuffle_epi8 intrinsic. // Shuffles bytes from `left` using `right` as pattern. // 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> { this.write_scalar(res, &dest)?; } } - // Used to implement the _mm_h{add,adds,sub}_epi{16,32} functions. - // Horizontally add / add with saturation / subtract adjacent 16/32-bit + // Used to implement the _mm_h{adds,subs}_epi16 functions. + // Horizontally add / subtract with saturation adjacent 16-bit // integer values in `left` and `right`. - "phadd.w.128" | "phadd.sw.128" | "phadd.d.128" | "phsub.w.128" | "phsub.sw.128" - | "phsub.d.128" => { + "phadd.sw.128" | "phsub.sw.128" => { let [left, right] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?; - let (which, saturating) = match unprefixed_name { - "phadd.w.128" | "phadd.d.128" => (mir::BinOp::Add, false), - "phadd.sw.128" => (mir::BinOp::Add, true), - "phsub.w.128" | "phsub.d.128" => (mir::BinOp::Sub, false), - "phsub.sw.128" => (mir::BinOp::Sub, true), + let which = match unprefixed_name { + "phadd.sw.128" => mir::BinOp::Add, + "phsub.sw.128" => mir::BinOp::Sub, _ => unreachable!(), }; - horizontal_bin_op(this, which, saturating, left, right, dest)?; + horizontal_bin_op(this, which, /*saturating*/ true, left, right, dest)?; } // Used to implement the _mm_maddubs_epi16 function. // Multiplies packed 8-bit unsigned integers from `left` and packed diff --git a/src/tools/miri/test-cargo-miri/Cargo.lock b/src/tools/miri/test-cargo-miri/Cargo.lock index 32119426184d4..dd81c3b03bd39 100644 --- a/src/tools/miri/test-cargo-miri/Cargo.lock +++ b/src/tools/miri/test-cargo-miri/Cargo.lock @@ -27,7 +27,6 @@ dependencies = [ "autocfg", "byteorder 0.5.3", "byteorder 1.5.0", - "cdylib", "exported_symbol", "eyre", "issue_1567", @@ -38,13 +37,6 @@ dependencies = [ "proc_macro_crate", ] -[[package]] -name = "cdylib" -version = "0.1.0" -dependencies = [ - "byteorder 1.5.0", -] - [[package]] name = "exported_symbol" version = "0.1.0" diff --git a/src/tools/miri/test-cargo-miri/Cargo.toml b/src/tools/miri/test-cargo-miri/Cargo.toml index f5092a4748f31..3f08f802cf422 100644 --- a/src/tools/miri/test-cargo-miri/Cargo.toml +++ b/src/tools/miri/test-cargo-miri/Cargo.toml @@ -10,7 +10,6 @@ edition = "2024" [dependencies] byteorder = "1.0" -cdylib = { path = "cdylib" } exported_symbol = { path = "exported-symbol" } proc_macro_crate = { path = "proc-macro-crate" } issue_1567 = { path = "issue-1567" } diff --git a/src/tools/miri/test-cargo-miri/cdylib/Cargo.toml b/src/tools/miri/test-cargo-miri/cdylib/Cargo.toml deleted file mode 100644 index 527602e0a888f..0000000000000 --- a/src/tools/miri/test-cargo-miri/cdylib/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "cdylib" -version = "0.1.0" -authors = ["Miri Team"] -edition = "2018" - -[lib] -# cargo-miri used to handle `cdylib` crate-type specially (https://github.com/rust-lang/miri/pull/1577). -crate-type = ["cdylib"] - -[dependencies] -byteorder = "1.0" # to test dependencies of sub-crates diff --git a/src/tools/miri/test-cargo-miri/cdylib/src/lib.rs b/src/tools/miri/test-cargo-miri/cdylib/src/lib.rs deleted file mode 100644 index e47e588251e4e..0000000000000 --- a/src/tools/miri/test-cargo-miri/cdylib/src/lib.rs +++ /dev/null @@ -1,6 +0,0 @@ -use byteorder::{BigEndian, ByteOrder}; - -#[no_mangle] -extern "C" fn use_the_dependency() { - let _n = ::read_u64(&[1, 2, 3, 4, 5, 6, 7, 8]); -} diff --git a/src/tools/miri/test-cargo-miri/run.local_crate.stdout.ref b/src/tools/miri/test-cargo-miri/run.local_crate.stdout.ref index 1587de9ff3f87..60cd9d371ad6c 100644 --- a/src/tools/miri/test-cargo-miri/run.local_crate.stdout.ref +++ b/src/tools/miri/test-cargo-miri/run.local_crate.stdout.ref @@ -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 +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 diff --git a/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.rs b/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.rs new file mode 100644 index 0000000000000..1c31236a2f805 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.rs @@ -0,0 +1,29 @@ +//@only-target: darwin +#![feature(sync_unsafe_cell)] + +use std::cell::SyncUnsafeCell; +use std::sync::atomic::*; +use std::thread; + +fn main() { + let lock = SyncUnsafeCell::new(libc::OS_UNFAIR_LOCK_INIT); + + thread::scope(|s| { + // First thread: grabs the lock. + s.spawn(|| { + unsafe { libc::os_unfair_lock_lock(lock.get()) }; + thread::yield_now(); + unreachable!(); + }); + // Second thread: queues for the lock. + s.spawn(|| { + unsafe { libc::os_unfair_lock_lock(lock.get()) }; + unreachable!(); + }); + // Third thread: tries to read the lock while second thread is queued. + s.spawn(|| { + let atomic_ref = unsafe { &*lock.get().cast::() }; + let _val = atomic_ref.load(Ordering::Relaxed); //~ERROR: read of `os_unfair_lock` is forbidden while the queue is non-empty + }); + }); +} diff --git a/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.stderr b/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.stderr new file mode 100644 index 0000000000000..003ddb9b287d2 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: read of `os_unfair_lock` is forbidden while the queue is non-empty + --> tests/fail-dep/concurrency/apple_os_unfair_lock_move_with_queue.rs:LL:CC + | +LL | let _val = atomic_ref.load(Ordering::Relaxed); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs index 5778765589de9..5d5ffded5c5c1 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs @@ -1,6 +1,6 @@ //@ignore-target: windows # No pthreads on Windows //@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" -//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" +//@ normalize-stderr-test: "\[0x[0-9a-z]+..0x[0-9a-z]+\]" -> "[0xX..0xY]" /// Test that destroying a pthread_cond twice fails, even without a check for number validity diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr index 9a7f0bb79e5fa..f3f64a60a89bb 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.init.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: `pthread_cond_t` can't be moved after first use +error: Undefined Behavior: `pthread_cond_t` was not properly initialized at this location, or it got overwritten --> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC | LL | libc::pthread_cond_destroy(cond2.as_mut_ptr()); diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.rs index 4db904ab5e224..ef20a53dd2f1b 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.rs @@ -18,7 +18,7 @@ fn check() { // move pthread_cond_t let mut cond2 = cond; - libc::pthread_cond_destroy(cond2.as_mut_ptr()); //~[init] ERROR: can't be moved after first use + libc::pthread_cond_destroy(cond2.as_mut_ptr()); //~[init] ERROR: not properly initialized } } @@ -32,6 +32,6 @@ fn check() { // move pthread_cond_t let mut cond2 = cond; - libc::pthread_cond_destroy(&mut cond2 as *mut _); //~[static_initializer] ERROR: can't be moved after first use + libc::pthread_cond_destroy(&mut cond2 as *mut _); //~[static_initializer] ERROR: not properly initialized } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.static_initializer.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.static_initializer.stderr index ee1fafcf7cb18..4056f7d9d41b5 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.static_initializer.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_move.static_initializer.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: `pthread_cond_t` can't be moved after first use +error: Undefined Behavior: `pthread_cond_t` was not properly initialized at this location, or it got overwritten --> tests/fail-dep/concurrency/libc_pthread_cond_move.rs:LL:CC | LL | libc::pthread_cond_destroy(&mut cond2 as *mut _); diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs index f04fe8be6b38d..45d16e173d9a6 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs @@ -1,6 +1,6 @@ //@ignore-target: windows # No pthreads on Windows //@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" -//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" +//@ normalize-stderr-test: "\[0x[0-9a-z]+..0x[0-9a-z]+\]" -> "[0xX..0xY]" /// Test that destroying a pthread_mutex twice fails, even without a check for number validity diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.rs new file mode 100644 index 0000000000000..55fcb4c61d480 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.rs @@ -0,0 +1,48 @@ +//@ignore-target: windows # No pthreads on Windows +//@compile-flags: -Zmiri-deterministic-concurrency +//@error-in-other-file: deallocation of `pthread_mutex_t` is forbidden while the queue is non-empty + +use std::cell::UnsafeCell; +use std::sync::atomic::*; +use std::thread; + +struct Mutex(UnsafeCell); +impl Mutex { + fn get(&self) -> *mut libc::pthread_mutex_t { + self.0.get() + } +} + +unsafe impl Send for Mutex {} +unsafe impl Sync for Mutex {} + +fn main() { + let m = Box::new(Mutex(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER))); + let initialized = AtomicBool::new(false); + thread::scope(|s| { + // First thread: initializes the lock, and then grabs it. + s.spawn(|| { + // Initialize (so the third thread can happens-after the write that occurs here). + assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0); + assert_eq!(unsafe { libc::pthread_mutex_unlock(m.get()) }, 0); + initialized.store(true, Ordering::Release); + // Grab and hold. + assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0); + thread::yield_now(); + unreachable!(); + }); + // Second thread: queues for the lock. + s.spawn(|| { + assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0); + unreachable!(); + }); + // Third thread: tries to free the lock while second thread is queued. + s.spawn(|| { + // Ensure we happen-after the initialization write. + assert!(initialized.load(Ordering::Acquire)); + // Now drop it. + drop(unsafe { Box::from_raw(m.get().cast::()) }); + }); + }); + unreachable!(); +} diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.stderr new file mode 100644 index 0000000000000..7b6e05828cea3 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.stderr @@ -0,0 +1,22 @@ +error: Undefined Behavior: deallocation of `pthread_mutex_t` is forbidden while the queue is non-empty + --> RUSTLIB/alloc/src/boxed.rs:LL:CC + | +LL | self.1.deallocate(From::from(ptr.cast()), layout); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE on thread `unnamed-ID`: + = note: inside ` as std::ops::Drop>::drop` at RUSTLIB/alloc/src/boxed.rs:LL:CC + = note: inside `std::ptr::drop_in_place::> - shim(Some(std::boxed::Box))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC + = note: inside `std::mem::drop::>` at RUSTLIB/core/src/mem/mod.rs:LL:CC +note: inside closure + --> tests/fail-dep/concurrency/libc_pthread_mutex_free_while_queued.rs:LL:CC + | +LL | drop(unsafe { Box::from_raw(m.get().cast::()) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr index 2e8e411e186a7..a7cba0f00fe97 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: `pthread_mutex_t` can't be moved after first use +error: Undefined Behavior: `pthread_mutex_t` was not properly initialized at this location, or it got overwritten --> tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC | LL | libc::pthread_mutex_lock(&mut m2 as *mut _); diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs index 6c1f967b2b03b..028c6ec34dc9e 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs @@ -12,7 +12,7 @@ fn check() { assert_eq!(libc::pthread_mutex_init(&mut m as *mut _, std::ptr::null()), 0); let mut m2 = m; // move the mutex - libc::pthread_mutex_lock(&mut m2 as *mut _); //~[init] ERROR: can't be moved after first use + libc::pthread_mutex_lock(&mut m2 as *mut _); //~[init] ERROR: not properly initialized } } @@ -23,6 +23,6 @@ fn check() { libc::pthread_mutex_lock(&mut m as *mut _); let mut m2 = m; // move the mutex - libc::pthread_mutex_unlock(&mut m2 as *mut _); //~[static_initializer] ERROR: can't be moved after first use + libc::pthread_mutex_unlock(&mut m2 as *mut _); //~[static_initializer] ERROR: not properly initialized } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr index 4fd3bd52ae12b..71f71efa0d96b 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: `pthread_mutex_t` can't be moved after first use +error: Undefined Behavior: `pthread_mutex_t` was not properly initialized at this location, or it got overwritten --> tests/fail-dep/concurrency/libc_pthread_mutex_move.rs:LL:CC | LL | libc::pthread_mutex_unlock(&mut m2 as *mut _); diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_overwrite.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_overwrite.rs new file mode 100644 index 0000000000000..95b934ab1b727 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_overwrite.rs @@ -0,0 +1,14 @@ +//@ignore-target: windows # No pthreads on Windows + +fn main() { + unsafe { + let mut m: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER; + libc::pthread_mutex_lock(&mut m as *mut _); + + // Overwrite the mutex with itself. This de-initializes it. + let copy = m; + m = copy; + + libc::pthread_mutex_unlock(&mut m as *mut _); //~ERROR: not properly initialized + } +} diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_overwrite.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_overwrite.stderr new file mode 100644 index 0000000000000..b44792285421c --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_overwrite.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: `pthread_mutex_t` was not properly initialized at this location, or it got overwritten + --> tests/fail-dep/concurrency/libc_pthread_mutex_overwrite.rs:LL:CC + | +LL | libc::pthread_mutex_unlock(&mut m as *mut _); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_read_while_queued.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_read_while_queued.rs new file mode 100644 index 0000000000000..555d765d24ba3 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_read_while_queued.rs @@ -0,0 +1,41 @@ +//@ignore-target: windows # No pthreads on Windows +//@compile-flags: -Zmiri-fixed-schedule + +use std::cell::UnsafeCell; +use std::sync::atomic::*; +use std::thread; + +struct Mutex(UnsafeCell); +impl Mutex { + fn get(&self) -> *mut libc::pthread_mutex_t { + self.0.get() + } +} + +unsafe impl Send for Mutex {} +unsafe impl Sync for Mutex {} + +// The offset to the "sensitive" part of the mutex (that Miri attaches the metadata to). +const OFFSET: usize = if cfg!(target_os = "macos") { 4 } else { 0 }; + +fn main() { + let m = Mutex(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER)); + thread::scope(|s| { + // First thread: grabs the lock. + s.spawn(|| { + assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0); + thread::yield_now(); + unreachable!(); + }); + // Second thread: queues for the lock. + s.spawn(|| { + assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0); + unreachable!(); + }); + // Third thread: tries to read the lock while second thread is queued. + s.spawn(|| { + let atomic_ref = unsafe { &*m.get().byte_add(OFFSET).cast::() }; + let _val = atomic_ref.load(Ordering::Relaxed); //~ERROR: read of `pthread_mutex_t` is forbidden while the queue is non-empty + }); + }); +} diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_read_while_queued.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_read_while_queued.stderr new file mode 100644 index 0000000000000..42dbd5f02cb3b --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_read_while_queued.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: read of `pthread_mutex_t` is forbidden while the queue is non-empty + --> tests/fail-dep/concurrency/libc_pthread_mutex_read_while_queued.rs:LL:CC + | +LL | ... let _val = atomic_ref.load(Ordering::Relaxed); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_write_while_queued.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_write_while_queued.rs new file mode 100644 index 0000000000000..00274f7080f33 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_write_while_queued.rs @@ -0,0 +1,41 @@ +//@ignore-target: windows # No pthreads on Windows +//@compile-flags: -Zmiri-fixed-schedule + +use std::cell::UnsafeCell; +use std::sync::atomic::*; +use std::thread; + +struct Mutex(UnsafeCell); +impl Mutex { + fn get(&self) -> *mut libc::pthread_mutex_t { + self.0.get() + } +} + +unsafe impl Send for Mutex {} +unsafe impl Sync for Mutex {} + +// The offset to the "sensitive" part of the mutex (that Miri attaches the metadata to). +const OFFSET: usize = if cfg!(target_os = "macos") { 4 } else { 0 }; + +fn main() { + let m = Mutex(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER)); + thread::scope(|s| { + // First thread: grabs the lock. + s.spawn(|| { + assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0); + thread::yield_now(); + unreachable!(); + }); + // Second thread: queues for the lock. + s.spawn(|| { + assert_eq!(unsafe { libc::pthread_mutex_lock(m.get()) }, 0); + unreachable!(); + }); + // Third thread: tries to overwrite the lock while second thread is queued. + s.spawn(|| { + let atomic_ref = unsafe { &*m.get().byte_add(OFFSET).cast::() }; + atomic_ref.store(0, Ordering::Relaxed); //~ERROR: write of `pthread_mutex_t` is forbidden while the queue is non-empty + }); + }); +} diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_write_while_queued.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_write_while_queued.stderr new file mode 100644 index 0000000000000..4705f9a1b5f02 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_write_while_queued.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: write of `pthread_mutex_t` is forbidden while the queue is non-empty + --> tests/fail-dep/concurrency/libc_pthread_mutex_write_while_queued.rs:LL:CC + | +LL | atomic_ref.store(0, Ordering::Relaxed); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs index 720ba71d23834..3d59d8e399373 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs @@ -1,6 +1,6 @@ //@ignore-target: windows # No pthreads on Windows //@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" -//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" +//@ normalize-stderr-test: "\[0x[0-9a-z]+..0x[0-9a-z]+\]" -> "[0xX..0xY]" /// Test that destroying a pthread_rwlock twice fails, even without a check for number validity diff --git a/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs b/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs index 6af19b7df9b58..fe507f63ec4e4 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs @@ -9,6 +9,6 @@ fn main() { // Move rwlock let mut rw2 = rw; - libc::pthread_rwlock_unlock(&mut rw2 as *mut _); //~ ERROR: can't be moved after first use + libc::pthread_rwlock_unlock(&mut rw2 as *mut _); //~ ERROR: not properly initialized } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.stderr b/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.stderr index e69da4de99ddf..0625708c256b0 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libx_pthread_rwlock_moved.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: `pthread_rwlock_t` can't be moved after first use +error: Undefined Behavior: `pthread_rwlock_t` was not properly initialized at this location, or it got overwritten --> tests/fail-dep/concurrency/libx_pthread_rwlock_moved.rs:LL:CC | LL | libc::pthread_rwlock_unlock(&mut rw2 as *mut _); diff --git a/src/tools/miri/tests/fail/intrinsics/simd_masked_load_element_misaligned.rs b/src/tools/miri/tests/fail/intrinsics/simd_masked_load_element_misaligned.rs index 3b5e389cf27ee..47a51dbbab518 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd_masked_load_element_misaligned.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd_masked_load_element_misaligned.rs @@ -6,7 +6,7 @@ use std::simd::*; fn main() { unsafe { let buf = [0u32; 5]; - //~v ERROR: accessing memory with alignment + //~v ERROR: accessing memory with alignment simd_masked_load::<_, _, _, { SimdAlign::Element }>( i32x4::splat(-1), // This is not i32-aligned diff --git a/src/tools/miri/tests/pass-dep/concurrency/apple-os-unfair-lock.rs b/src/tools/miri/tests/pass-dep/concurrency/apple-os-unfair-lock.rs index f5b64474f83b6..05765fc3f30d4 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/apple-os-unfair-lock.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/apple-os-unfair-lock.rs @@ -14,12 +14,10 @@ fn main() { libc::os_unfair_lock_assert_not_owner(lock.get()); } - // `os_unfair_lock`s can be moved and leaked. - // In the real implementation, even moving it while locked is possible - // (and "forks" the lock, i.e. old and new location have independent wait queues). - // We only test the somewhat sane case of moving while unlocked that `std` plans to rely on. + // `os_unfair_lock`s can be moved, and even acquired again then. let lock = lock; - let locked = unsafe { libc::os_unfair_lock_trylock(lock.get()) }; - assert!(locked); - let _lock = lock; + assert!(unsafe { libc::os_unfair_lock_trylock(lock.get()) }); + // We can even move it while locked, but then we cannot acquire it any more. + let lock = lock; + assert!(!unsafe { libc::os_unfair_lock_trylock(lock.get()) }); } diff --git a/src/tools/miri/tests/pass-dep/libc/pthread-sync.rs b/src/tools/miri/tests/pass-dep/libc/pthread-sync.rs index 255944662940d..a79d0656d85c4 100644 --- a/src/tools/miri/tests/pass-dep/libc/pthread-sync.rs +++ b/src/tools/miri/tests/pass-dep/libc/pthread-sync.rs @@ -8,18 +8,21 @@ use std::mem::MaybeUninit; use std::{mem, ptr, thread}; fn main() { + test_mutex(); test_mutex_libc_init_recursive(); test_mutex_libc_init_normal(); test_mutex_libc_init_errorcheck(); - test_rwlock_libc_static_initializer(); #[cfg(target_os = "linux")] test_mutex_libc_static_initializer_recursive(); + #[cfg(target_os = "linux")] + test_mutex_libc_static_initializer_errorcheck(); + + test_cond(); + test_condattr(); - check_mutex(); - check_rwlock_write(); - check_rwlock_read_no_deadlock(); - check_cond(); - check_condattr(); + test_rwlock(); + test_rwlock_write(); + test_rwlock_read_no_deadlock(); } // We want to only use pthread APIs here for easier testing. @@ -107,8 +110,7 @@ fn test_mutex_libc_init_errorcheck() { } } -// Only linux provides PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, -// libc for macOS just has the default PTHREAD_MUTEX_INITIALIZER. +// Only linux provides PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP. #[cfg(target_os = "linux")] fn test_mutex_libc_static_initializer_recursive() { let mutex = std::cell::UnsafeCell::new(libc::PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); @@ -126,6 +128,22 @@ fn test_mutex_libc_static_initializer_recursive() { } } +// Only linux provides PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP. +#[cfg(target_os = "linux")] +fn test_mutex_libc_static_initializer_errorcheck() { + let mutex = std::cell::UnsafeCell::new(libc::PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP); + unsafe { + assert_eq!(libc::pthread_mutex_lock(mutex.get()), 0); + assert_eq!(libc::pthread_mutex_trylock(mutex.get()), libc::EBUSY); + assert_eq!(libc::pthread_mutex_lock(mutex.get()), libc::EDEADLK); + assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0); + assert_eq!(libc::pthread_mutex_trylock(mutex.get()), 0); + assert_eq!(libc::pthread_mutex_unlock(mutex.get()), 0); + assert_eq!(libc::pthread_mutex_unlock(mutex.get()), libc::EPERM); + assert_eq!(libc::pthread_mutex_destroy(mutex.get()), 0); + } +} + struct SendPtr { ptr: *mut T, } @@ -137,7 +155,7 @@ impl Clone for SendPtr { } } -fn check_mutex() { +fn test_mutex() { let bomb = AbortOnDrop; // Specifically *not* using `Arc` to make sure there is no synchronization apart from the mutex. unsafe { @@ -168,7 +186,7 @@ fn check_mutex() { bomb.defuse(); } -fn check_rwlock_write() { +fn test_rwlock_write() { let bomb = AbortOnDrop; unsafe { let data = SyncUnsafeCell::new((libc::PTHREAD_RWLOCK_INITIALIZER, 0)); @@ -209,7 +227,7 @@ fn check_rwlock_write() { bomb.defuse(); } -fn check_rwlock_read_no_deadlock() { +fn test_rwlock_read_no_deadlock() { let bomb = AbortOnDrop; unsafe { let l1 = SyncUnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER); @@ -237,12 +255,11 @@ fn check_rwlock_read_no_deadlock() { bomb.defuse(); } -fn check_cond() { +fn test_cond() { let bomb = AbortOnDrop; unsafe { - let mut cond: MaybeUninit = MaybeUninit::uninit(); - assert_eq!(libc::pthread_cond_init(cond.as_mut_ptr(), ptr::null()), 0); - let cond = SendPtr { ptr: cond.as_mut_ptr() }; + let mut cond: libc::pthread_cond_t = libc::PTHREAD_COND_INITIALIZER; + let cond = SendPtr { ptr: &mut cond }; let mut mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER; let mutex = SendPtr { ptr: &mut mutex }; @@ -286,7 +303,7 @@ fn check_cond() { bomb.defuse(); } -fn check_condattr() { +fn test_condattr() { unsafe { // Just smoke-testing that these functions can be called. let mut attr: MaybeUninit = MaybeUninit::uninit(); @@ -311,9 +328,7 @@ fn check_condattr() { } } -// std::sync::RwLock does not even used pthread_rwlock any more. -// Do some smoke testing of the API surface. -fn test_rwlock_libc_static_initializer() { +fn test_rwlock() { let rw = std::cell::UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER); unsafe { assert_eq!(libc::pthread_rwlock_rdlock(rw.get()), 0); diff --git a/src/tools/miri/triagebot.toml b/src/tools/miri/triagebot.toml index c747cbb0a5211..060b749676e62 100644 --- a/src/tools/miri/triagebot.toml +++ b/src/tools/miri/triagebot.toml @@ -20,7 +20,7 @@ contributing_url = "https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.m [assign.custom_welcome_messages] welcome-message = "(unused)" welcome-message-no-reviewer = """ -Thank you for contributing to Miri! +Thank you for contributing to Miri! A reviewer will take a look at your PR, typically within a week or two. 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. """ diff --git a/src/tools/tidy/src/diagnostics.rs b/src/tools/tidy/src/diagnostics.rs index 1e25f862522e8..159500751aa5a 100644 --- a/src/tools/tidy/src/diagnostics.rs +++ b/src/tools/tidy/src/diagnostics.rs @@ -1,9 +1,10 @@ use std::collections::HashSet; use std::fmt::{Display, Formatter}; +use std::io; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; -use termcolor::{Color, WriteColor}; +use termcolor::Color; #[derive(Clone, Default)] ///CLI flags used by tidy. @@ -245,30 +246,63 @@ pub const COLOR_WARNING: Color = Color::Yellow; /// Output a message to stderr. /// The message can be optionally scoped to a certain check, and it can also have a certain color. pub fn output_message(msg: &str, id: Option<&CheckId>, color: Option) { - use std::io::Write; + use termcolor::{ColorChoice, ColorSpec}; - use termcolor::{ColorChoice, ColorSpec, StandardStream}; + let stderr: &mut dyn termcolor::WriteColor = if cfg!(test) { + &mut StderrForUnitTests + } else { + &mut termcolor::StandardStream::stderr(ColorChoice::Auto) + }; - let mut stderr = StandardStream::stderr(ColorChoice::Auto); if let Some(color) = &color { stderr.set_color(ColorSpec::new().set_fg(Some(*color))).unwrap(); } match id { Some(id) => { - write!(&mut stderr, "tidy [{}", id.name).unwrap(); + write!(stderr, "tidy [{}", id.name).unwrap(); if let Some(path) = &id.path { - write!(&mut stderr, " ({})", path.display()).unwrap(); + write!(stderr, " ({})", path.display()).unwrap(); } - write!(&mut stderr, "]").unwrap(); + write!(stderr, "]").unwrap(); } None => { - write!(&mut stderr, "tidy").unwrap(); + write!(stderr, "tidy").unwrap(); } } if color.is_some() { stderr.set_color(&ColorSpec::new()).unwrap(); } - writeln!(&mut stderr, ": {msg}").unwrap(); + writeln!(stderr, ": {msg}").unwrap(); +} + +/// An implementation of `io::Write` and `termcolor::WriteColor` that writes +/// to stderr via `eprint!`, so that the output can be properly captured when +/// running tidy's unit tests. +struct StderrForUnitTests; + +impl io::Write for StderrForUnitTests { + fn write(&mut self, buf: &[u8]) -> io::Result { + eprint!("{}", String::from_utf8_lossy(buf)); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl termcolor::WriteColor for StderrForUnitTests { + fn supports_color(&self) -> bool { + false + } + + fn set_color(&mut self, _spec: &termcolor::ColorSpec) -> io::Result<()> { + Ok(()) + } + + fn reset(&mut self) -> io::Result<()> { + Ok(()) + } } diff --git a/tests/crashes/140729.rs b/tests/crashes/140729.rs deleted file mode 100644 index a436ec58e8e83..0000000000000 --- a/tests/crashes/140729.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: #140729 -#![feature(min_generic_const_args)] - -const C: usize = 0; -pub struct A {} -impl A { - fn fun1() {} -} -impl A { - fn fun1() {} -} diff --git a/tests/crashes/140860.rs b/tests/crashes/140860.rs deleted file mode 100644 index 04da6bd832c3a..0000000000000 --- a/tests/crashes/140860.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #140860 -#![feature(min_generic_const_args)] -#![feature(unsized_const_params)] -#![feature(with_negative_coherence, negative_impls)] -trait a < const b : &'static str> {} trait c {} struct d< e >(e); -impl c for e where e: a<""> {} -impl c for d {} -impl !a for e {} -const f : &str = ""; -fn main() {} diff --git a/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-disabled.stderr b/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-disabled.stderr index 646688604674c..46b0ce96b1fee 100644 --- a/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-disabled.stderr +++ b/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-disabled.stderr @@ -38,8 +38,8 @@ LL | trait Bar: [const] Foo {} | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | const trait Foo { + | +++++ error: `[const]` can only be applied to `const` traits --> const-super-trait.rs:9:17 @@ -49,8 +49,8 @@ LL | const fn foo(x: &T) { | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Bar: [const] Foo {} - | ++++++++++++++ +LL | const trait Bar: [const] Foo {} + | +++++ error[E0015]: cannot call non-const method `::a` in constant functions --> const-super-trait.rs:10:7 @@ -65,13 +65,12 @@ LL | trait Foo { | ^^^^^^^^^ this trait is not const LL | fn a(&self); | ------------ this method is not const - = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]` + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable const traits = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider making trait `Foo` const | -LL + #[const_trait] -LL | trait Foo { - | +LL | const trait Foo { + | +++++ error: aborting due to 6 previous errors diff --git a/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-enabled.stderr b/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-enabled.stderr index d0e7edf42cdd5..c1b35e733a1ff 100644 --- a/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-enabled.stderr +++ b/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-enabled.stderr @@ -18,8 +18,8 @@ LL | trait Bar: [const] Foo {} | help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | const trait Foo { + | +++++ error: `[const]` can only be applied to `const` traits --> const-super-trait.rs:9:17 @@ -29,8 +29,8 @@ LL | const fn foo(x: &T) { | help: mark `Bar` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Bar: [const] Foo {} - | ++++++++++++++ +LL | const trait Bar: [const] Foo {} + | +++++ error[E0015]: cannot call non-const method `::a` in constant functions --> const-super-trait.rs:10:7 @@ -48,9 +48,8 @@ LL | fn a(&self); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider making trait `Foo` const | -LL + #[const_trait] -LL | trait Foo { - | +LL | const trait Foo { + | +++++ error: aborting due to 4 previous errors diff --git a/tests/rustdoc/constant/const-effect-param.rs b/tests/rustdoc/constant/const-effect-param.rs index 3dc63fb3d30f6..28c1a43fa9daf 100644 --- a/tests/rustdoc/constant/const-effect-param.rs +++ b/tests/rustdoc/constant/const-effect-param.rs @@ -3,8 +3,7 @@ #![crate_name = "foo"] #![feature(const_trait_impl)] -#[const_trait] -pub trait Tr { +pub const trait Tr { fn f(); } diff --git a/tests/rustdoc/constant/const-trait-and-impl-methods.rs b/tests/rustdoc/constant/const-trait-and-impl-methods.rs index 30fc539e5533f..987a816d465bd 100644 --- a/tests/rustdoc/constant/const-trait-and-impl-methods.rs +++ b/tests/rustdoc/constant/const-trait-and-impl-methods.rs @@ -1,5 +1,4 @@ -// check that we don't render `#[const_trait]` methods as `const` - even for -// const `trait`s and `impl`s. +// check that we don't render assoc fns as `const` - even for const `trait`s and `impl`s. #![crate_name = "foo"] #![feature(const_trait_impl)] @@ -8,8 +7,7 @@ //@ !has - '//*[@id="tymethod.required"]' 'const' //@ has - '//*[@id="method.defaulted"]' 'fn defaulted()' //@ !has - '//*[@id="method.defaulted"]' 'const' -#[const_trait] -pub trait Tr { +pub const trait Tr { fn required(); fn defaulted() {} } diff --git a/tests/rustdoc/constant/rfc-2632-const-trait-impl.rs b/tests/rustdoc/constant/rfc-2632-const-trait-impl.rs index e304eff14e8cb..f263410d93afe 100644 --- a/tests/rustdoc/constant/rfc-2632-const-trait-impl.rs +++ b/tests/rustdoc/constant/rfc-2632-const-trait-impl.rs @@ -19,8 +19,7 @@ pub struct S(T); //@ has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Fn' //@ !has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' '[const]' //@ has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' ': Fn' -#[const_trait] -pub trait Tr { +pub const trait Tr { //@ !has - '//section[@id="method.a"]/h4[@class="code-header"]' '[const]' //@ has - '//section[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn' //@ !has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '[const]' diff --git a/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs index d7d7b32e2b8b7..6f47091b18bf8 100644 --- a/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs +++ b/tests/rustdoc/inline_cross/auxiliary/const-effect-param.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -pub trait Resource {} +pub const trait Resource {} pub const fn load() -> i32 { 0 diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs b/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs index d433af6bdd57d..2ff5a0353a0a6 100644 --- a/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs +++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs @@ -1,7 +1,7 @@ // We used to say "ambiguous associated type" on ambiguous associated consts. // Ensure that we now use the correct label. -#![feature(associated_const_equality, min_generic_const_args)] +#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] trait Trait0: Parent0 + Parent0 {} diff --git a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.rs b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.rs index f6240ead0b9bd..5232b895803e8 100644 --- a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.rs +++ b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.rs @@ -1,9 +1,16 @@ // Check that we eventually catch types of assoc const bounds // (containing late-bound vars) that are ill-formed. -#![feature(associated_const_equality, min_generic_const_args)] +#![feature( + associated_const_equality, + min_generic_const_args, + adt_const_params, + unsized_const_params, +)] #![allow(incomplete_features)] -trait Trait { +use std::marker::ConstParamTy_; + +trait Trait { #[type_const] const K: T; } diff --git a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr index b629bb4d3f8c7..a0329e2b15d17 100644 --- a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr @@ -1,11 +1,11 @@ error: higher-ranked subtype error - --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:14:13 + --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:13 | LL | K = { () } | ^^^^^^ error: higher-ranked subtype error - --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:14:13 + --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:13 | LL | K = { () } | ^^^^^^ @@ -13,7 +13,7 @@ LL | K = { () } = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Project` is not general enough - --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:12:13 + --> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:19:13 | LL | _: impl Trait< | _____________^ diff --git a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs index 36b3d8a648fd8..ef8077b9f44a5 100644 --- a/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs +++ b/tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty.rs @@ -3,10 +3,17 @@ // //@ check-pass -#![feature(associated_const_equality, min_generic_const_args)] +#![feature( + associated_const_equality, + min_generic_const_args, + adt_const_params, + unsized_const_params, +)] #![allow(incomplete_features)] -trait Trait { +use std::marker::ConstParamTy_; + +trait Trait { #[type_const] const K: T; } diff --git a/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.rs b/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.rs index 3f48b3bfbb6d1..1ab93ea596a76 100644 --- a/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.rs +++ b/tests/ui/associated-consts/assoc-const-eq-esc-bound-var-in-ty.rs @@ -1,6 +1,6 @@ // Detect and reject escaping late-bound generic params in // the type of assoc consts used in an equality bound. -#![feature(associated_const_equality, min_generic_const_args)] +#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] trait Trait<'a> { diff --git a/tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs b/tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs index 5b0438e95695c..0afb95a0b0336 100644 --- a/tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs +++ b/tests/ui/associated-consts/assoc-const-eq-param-in-ty.rs @@ -1,14 +1,21 @@ // Regression test for issue #108271. // Detect and reject generic params in the type of assoc consts used in an equality bound. -#![feature(associated_const_equality, min_generic_const_args)] +#![feature( + associated_const_equality, + min_generic_const_args, + adt_const_params, + unsized_const_params, +)] #![allow(incomplete_features)] -trait Trait<'a, T: 'a, const N: usize> { +use std::marker::ConstParamTy_; + +trait Trait<'a, T: 'a + ConstParamTy_, const N: usize> { #[type_const] const K: &'a [T; N]; } -fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} +fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} //~^ ERROR the type of the associated constant `K` must not depend on generic parameters //~| NOTE its type must not depend on the lifetime parameter `'r` //~| 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 {} }>) {} //~| NOTE the const parameter `Q` is defined here //~| NOTE `K` has type `&'r [A; Q]` -trait Project { +trait Project: ConstParamTy_ { #[type_const] const SELF: Self; } @@ -38,7 +45,7 @@ fn take2>(_: P) {} //~| NOTE the type parameter `P` is defined here //~| NOTE `SELF` has type `P` -trait Iface<'r> { +trait Iface<'r>: ConstParamTy_ { //~^ NOTE the lifetime parameter `'r` is defined here //~| NOTE the lifetime parameter `'r` is defined here type Assoc: Trait<'r, Self, Q, K = { loop {} }> diff --git a/tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr b/tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr index 7ba1d638baa88..229dd10c0bebf 100644 --- a/tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-param-in-ty.stderr @@ -1,31 +1,31 @@ error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:11:61 + --> $DIR/assoc-const-eq-param-in-ty.rs:18:77 | -LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} - | -- the lifetime parameter `'r` is defined here ^ its type must not depend on the lifetime parameter `'r` +LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} + | -- the lifetime parameter `'r` is defined here ^ its type must not depend on the lifetime parameter `'r` | = note: `K` has type `&'r [A; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:11:61 + --> $DIR/assoc-const-eq-param-in-ty.rs:18:77 | -LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} - | - the type parameter `A` is defined here ^ its type must not depend on the type parameter `A` +LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} + | - the type parameter `A` is defined here ^ its type must not depend on the type parameter `A` | = note: `K` has type `&'r [A; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:11:61 + --> $DIR/assoc-const-eq-param-in-ty.rs:18:77 | -LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} - | - ^ its type must not depend on the const parameter `Q` - | | - | the const parameter `Q` is defined here +LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {} + | - ^ its type must not depend on the const parameter `Q` + | | + | the const parameter `Q` is defined here | = note: `K` has type `&'r [A; Q]` error: the type of the associated constant `SELF` must not depend on `impl Trait` - --> $DIR/assoc-const-eq-param-in-ty.rs:30:26 + --> $DIR/assoc-const-eq-param-in-ty.rs:37:26 | LL | fn take1(_: impl Project) {} | -------------^^^^------ @@ -34,7 +34,7 @@ LL | fn take1(_: impl Project) {} | the `impl Trait` is specified here error: the type of the associated constant `SELF` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:35:21 + --> $DIR/assoc-const-eq-param-in-ty.rs:42:21 | LL | fn take2>(_: P) {} | - ^^^^ its type must not depend on the type parameter `P` @@ -44,9 +44,9 @@ LL | fn take2>(_: P) {} = note: `SELF` has type `P` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:44:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 | -LL | trait Iface<'r> { +LL | trait Iface<'r>: ConstParamTy_ { | -- the lifetime parameter `'r` is defined here ... LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> @@ -55,7 +55,7 @@ LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> = note: `K` has type `&'r [Self; Q]` error: the type of the associated constant `K` must not depend on `Self` - --> $DIR/assoc-const-eq-param-in-ty.rs:44:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 | LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> | ^ its type must not depend on `Self` @@ -63,7 +63,7 @@ LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> = note: `K` has type `&'r [Self; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:44:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 | LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> | - ^ its type must not depend on the const parameter `Q` @@ -73,9 +73,9 @@ LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> = note: `K` has type `&'r [Self; Q]` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:44:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 | -LL | trait Iface<'r> { +LL | trait Iface<'r>: ConstParamTy_ { | -- the lifetime parameter `'r` is defined here ... LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> @@ -85,7 +85,7 @@ LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: the type of the associated constant `K` must not depend on `Self` - --> $DIR/assoc-const-eq-param-in-ty.rs:44:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 | LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> | ^ its type must not depend on `Self` @@ -94,7 +94,7 @@ LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: the type of the associated constant `K` must not depend on generic parameters - --> $DIR/assoc-const-eq-param-in-ty.rs:44:52 + --> $DIR/assoc-const-eq-param-in-ty.rs:51:52 | LL | type Assoc: Trait<'r, Self, Q, K = { loop {} }> | - ^ its type must not depend on the const parameter `Q` diff --git a/tests/ui/associated-consts/assoc-const-eq-supertraits.rs b/tests/ui/associated-consts/assoc-const-eq-supertraits.rs index 301ddf2d01047..d9b8a8cd43d7d 100644 --- a/tests/ui/associated-consts/assoc-const-eq-supertraits.rs +++ b/tests/ui/associated-consts/assoc-const-eq-supertraits.rs @@ -3,12 +3,19 @@ //@ check-pass -#![feature(associated_const_equality, min_generic_const_args)] +#![feature( + associated_const_equality, + min_generic_const_args, + adt_const_params, + unsized_const_params, +)] #![allow(incomplete_features)] +use std::marker::ConstParamTy_; + trait Trait: SuperTrait {} trait SuperTrait: SuperSuperTrait {} -trait SuperSuperTrait { +trait SuperSuperTrait { #[type_const] const K: T; } diff --git a/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs index febd838e2c2ee..41857eca87de6 100644 --- a/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs +++ b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs @@ -5,7 +5,7 @@ //@ check-pass -#![feature(associated_const_equality, min_generic_const_args)] +#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] trait Trait: SuperTrait { diff --git a/tests/ui/const-generics/const_trait_fn-issue-88433.rs b/tests/ui/const-generics/const_trait_fn-issue-88433.rs index 2f92a528bf728..51c4fefaf70d5 100644 --- a/tests/ui/const-generics/const_trait_fn-issue-88433.rs +++ b/tests/ui/const-generics/const_trait_fn-issue-88433.rs @@ -3,8 +3,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Func { +const trait Func { type Output; fn call_once(self, arg: T) -> Self::Output; diff --git a/tests/ui/const-generics/issues/issue-88119.rs b/tests/ui/const-generics/issues/issue-88119.rs index a49b2ab8b03d1..d44b5ab985b01 100644 --- a/tests/ui/const-generics/issues/issue-88119.rs +++ b/tests/ui/const-generics/issues/issue-88119.rs @@ -3,8 +3,7 @@ #![allow(incomplete_features)] #![feature(const_trait_impl, generic_const_exprs)] -#[const_trait] -trait ConstName { +const trait ConstName { const NAME_BYTES: &'static [u8]; } diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr index 0aabf48011dcd..0bdf153468bcc 100644 --- a/tests/ui/const-generics/issues/issue-88119.stderr +++ b/tests/ui/const-generics/issues/issue-88119.stderr @@ -7,85 +7,85 @@ LL | #![feature(const_trait_impl, generic_const_exprs)] = help: remove one of these features error[E0275]: overflow evaluating the requirement `&T: [const] ConstName` - --> $DIR/issue-88119.rs:19:49 + --> $DIR/issue-88119.rs:18:49 | LL | impl const ConstName for &T | ^^ error[E0275]: overflow evaluating the requirement `&T: ConstName` - --> $DIR/issue-88119.rs:19:49 + --> $DIR/issue-88119.rs:18:49 | LL | impl const ConstName for &T | ^^ error[E0275]: overflow evaluating the requirement `[(); name_len::()] well-formed` - --> $DIR/issue-88119.rs:21:5 + --> $DIR/issue-88119.rs:20:5 | LL | [(); name_len::()]:, | ^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `<&T as ConstName>` - --> $DIR/issue-88119.rs:21:5 + --> $DIR/issue-88119.rs:20:5 | LL | [(); name_len::()]:, | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` error[E0275]: overflow evaluating the requirement `[(); name_len::()] well-formed` - --> $DIR/issue-88119.rs:21:10 + --> $DIR/issue-88119.rs:20:10 | LL | [(); name_len::()]:, | ^^^^^^^^^^^^^^^ | note: required by a bound in `<&T as ConstName>` - --> $DIR/issue-88119.rs:21:5 + --> $DIR/issue-88119.rs:20:5 | LL | [(); name_len::()]:, | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` error[E0275]: overflow evaluating the requirement `&mut T: [const] ConstName` - --> $DIR/issue-88119.rs:26:49 + --> $DIR/issue-88119.rs:25:49 | LL | impl const ConstName for &mut T | ^^^^^^ error[E0275]: overflow evaluating the requirement `&mut T: ConstName` - --> $DIR/issue-88119.rs:26:49 + --> $DIR/issue-88119.rs:25:49 | LL | impl const ConstName for &mut T | ^^^^^^ error[E0275]: overflow evaluating the requirement `[(); name_len::()] well-formed` - --> $DIR/issue-88119.rs:28:5 + --> $DIR/issue-88119.rs:27:5 | LL | [(); name_len::()]:, | ^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `<&mut T as ConstName>` - --> $DIR/issue-88119.rs:28:5 + --> $DIR/issue-88119.rs:27:5 | LL | [(); name_len::()]:, | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` error[E0275]: overflow evaluating the requirement `[(); name_len::()] well-formed` - --> $DIR/issue-88119.rs:28:10 + --> $DIR/issue-88119.rs:27:10 | LL | [(); name_len::()]:, | ^^^^^^^^^^^^^^^ | note: required by a bound in `<&mut T as ConstName>` - --> $DIR/issue-88119.rs:28:5 + --> $DIR/issue-88119.rs:27:5 | LL | [(); name_len::()]:, | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` error[E0275]: overflow evaluating the requirement `&&mut u8: ConstName` - --> $DIR/issue-88119.rs:33:35 + --> $DIR/issue-88119.rs:32:35 | LL | pub const ICE_1: &'static [u8] = <&&mut u8 as ConstName>::NAME_BYTES; | ^^^^^^^^ error[E0275]: overflow evaluating the requirement `&mut &u8: ConstName` - --> $DIR/issue-88119.rs:34:35 + --> $DIR/issue-88119.rs:33:35 | LL | pub const ICE_2: &'static [u8] = <&mut &u8 as ConstName>::NAME_BYTES; | ^^^^^^^^ diff --git a/tests/ui/const-generics/issues/issue-98629.rs b/tests/ui/const-generics/issues/issue-98629.rs index 1d2d3012a6ee1..4d65ce8681958 100644 --- a/tests/ui/const-generics/issues/issue-98629.rs +++ b/tests/ui/const-generics/issues/issue-98629.rs @@ -1,7 +1,6 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Trait { +const trait Trait { const N: usize; } diff --git a/tests/ui/const-generics/issues/issue-98629.stderr b/tests/ui/const-generics/issues/issue-98629.stderr index e7582aaae11aa..3e929356d2cdf 100644 --- a/tests/ui/const-generics/issues/issue-98629.stderr +++ b/tests/ui/const-generics/issues/issue-98629.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `N` - --> $DIR/issue-98629.rs:8:1 + --> $DIR/issue-98629.rs:7:1 | LL | const N: usize; | -------------- `N` from trait diff --git a/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs b/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs new file mode 100644 index 0000000000000..37f9c31feaa55 --- /dev/null +++ b/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs @@ -0,0 +1,26 @@ +//@ check-pass + +#![expect(incomplete_features)] +#![feature(min_generic_const_args, generic_const_items)] + +pub trait Tr { + #[type_const] + const N1: usize; + #[type_const] + const N2: usize; + #[type_const] + const N3: usize; +} + +pub struct S; + +impl Tr for S { + #[type_const] + const N1: usize = 0; + #[type_const] + const N2: usize = 1; + #[type_const] + const N3: usize = 2; +} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs new file mode 100644 index 0000000000000..68aa30bd65bbe --- /dev/null +++ b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs @@ -0,0 +1,17 @@ +// Regression test for #140729 + +#![expect(incomplete_features)] +#![feature(min_generic_const_args)] + +const C: usize = 0; +pub struct A {} +impl A { + fn fun1() {} + //~^ ERROR duplicate definitions with name `fun1` +} +impl A { + //~^ ERROR missing generics for struct `A` + fn fun1() {} +} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr new file mode 100644 index 0000000000000..3d74d1db206e1 --- /dev/null +++ b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr @@ -0,0 +1,29 @@ +error[E0107]: missing generics for struct `A` + --> $DIR/const-arg-coherence-conflicting-methods.rs:12:6 + | +LL | impl A { + | ^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `M` + --> $DIR/const-arg-coherence-conflicting-methods.rs:7:12 + | +LL | pub struct A {} + | ^ -------------- +help: add missing generic argument + | +LL | impl A { + | +++ + +error[E0592]: duplicate definitions with name `fun1` + --> $DIR/const-arg-coherence-conflicting-methods.rs:9:5 + | +LL | fn fun1() {} + | ^^^^^^^^^ duplicate definitions for `fun1` +... +LL | fn fun1() {} + | --------- other definition for `fun1` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0592. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs new file mode 100644 index 0000000000000..8d2eae71d330d --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs @@ -0,0 +1,23 @@ +#![expect(incomplete_features)] +#![feature(min_generic_const_args)] + +#[type_const] +const FREE: u32 = 5_usize; +//~^ ERROR mismatched types + +#[type_const] +const FREE2: isize = FREE; +//~^ ERROR the constant `5` is not of type `isize` + +trait Tr { + #[type_const] + const N: usize; +} + +impl Tr for () { + #[type_const] + const N: usize = false; + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr new file mode 100644 index 0000000000000..4029bb7b6bff2 --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr @@ -0,0 +1,27 @@ +error: the constant `5` is not of type `isize` + --> $DIR/type_const-mismatched-types.rs:9:1 + | +LL | const FREE2: isize = FREE; + | ^^^^^^^^^^^^^^^^^^ expected `isize`, found `u32` + +error[E0308]: mismatched types + --> $DIR/type_const-mismatched-types.rs:5:19 + | +LL | const FREE: u32 = 5_usize; + | ^^^^^^^ expected `u32`, found `usize` + | +help: change the type of the numeric literal from `usize` to `u32` + | +LL - const FREE: u32 = 5_usize; +LL + const FREE: u32 = 5_u32; + | + +error[E0308]: mismatched types + --> $DIR/type_const-mismatched-types.rs:19:22 + | +LL | const N: usize = false; + | ^^^^^ expected `usize`, found `bool` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/type_const-not-constparamty.rs b/tests/ui/const-generics/mgca/type_const-not-constparamty.rs new file mode 100644 index 0000000000000..27b446e6a40d2 --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-not-constparamty.rs @@ -0,0 +1,26 @@ +#![expect(incomplete_features)] +#![feature(min_generic_const_args)] + +struct S; + +// FIXME(mgca): need support for ctors without anon const +// (we use double-braces to trigger an anon const here) +#[type_const] +const FREE: S = { { S } }; +//~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter + +trait Tr { + #[type_const] + const N: S; + //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter +} + +impl Tr for S { + // FIXME(mgca): need support for ctors without anon const + // (we use double-braces to trigger an anon const here) + #[type_const] + const N: S = { { S } }; + //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter +} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr b/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr new file mode 100644 index 0000000000000..6b13917a95cd1 --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr @@ -0,0 +1,39 @@ +error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter + --> $DIR/type_const-not-constparamty.rs:9:13 + | +LL | const FREE: S = { { S } }; + | ^ + | +help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct + | +LL + #[derive(ConstParamTy, PartialEq, Eq)] +LL | struct S; + | + +error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter + --> $DIR/type_const-not-constparamty.rs:22:14 + | +LL | const N: S = { { S } }; + | ^ + | +help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct + | +LL + #[derive(ConstParamTy, PartialEq, Eq)] +LL | struct S; + | + +error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter + --> $DIR/type_const-not-constparamty.rs:14:14 + | +LL | const N: S; + | ^ + | +help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct + | +LL + #[derive(ConstParamTy, PartialEq, Eq)] +LL | struct S; + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs b/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs new file mode 100644 index 0000000000000..d38d5ab7a59f8 --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs @@ -0,0 +1,34 @@ +#![expect(incomplete_features)] +#![feature(min_generic_const_args, generic_const_items)] + +#[type_const] +const FREE1: usize = std::mem::size_of::(); +//~^ ERROR generic parameters may not be used in const operations +#[type_const] +const FREE2: usize = I + 1; +//~^ ERROR generic parameters may not be used in const operations + +pub trait Tr { + #[type_const] + const N1: usize; + #[type_const] + const N2: usize; + #[type_const] + const N3: usize; +} + +pub struct S; + +impl Tr for S { + #[type_const] + const N1: usize = std::mem::size_of::(); + //~^ ERROR generic parameters may not be used in const operations + #[type_const] + const N2: usize = I + 1; + //~^ ERROR generic parameters may not be used in const operations + #[type_const] + const N3: usize = 2 & X; + //~^ ERROR generic parameters may not be used in const operations +} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr new file mode 100644 index 0000000000000..76638f27e96cf --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr @@ -0,0 +1,47 @@ +error: generic parameters may not be used in const operations + --> $DIR/type_const-on-generic-expr.rs:5:45 + | +LL | const FREE1: usize = std::mem::size_of::(); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/type_const-on-generic-expr.rs:8:38 + | +LL | const FREE2: usize = I + 1; + | ^ cannot perform const operation using `I` + | + = help: const parameters may only be used as standalone arguments here, i.e. `I` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/type_const-on-generic-expr.rs:24:46 + | +LL | const N1: usize = std::mem::size_of::(); + | ^ cannot perform const operation using `T` + | + = note: type parameters may not be used in const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/type_const-on-generic-expr.rs:27:39 + | +LL | const N2: usize = I + 1; + | ^ cannot perform const operation using `I` + | + = help: const parameters may only be used as standalone arguments here, i.e. `I` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: generic parameters may not be used in const operations + --> $DIR/type_const-on-generic-expr.rs:30:27 + | +LL | const N3: usize = 2 & X; + | ^ cannot perform const operation using `X` + | + = help: const parameters may only be used as standalone arguments here, i.e. `X` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 5 previous errors + diff --git a/tests/crashes/mgca/type_const-only-in-trait.rs b/tests/ui/const-generics/mgca/type_const-only-in-trait.rs similarity index 73% rename from tests/crashes/mgca/type_const-only-in-trait.rs rename to tests/ui/const-generics/mgca/type_const-only-in-trait.rs index 109cf0ec670c4..8c8ff6259cae5 100644 --- a/tests/crashes/mgca/type_const-only-in-trait.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-trait.rs @@ -1,7 +1,3 @@ -//@ known-bug: #132980 -// Move this test to tests/ui/const-generics/mgca/type_const-only-in-trait.rs -// once fixed. - #![expect(incomplete_features)] #![feature(associated_const_equality, min_generic_const_args)] @@ -14,6 +10,7 @@ struct BadS; impl GoodTr for BadS { const NUM: usize = 42; + //~^ ERROR implementation of `#[type_const]` const must be marked with `#[type_const]` } fn accept_good_tr>(_x: &T) {} diff --git a/tests/ui/const-generics/mgca/type_const-only-in-trait.stderr b/tests/ui/const-generics/mgca/type_const-only-in-trait.stderr new file mode 100644 index 0000000000000..29f1b724960aa --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-only-in-trait.stderr @@ -0,0 +1,16 @@ +error: implementation of `#[type_const]` const must be marked with `#[type_const]` + --> $DIR/type_const-only-in-trait.rs:12:5 + | +LL | const NUM: usize = 42; + | ^^^^^^^^^^^^^^^^ + | +note: trait declaration of const is marked with `#[type_const]` + --> $DIR/type_const-only-in-trait.rs:5:5 + | +LL | #[type_const] + | ^^^^^^^^^^^^^ +LL | const NUM: usize; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/crashes/119783.rs b/tests/ui/const-generics/mgca/using-fnptr-as-type_const.rs similarity index 54% rename from tests/crashes/119783.rs rename to tests/ui/const-generics/mgca/using-fnptr-as-type_const.rs index efde7f89ade2e..554e078ccd49c 100644 --- a/tests/crashes/119783.rs +++ b/tests/ui/const-generics/mgca/using-fnptr-as-type_const.rs @@ -1,9 +1,12 @@ -//@ known-bug: #119783 +// Regression test for #119783 + +#![expect(incomplete_features)] #![feature(associated_const_equality, min_generic_const_args)] trait Trait { #[type_const] const F: fn(); + //~^ ERROR using function pointers as const generic parameters is forbidden } fn take(_: impl Trait) {} diff --git a/tests/ui/const-generics/mgca/using-fnptr-as-type_const.stderr b/tests/ui/const-generics/mgca/using-fnptr-as-type_const.stderr new file mode 100644 index 0000000000000..09d1063081fe1 --- /dev/null +++ b/tests/ui/const-generics/mgca/using-fnptr-as-type_const.stderr @@ -0,0 +1,9 @@ +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/using-fnptr-as-type_const.rs:8:14 + | +LL | const F: fn(); + | ^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/tests/ui/consts/constifconst-call-in-const-position.rs b/tests/ui/consts/constifconst-call-in-const-position.rs index da29030dbc746..3069014088bbb 100644 --- a/tests/ui/consts/constifconst-call-in-const-position.rs +++ b/tests/ui/consts/constifconst-call-in-const-position.rs @@ -3,8 +3,7 @@ #![feature(const_trait_impl, generic_const_exprs)] #![allow(incomplete_features)] -#[const_trait] -pub trait Tr { +pub const trait Tr { fn a() -> usize; } diff --git a/tests/ui/consts/constifconst-call-in-const-position.stderr b/tests/ui/consts/constifconst-call-in-const-position.stderr index e84e686251a5b..70e8ac988e515 100644 --- a/tests/ui/consts/constifconst-call-in-const-position.stderr +++ b/tests/ui/consts/constifconst-call-in-const-position.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: const Tr` is not satisfied - --> $DIR/constifconst-call-in-const-position.rs:17:39 + --> $DIR/constifconst-call-in-const-position.rs:16:39 | LL | const fn foo() -> [u8; T::a()] { | ^ error[E0277]: the trait bound `T: const Tr` is not satisfied - --> $DIR/constifconst-call-in-const-position.rs:18:9 + --> $DIR/constifconst-call-in-const-position.rs:17:9 | LL | [0; T::a()] | ^ diff --git a/tests/ui/delegation/unsupported.current.stderr b/tests/ui/delegation/unsupported.current.stderr index 55564e8f231f7..5c4115630c002 100644 --- a/tests/ui/delegation/unsupported.current.stderr +++ b/tests/ui/delegation/unsupported.current.stderr @@ -46,7 +46,7 @@ LL | reuse to_reuse1::foo; | ^^^ error[E0283]: type annotations needed - --> $DIR/unsupported.rs:56:18 + --> $DIR/unsupported.rs:55:18 | LL | reuse Trait::foo; | ^^^ cannot infer type diff --git a/tests/ui/delegation/unsupported.next.stderr b/tests/ui/delegation/unsupported.next.stderr index 606a25d4269a1..a626da9a1442c 100644 --- a/tests/ui/delegation/unsupported.next.stderr +++ b/tests/ui/delegation/unsupported.next.stderr @@ -38,7 +38,7 @@ LL | reuse to_reuse1::foo; | ^^^ error[E0283]: type annotations needed - --> $DIR/unsupported.rs:56:18 + --> $DIR/unsupported.rs:55:18 | LL | reuse Trait::foo; | ^^^ cannot infer type diff --git a/tests/ui/delegation/unsupported.rs b/tests/ui/delegation/unsupported.rs index 79bab342da091..5e2bd832a4d84 100644 --- a/tests/ui/delegation/unsupported.rs +++ b/tests/ui/delegation/unsupported.rs @@ -48,8 +48,7 @@ mod recursive { } mod effects { - #[const_trait] - trait Trait { + const trait Trait { fn foo(); } diff --git a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs index 57b748a6b4756..7f4926fa2b71f 100644 --- a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs +++ b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs @@ -1,6 +1,6 @@ // ICE: assertion failed: !value.has_infer() // issue: rust-lang/rust#115806 -#![feature(associated_const_equality, min_generic_const_args)] +#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] pub struct NoPin; diff --git a/tests/ui/generic-const-items/associated-const-equality.rs b/tests/ui/generic-const-items/associated-const-equality.rs index 0620998188b26..6f5d4985ae539 100644 --- a/tests/ui/generic-const-items/associated-const-equality.rs +++ b/tests/ui/generic-const-items/associated-const-equality.rs @@ -9,8 +9,8 @@ trait Owner { const C: u32; #[type_const] const K: u32; - #[type_const] - const Q: Maybe; + // #[type_const] + // const Q: Maybe; } impl Owner for () { @@ -18,13 +18,15 @@ impl Owner for () { const C: u32 = N; #[type_const] const K: u32 = 99 + 1; - #[type_const] - const Q: Maybe = Maybe::Nothing; + // FIXME(mgca): re-enable once we properly support ctors and generics on paths + // #[type_const] + // const Q: Maybe = Maybe::Nothing; } fn take0(_: impl Owner = { N }>) {} fn take1(_: impl Owner = 100>) {} -fn take2(_: impl Owner = { Maybe::Just(()) }>) {} +// FIXME(mgca): re-enable once we properly support ctors and generics on paths +// fn take2(_: impl Owner = { Maybe::Just(()) }>) {} fn main() { take0::<128>(()); diff --git a/tests/ui/generic-const-items/const-trait-impl.rs b/tests/ui/generic-const-items/const-trait-impl.rs index e11d346b712d8..197c97ef9fed7 100644 --- a/tests/ui/generic-const-items/const-trait-impl.rs +++ b/tests/ui/generic-const-items/const-trait-impl.rs @@ -11,8 +11,7 @@ const CREATE: T = T::create(); pub const K0: i32 = CREATE::; pub const K1: i32 = CREATE; // arg inferred -#[const_trait] -trait Create { +const trait Create { fn create() -> Self; } @@ -22,7 +21,7 @@ impl const Create for i32 { } } -trait Mod { // doesn't need to be a `#[const_trait]` +trait Mod { // doesn't need to be a const trait const CREATE: T; } diff --git a/tests/ui/parser/impls-nested-within-fns-semantic-1.rs b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs index f06d19d7f5ec6..be8a7ddf26693 100644 --- a/tests/ui/parser/impls-nested-within-fns-semantic-1.rs +++ b/tests/ui/parser/impls-nested-within-fns-semantic-1.rs @@ -4,8 +4,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Trait { +const trait Trait { fn required(); } diff --git a/tests/ui/resolve/issue-39559-2.stderr b/tests/ui/resolve/issue-39559-2.stderr index 4bfa1d1b1322f..27b6020dd1c61 100644 --- a/tests/ui/resolve/issue-39559-2.stderr +++ b/tests/ui/resolve/issue-39559-2.stderr @@ -11,13 +11,12 @@ LL | trait Dim { | ^^^^^^^^^ this trait is not const LL | fn dim() -> usize; | ------------------ this associated function is not const - = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]` + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable const traits = note: calls in constants are limited to constant functions, tuple structs and tuple variants help: consider making trait `Dim` const | -LL + #[const_trait] -LL | trait Dim { - | +LL | const trait Dim { + | +++++ error[E0015]: cannot call non-const associated function `::dim` in constants --> $DIR/issue-39559-2.rs:16:15 @@ -32,13 +31,12 @@ LL | trait Dim { | ^^^^^^^^^ this trait is not const LL | fn dim() -> usize; | ------------------ this associated function is not const - = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]` + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable const traits = note: calls in constants are limited to constant functions, tuple structs and tuple variants help: consider making trait `Dim` const | -LL + #[const_trait] -LL | trait Dim { - | +LL | const trait Dim { + | +++++ error: aborting due to 2 previous errors diff --git a/tests/ui/specialization/const_trait_impl.rs b/tests/ui/specialization/const_trait_impl.rs index e917263d1936a..adfef77a15ca3 100644 --- a/tests/ui/specialization/const_trait_impl.rs +++ b/tests/ui/specialization/const_trait_impl.rs @@ -5,14 +5,12 @@ use std::fmt::Debug; #[rustc_specialization_trait] -#[const_trait] -pub unsafe trait Sup { +pub const unsafe trait Sup { fn foo() -> u32; } #[rustc_specialization_trait] -#[const_trait] -pub unsafe trait Sub: [const] Sup {} +pub const unsafe trait Sub: [const] Sup {} unsafe impl const Sup for u8 { default fn foo() -> u32 { @@ -28,8 +26,7 @@ unsafe impl const Sup for () { unsafe impl const Sub for () {} -#[const_trait] -pub trait A { +pub const trait A { fn a() -> u32; } diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr index a21a48997ee71..93ed7234e5634 100644 --- a/tests/ui/specialization/const_trait_impl.stderr +++ b/tests/ui/specialization/const_trait_impl.stderr @@ -1,5 +1,5 @@ error: `[const]` can only be applied to `const` traits - --> $DIR/const_trait_impl.rs:36:9 + --> $DIR/const_trait_impl.rs:33:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` @@ -8,7 +8,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const` --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL error: `[const]` can only be applied to `const` traits - --> $DIR/const_trait_impl.rs:42:9 + --> $DIR/const_trait_impl.rs:39:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` @@ -17,7 +17,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const` --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL error: `[const]` can only be applied to `const` traits - --> $DIR/const_trait_impl.rs:48:9 + --> $DIR/const_trait_impl.rs:45:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` @@ -26,7 +26,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const` --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL error: `[const]` can only be applied to `const` traits - --> $DIR/const_trait_impl.rs:42:9 + --> $DIR/const_trait_impl.rs:39:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` @@ -36,7 +36,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `[const]` can only be applied to `const` traits - --> $DIR/const_trait_impl.rs:36:9 + --> $DIR/const_trait_impl.rs:33:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` @@ -46,7 +46,7 @@ note: `Debug` can't be used with `[const]` because it isn't `const` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `[const]` can only be applied to `const` traits - --> $DIR/const_trait_impl.rs:48:9 + --> $DIR/const_trait_impl.rs:45:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` diff --git a/tests/ui/structs/default-field-values/support.rs b/tests/ui/structs/default-field-values/support.rs index 8209d6dd4a093..670557e12c110 100644 --- a/tests/ui/structs/default-field-values/support.rs +++ b/tests/ui/structs/default-field-values/support.rs @@ -27,7 +27,7 @@ pub enum Bar { } } -#[const_trait] pub trait ConstDefault { +pub const trait ConstDefault { fn value() -> Self; } diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs index ff1ce949f097d..0bda247d5f4eb 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs @@ -4,8 +4,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Trait { +const trait Trait { type Assoc: [const] Trait; fn func() -> i32; } diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs index 5773f2281c390..2498a1ad03bf7 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-1.rs @@ -3,8 +3,7 @@ #![feature(const_trait_impl, generic_const_exprs)] #![allow(incomplete_features)] -#[const_trait] -trait Trait { +const trait Trait { type Assoc: [const] Trait; fn func() -> i32; } diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr index a0474e65efeba..3976c71899e6b 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `U: [const] Other` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5 + --> $DIR/assoc-type-const-bound-usage-fail-2.rs:22:5 | LL | T::Assoc::::func(); | ^^^^^^^^^^^^^ error[E0277]: the trait bound `U: [const] Other` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5 + --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5 | LL | ::Assoc::::func(); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr index a0474e65efeba..3976c71899e6b 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `U: [const] Other` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5 + --> $DIR/assoc-type-const-bound-usage-fail-2.rs:22:5 | LL | T::Assoc::::func(); | ^^^^^^^^^^^^^ error[E0277]: the trait bound `U: [const] Other` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5 + --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5 | LL | ::Assoc::::func(); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs index 5338c27bedca5..a817fff36fa64 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs @@ -8,8 +8,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Trait { +const trait Trait { type Assoc: [const] Trait where U: [const] Other; @@ -17,8 +16,7 @@ trait Trait { fn func(); } -#[const_trait] -trait Other {} +const trait Other {} const fn fails() { T::Assoc::::func(); diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.current.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.current.stderr index 20b01d06e8d5e..1f0248365ce6e 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.current.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: [const] Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail.rs:17:5 + --> $DIR/assoc-type-const-bound-usage-fail.rs:16:5 | LL | T::Assoc::func(); | ^^^^^^^^ error[E0277]: the trait bound `T: [const] Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail.rs:19:5 + --> $DIR/assoc-type-const-bound-usage-fail.rs:18:5 | LL | ::Assoc::func(); | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr index 20b01d06e8d5e..1f0248365ce6e 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: [const] Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail.rs:17:5 + --> $DIR/assoc-type-const-bound-usage-fail.rs:16:5 | LL | T::Assoc::func(); | ^^^^^^^^ error[E0277]: the trait bound `T: [const] Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail.rs:19:5 + --> $DIR/assoc-type-const-bound-usage-fail.rs:18:5 | LL | ::Assoc::func(); | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs index 4940b3a1aa6ce..65c3a06e89c2d 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs @@ -7,8 +7,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Trait { +const trait Trait { type Assoc: [const] Trait; fn func(); } diff --git a/tests/ui/traits/const-traits/assoc-type.current.stderr b/tests/ui/traits/const-traits/assoc-type.current.stderr index 7fe086550f1c2..b730fd8ad3662 100644 --- a/tests/ui/traits/const-traits/assoc-type.current.stderr +++ b/tests/ui/traits/const-traits/assoc-type.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `NonConstAdd: [const] Add` is not satisfied - --> $DIR/assoc-type.rs:37:16 + --> $DIR/assoc-type.rs:35:16 | LL | type Bar = NonConstAdd; | ^^^^^^^^^^^ | note: required by a bound in `Foo::Bar` - --> $DIR/assoc-type.rs:33:15 + --> $DIR/assoc-type.rs:31:15 | LL | type Bar: [const] Add; | ^^^^^^^^^^^ required by this bound in `Foo::Bar` diff --git a/tests/ui/traits/const-traits/assoc-type.next.stderr b/tests/ui/traits/const-traits/assoc-type.next.stderr index 7fe086550f1c2..b730fd8ad3662 100644 --- a/tests/ui/traits/const-traits/assoc-type.next.stderr +++ b/tests/ui/traits/const-traits/assoc-type.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `NonConstAdd: [const] Add` is not satisfied - --> $DIR/assoc-type.rs:37:16 + --> $DIR/assoc-type.rs:35:16 | LL | type Bar = NonConstAdd; | ^^^^^^^^^^^ | note: required by a bound in `Foo::Bar` - --> $DIR/assoc-type.rs:33:15 + --> $DIR/assoc-type.rs:31:15 | LL | type Bar: [const] Add; | ^^^^^^^^^^^ required by this bound in `Foo::Bar` diff --git a/tests/ui/traits/const-traits/assoc-type.rs b/tests/ui/traits/const-traits/assoc-type.rs index 1faef1b0a3251..3fb6f679a1933 100644 --- a/tests/ui/traits/const-traits/assoc-type.rs +++ b/tests/ui/traits/const-traits/assoc-type.rs @@ -3,8 +3,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Add { +const trait Add { type Output; fn add(self, other: Rhs) -> Self::Output; @@ -28,8 +27,7 @@ impl Add for NonConstAdd { } } -#[const_trait] -trait Foo { +const trait Foo { type Bar: [const] Add; } @@ -38,8 +36,7 @@ impl const Foo for NonConstAdd { //~^ ERROR the trait bound `NonConstAdd: [const] Add` is not satisfied } -#[const_trait] -trait Baz { +const trait Baz { type Qux: Add; } diff --git a/tests/ui/traits/const-traits/attr-misuse.rs b/tests/ui/traits/const-traits/attr-misuse.rs deleted file mode 100644 index 70dfcbf47d289..0000000000000 --- a/tests/ui/traits/const-traits/attr-misuse.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(const_trait_impl)] - -#[const_trait] -trait A { - #[const_trait] //~ ERROR attribute cannot be used on - fn foo(self); -} - -#[const_trait] //~ ERROR attribute cannot be used on -fn main() {} diff --git a/tests/ui/traits/const-traits/attr-misuse.stderr b/tests/ui/traits/const-traits/attr-misuse.stderr deleted file mode 100644 index 2f86efac4c921..0000000000000 --- a/tests/ui/traits/const-traits/attr-misuse.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: `#[const_trait]` attribute cannot be used on required trait methods - --> $DIR/attr-misuse.rs:5:5 - | -LL | #[const_trait] - | ^^^^^^^^^^^^^^ - | - = help: `#[const_trait]` can only be applied to traits - -error: `#[const_trait]` attribute cannot be used on functions - --> $DIR/attr-misuse.rs:9:1 - | -LL | #[const_trait] - | ^^^^^^^^^^^^^^ - | - = help: `#[const_trait]` can only be applied to traits - -error: aborting due to 2 previous errors - diff --git a/tests/ui/traits/const-traits/auxiliary/cross-crate.rs b/tests/ui/traits/const-traits/auxiliary/cross-crate.rs index 01921c140cbcf..7d464d57c3651 100644 --- a/tests/ui/traits/const-traits/auxiliary/cross-crate.rs +++ b/tests/ui/traits/const-traits/auxiliary/cross-crate.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -pub trait MyTrait { +pub const trait MyTrait { fn defaulted_func(&self) {} fn func(self); } diff --git a/tests/ui/traits/const-traits/auxiliary/minicore.rs b/tests/ui/traits/const-traits/auxiliary/minicore.rs index d2133bbbcaea4..2e5df13d021d5 100644 --- a/tests/ui/traits/const-traits/auxiliary/minicore.rs +++ b/tests/ui/traits/const-traits/auxiliary/minicore.rs @@ -35,8 +35,7 @@ impl Copy for u8 {} impl Copy for &T {} #[lang = "add"] -#[const_trait] -pub trait Add { +pub const trait Add { type Output; fn add(self, rhs: Rhs) -> Self::Output; @@ -58,8 +57,7 @@ const fn bar() { } #[lang = "Try"] -#[const_trait] -pub trait Try: FromResidual { +pub const trait Try: FromResidual { type Output; type Residual; @@ -70,8 +68,7 @@ pub trait Try: FromResidual { fn branch(self) -> ControlFlow; } -#[const_trait] -pub trait FromResidual::Residual> { +pub const trait FromResidual::Residual> { #[lang = "from_residual"] fn from_residual(residual: R) -> Self; } @@ -83,24 +80,21 @@ enum ControlFlow { Break(B), } -#[const_trait] #[lang = "fn"] #[rustc_paren_sugar] -pub trait Fn: [const] FnMut { +pub const trait Fn: [const] FnMut { extern "rust-call" fn call(&self, args: Args) -> Self::Output; } -#[const_trait] #[lang = "fn_mut"] #[rustc_paren_sugar] -pub trait FnMut: [const] FnOnce { +pub const trait FnMut: [const] FnOnce { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; } -#[const_trait] #[lang = "fn_once"] #[rustc_paren_sugar] -pub trait FnOnce { +pub const trait FnOnce { #[lang = "fn_once_output"] type Output; @@ -128,20 +122,17 @@ impl Receiver for T { } #[lang = "destruct"] -#[const_trait] -pub trait Destruct {} +pub const trait Destruct {} #[lang = "freeze"] pub unsafe auto trait Freeze {} #[lang = "drop"] -#[const_trait] -pub trait Drop { +pub const trait Drop { fn drop(&mut self); } -#[const_trait] -pub trait Residual { +pub const trait Residual { type TryType: [const] Try + Try; } @@ -168,15 +159,13 @@ const fn panic_display() { fn panic_fmt() {} #[lang = "index"] -#[const_trait] -pub trait Index { +pub const trait Index { type Output: MetaSized; fn index(&self, index: Idx) -> &Self::Output; } -#[const_trait] -pub unsafe trait SliceIndex { +pub const unsafe trait SliceIndex { type Output: MetaSized; fn index(self, slice: &T) -> &Self::Output; } @@ -214,8 +203,7 @@ pub trait CoerceUnsized {} impl<'a, 'b: 'a, T: PointeeSized + Unsize, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {} #[lang = "deref"] -#[const_trait] -pub trait Deref { +pub const trait Deref { #[lang = "deref_target"] type Target: MetaSized; @@ -273,13 +261,11 @@ where } } -#[const_trait] -pub trait Into: Sized { +pub const trait Into: Sized { fn into(self) -> T; } -#[const_trait] -pub trait From: Sized { +pub const trait From: Sized { fn from(value: T) -> Self; } @@ -313,8 +299,7 @@ fn from_str(s: &str) -> Result { } #[lang = "eq"] -#[const_trait] -pub trait PartialEq: PointeeSized { +pub const trait PartialEq: PointeeSized { fn eq(&self, other: &Rhs) -> bool; fn ne(&self, other: &Rhs) -> bool { !self.eq(other) @@ -337,8 +322,7 @@ impl PartialEq for str { } #[lang = "not"] -#[const_trait] -pub trait Not { +pub const trait Not { type Output; fn not(self) -> Self::Output; } @@ -462,8 +446,7 @@ impl Deref for Ref<'_, T> { #[lang = "clone"] #[rustc_trivial_field_reads] -#[const_trait] -pub trait Clone: Sized { +pub const trait Clone: Sized { fn clone(&self) -> Self; fn clone_from(&mut self, source: &Self) where diff --git a/tests/ui/traits/const-traits/auxiliary/staged-api.rs b/tests/ui/traits/const-traits/auxiliary/staged-api.rs index 933a25769dca2..b2b1e0615c37f 100644 --- a/tests/ui/traits/const-traits/auxiliary/staged-api.rs +++ b/tests/ui/traits/const-traits/auxiliary/staged-api.rs @@ -5,8 +5,7 @@ #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "unstable", issue = "none")] -#[const_trait] -pub trait MyTrait { +pub const trait MyTrait { #[stable(feature = "rust1", since = "1.0.0")] fn func(); } diff --git a/tests/ui/traits/const-traits/call-const-closure.rs b/tests/ui/traits/const-traits/call-const-closure.rs index 70dfaf724c9bd..c4293579aea8e 100644 --- a/tests/ui/traits/const-traits/call-const-closure.rs +++ b/tests/ui/traits/const-traits/call-const-closure.rs @@ -4,8 +4,7 @@ #![feature(const_trait_impl, const_closures)] #![allow(incomplete_features)] -#[const_trait] -trait Bar { +const trait Bar { fn foo(&self); } diff --git a/tests/ui/traits/const-traits/call-const-closure.stderr b/tests/ui/traits/const-traits/call-const-closure.stderr index 9de22759c2003..9a851a97f186a 100644 --- a/tests/ui/traits/const-traits/call-const-closure.stderr +++ b/tests/ui/traits/const-traits/call-const-closure.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): [const] Bar` is not satisfied - --> $DIR/call-const-closure.rs:17:18 + --> $DIR/call-const-closure.rs:16:18 | LL | (const || ().foo())(); | ^^^ diff --git a/tests/ui/traits/const-traits/call-const-in-conditionally-const.rs b/tests/ui/traits/const-traits/call-const-in-conditionally-const.rs index 4e8c2cd171e6c..52d25b85c01dc 100644 --- a/tests/ui/traits/const-traits/call-const-in-conditionally-const.rs +++ b/tests/ui/traits/const-traits/call-const-in-conditionally-const.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] trait Foo { +const trait Foo { fn foo(); } diff --git a/tests/ui/traits/const-traits/call-const-trait-method-fail.rs b/tests/ui/traits/const-traits/call-const-trait-method-fail.rs index c03d3e950b0b4..bb481d0d9ea94 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-fail.rs +++ b/tests/ui/traits/const-traits/call-const-trait-method-fail.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -pub trait Plus { +pub const trait Plus { fn plus(self, rhs: Self) -> Self; } diff --git a/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr index c6f93629379ac..6e235d9cb6f0c 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr +++ b/tests/ui/traits/const-traits/call-const-trait-method-fail.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `u32: [const] Plus` is not satisfied - --> $DIR/call-const-trait-method-fail.rs:26:5 + --> $DIR/call-const-trait-method-fail.rs:25:5 | LL | a.plus(b) | ^ diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.rs b/tests/ui/traits/const-traits/call-const-trait-method-pass.rs index 2d9c2ca086178..b12e7e82664b7 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-pass.rs +++ b/tests/ui/traits/const-traits/call-const-trait-method-pass.rs @@ -20,8 +20,7 @@ impl const PartialEq for Int { } } -#[const_trait] -pub trait Plus { +pub const trait Plus { fn plus(self, rhs: Self) -> Self; } diff --git a/tests/ui/traits/const-traits/call-generic-in-impl.rs b/tests/ui/traits/const-traits/call-generic-in-impl.rs index 72fc80c50e02a..4ed937eacaca4 100644 --- a/tests/ui/traits/const-traits/call-generic-in-impl.rs +++ b/tests/ui/traits/const-traits/call-generic-in-impl.rs @@ -1,8 +1,7 @@ //@ check-pass #![feature(const_trait_impl, const_cmp)] -#[const_trait] -trait MyPartialEq { +const trait MyPartialEq { fn eq(&self, other: &Self) -> bool; } diff --git a/tests/ui/traits/const-traits/call-generic-method-nonconst.rs b/tests/ui/traits/const-traits/call-generic-method-nonconst.rs index 0efc8a954dedb..e23c4d646b7cf 100644 --- a/tests/ui/traits/const-traits/call-generic-method-nonconst.rs +++ b/tests/ui/traits/const-traits/call-generic-method-nonconst.rs @@ -3,8 +3,7 @@ struct S; -#[const_trait] -trait Foo { +const trait Foo { fn eq(&self, _: &Self) -> bool; } diff --git a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr index b2ec41182a83b..91d3918372601 100644 --- a/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-nonconst.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `S: const Foo` is not satisfied - --> $DIR/call-generic-method-nonconst.rs:24:34 + --> $DIR/call-generic-method-nonconst.rs:23:34 | LL | pub const EQ: bool = equals_self(&S); | ----------- ^^ @@ -7,7 +7,7 @@ LL | pub const EQ: bool = equals_self(&S); | required by a bound introduced by this call | note: required by a bound in `equals_self` - --> $DIR/call-generic-method-nonconst.rs:17:25 + --> $DIR/call-generic-method-nonconst.rs:16:25 | LL | const fn equals_self(t: &T) -> bool { | ^^^^^^^^^^^ required by this bound in `equals_self` diff --git a/tests/ui/traits/const-traits/conditionally-const-and-const-params.rs b/tests/ui/traits/const-traits/conditionally-const-and-const-params.rs index 29553884b21c2..2241f70cf21e1 100644 --- a/tests/ui/traits/const-traits/conditionally-const-and-const-params.rs +++ b/tests/ui/traits/const-traits/conditionally-const-and-const-params.rs @@ -12,8 +12,7 @@ impl Foo { } } -#[const_trait] -trait Add42 { +const trait Add42 { fn add(a: usize) -> usize; } diff --git a/tests/ui/traits/const-traits/conditionally-const-and-const-params.stderr b/tests/ui/traits/const-traits/conditionally-const-and-const-params.stderr index ebd816ac9a54f..81eff253d7177 100644 --- a/tests/ui/traits/const-traits/conditionally-const-and-const-params.stderr +++ b/tests/ui/traits/const-traits/conditionally-const-and-const-params.stderr @@ -11,19 +11,19 @@ LL | fn add(self) -> Foo<{ A::add(N) }> { | ^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-and-const-params.rs:26:11 + --> $DIR/conditionally-const-and-const-params.rs:25:11 | LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { | ^^^^^^^ | note: this function is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/conditionally-const-and-const-params.rs:26:4 + --> $DIR/conditionally-const-and-const-params.rs:25:4 | LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { | ^^^ error[E0277]: the trait bound `A: const Add42` is not satisfied - --> $DIR/conditionally-const-and-const-params.rs:26:62 + --> $DIR/conditionally-const-and-const-params.rs:25:62 | LL | fn bar(_: Foo) -> Foo<{ A::add(N) }> { | ^ diff --git a/tests/ui/traits/const-traits/conditionally-const-assoc-fn-in-trait-impl.rs b/tests/ui/traits/const-traits/conditionally-const-assoc-fn-in-trait-impl.rs index 7f01c0b7a5c96..11ff1ddb79535 100644 --- a/tests/ui/traits/const-traits/conditionally-const-assoc-fn-in-trait-impl.rs +++ b/tests/ui/traits/const-traits/conditionally-const-assoc-fn-in-trait-impl.rs @@ -3,8 +3,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -trait Main { +const trait Main { fn compute() -> u32; } @@ -14,8 +13,7 @@ impl const Main for () { } } -#[const_trait] -trait Aux { +const trait Aux { fn generate() -> u32; } diff --git a/tests/ui/traits/const-traits/conditionally-const-in-anon-const.rs b/tests/ui/traits/const-traits/conditionally-const-in-anon-const.rs index 5aebcceb7c75d..21419be29591f 100644 --- a/tests/ui/traits/const-traits/conditionally-const-in-anon-const.rs +++ b/tests/ui/traits/const-traits/conditionally-const-in-anon-const.rs @@ -1,8 +1,7 @@ #![feature(const_trait_impl, impl_trait_in_bindings)] struct S; -#[const_trait] -trait Trait {} +const trait Trait {} impl const Trait<0> for () {} diff --git a/tests/ui/traits/const-traits/conditionally-const-in-anon-const.stderr b/tests/ui/traits/const-traits/conditionally-const-in-anon-const.stderr index c6be249b95a22..94b8ea0970dd9 100644 --- a/tests/ui/traits/const-traits/conditionally-const-in-anon-const.stderr +++ b/tests/ui/traits/const-traits/conditionally-const-in-anon-const.stderr @@ -1,23 +1,23 @@ error: `[const]` is not allowed here - --> $DIR/conditionally-const-in-anon-const.rs:14:25 + --> $DIR/conditionally-const-in-anon-const.rs:13:25 | LL | struct I>(U); | ^^^^^^^ | note: structs cannot have `[const]` trait bounds - --> $DIR/conditionally-const-in-anon-const.rs:14:13 + --> $DIR/conditionally-const-in-anon-const.rs:13:13 | LL | struct I>(U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-in-anon-const.rs:17:26 + --> $DIR/conditionally-const-in-anon-const.rs:16:26 | LL | let x: &impl [const] Trait<0> = &(); | ^^^^^^^ | note: anonymous constants cannot have `[const]` trait bounds - --> $DIR/conditionally-const-in-anon-const.rs:11:9 + --> $DIR/conditionally-const-in-anon-const.rs:10:9 | LL | / { LL | | const fn g>() {} diff --git a/tests/ui/traits/const-traits/conditionally-const-inherent-assoc-const-fn.rs b/tests/ui/traits/const-traits/conditionally-const-inherent-assoc-const-fn.rs index 56478a6674b0e..083885837cff4 100644 --- a/tests/ui/traits/const-traits/conditionally-const-inherent-assoc-const-fn.rs +++ b/tests/ui/traits/const-traits/conditionally-const-inherent-assoc-const-fn.rs @@ -2,8 +2,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -trait Foo { +const trait Foo { fn foo(&self) {} } diff --git a/tests/ui/traits/const-traits/conditionally-const-invalid-places.rs b/tests/ui/traits/const-traits/conditionally-const-invalid-places.rs index 52627004fb246..5e13097b3fa21 100644 --- a/tests/ui/traits/const-traits/conditionally-const-invalid-places.rs +++ b/tests/ui/traits/const-traits/conditionally-const-invalid-places.rs @@ -1,7 +1,6 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Trait {} +const trait Trait {} // Regression test for issue #90052. fn non_const_function() {} //~ ERROR `[const]` is not allowed diff --git a/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr b/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr index 5c3bb2369675e..52b62e7aaccc8 100644 --- a/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr +++ b/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr @@ -1,77 +1,77 @@ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:7:26 + --> $DIR/conditionally-const-invalid-places.rs:6:26 | LL | fn non_const_function() {} | ^^^^^^^ | note: this function is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:7:4 + --> $DIR/conditionally-const-invalid-places.rs:6:4 | LL | fn non_const_function() {} | ^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:9:18 + --> $DIR/conditionally-const-invalid-places.rs:8:18 | LL | struct Struct { field: T } | ^^^^^^^ | note: structs cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:9:1 + --> $DIR/conditionally-const-invalid-places.rs:8:1 | LL | struct Struct { field: T } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:10:23 + --> $DIR/conditionally-const-invalid-places.rs:9:23 | LL | struct TupleStruct(T); | ^^^^^^^ | note: structs cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:10:1 + --> $DIR/conditionally-const-invalid-places.rs:9:1 | LL | struct TupleStruct(T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:11:22 + --> $DIR/conditionally-const-invalid-places.rs:10:22 | LL | struct UnitStruct; | ^^^^^^^ | note: structs cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:11:1 + --> $DIR/conditionally-const-invalid-places.rs:10:1 | LL | struct UnitStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:14:14 + --> $DIR/conditionally-const-invalid-places.rs:13:14 | LL | enum Enum { Variant(T) } | ^^^^^^^ | note: enums cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:14:1 + --> $DIR/conditionally-const-invalid-places.rs:13:1 | LL | enum Enum { Variant(T) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:16:16 + --> $DIR/conditionally-const-invalid-places.rs:15:16 | LL | union Union { field: T } | ^^^^^^^ | note: unions cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:16:1 + --> $DIR/conditionally-const-invalid-places.rs:15:1 | LL | union Union { field: T } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:19:14 + --> $DIR/conditionally-const-invalid-places.rs:18:14 | LL | type Type = T; | ^^^^^^^ @@ -79,7 +79,7 @@ LL | type Type = T; = note: this item cannot have `[const]` trait bounds error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:21:19 + --> $DIR/conditionally-const-invalid-places.rs:20:19 | LL | const CONSTANT: () = (); | ^^^^^^^ @@ -87,43 +87,43 @@ LL | const CONSTANT: () = (); = note: this item cannot have `[const]` trait bounds error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:25:18 + --> $DIR/conditionally-const-invalid-places.rs:24:18 | LL | type Type: [const] Trait; | ^^^^^^^ | note: associated types in non-`const` traits cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:25:5 + --> $DIR/conditionally-const-invalid-places.rs:24:5 | LL | type Type: [const] Trait; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:25:34 + --> $DIR/conditionally-const-invalid-places.rs:24:34 | LL | type Type: [const] Trait; | ^^^^^^^ | note: associated types in non-`const` traits cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:25:5 + --> $DIR/conditionally-const-invalid-places.rs:24:5 | LL | type Type: [const] Trait; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:28:30 + --> $DIR/conditionally-const-invalid-places.rs:27:30 | LL | fn non_const_function(); | ^^^^^^^ | note: this function is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:28:8 + --> $DIR/conditionally-const-invalid-places.rs:27:8 | LL | fn non_const_function(); | ^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:29:23 + --> $DIR/conditionally-const-invalid-places.rs:28:23 | LL | const CONSTANT: (); | ^^^^^^^ @@ -131,31 +131,31 @@ LL | const CONSTANT: (); = note: this item cannot have `[const]` trait bounds error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:34:18 + --> $DIR/conditionally-const-invalid-places.rs:33:18 | LL | type Type = (); | ^^^^^^^ | note: associated types in non-const impls cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:34:5 + --> $DIR/conditionally-const-invalid-places.rs:33:5 | LL | type Type = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:36:30 + --> $DIR/conditionally-const-invalid-places.rs:35:30 | LL | fn non_const_function() {} | ^^^^^^^ | note: this function is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:36:8 + --> $DIR/conditionally-const-invalid-places.rs:35:8 | LL | fn non_const_function() {} | ^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:37:23 + --> $DIR/conditionally-const-invalid-places.rs:36:23 | LL | const CONSTANT: () = (); | ^^^^^^^ @@ -163,31 +163,31 @@ LL | const CONSTANT: () = (); = note: this item cannot have `[const]` trait bounds error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:44:18 + --> $DIR/conditionally-const-invalid-places.rs:43:18 | LL | type Type = (); | ^^^^^^^ | note: inherent associated types cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:44:5 + --> $DIR/conditionally-const-invalid-places.rs:43:5 | LL | type Type = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:46:30 + --> $DIR/conditionally-const-invalid-places.rs:45:30 | LL | fn non_const_function() {} | ^^^^^^^ | note: this function is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:46:8 + --> $DIR/conditionally-const-invalid-places.rs:45:8 | LL | fn non_const_function() {} | ^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:47:23 + --> $DIR/conditionally-const-invalid-places.rs:46:23 | LL | const CONSTANT: () = (); | ^^^^^^^ @@ -195,55 +195,55 @@ LL | const CONSTANT: () = (); = note: this item cannot have `[const]` trait bounds error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:52:15 + --> $DIR/conditionally-const-invalid-places.rs:51:15 | LL | trait Child0: [const] Trait {} | ^^^^^^^ | note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:52:1 + --> $DIR/conditionally-const-invalid-places.rs:51:1 | LL | trait Child0: [const] Trait {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:53:26 + --> $DIR/conditionally-const-invalid-places.rs:52:26 | LL | trait Child1 where Self: [const] Trait {} | ^^^^^^^ | note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:53:1 + --> $DIR/conditionally-const-invalid-places.rs:52:1 | LL | trait Child1 where Self: [const] Trait {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:56:9 + --> $DIR/conditionally-const-invalid-places.rs:55:9 | LL | impl Trait for T {} | ^^^^^^^ | note: this impl is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:56:1 + --> $DIR/conditionally-const-invalid-places.rs:55:1 | LL | impl Trait for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/conditionally-const-invalid-places.rs:59:9 + --> $DIR/conditionally-const-invalid-places.rs:58:9 | LL | impl Struct {} | ^^^^^^^ | note: inherent impls cannot have `[const]` trait bounds - --> $DIR/conditionally-const-invalid-places.rs:59:1 + --> $DIR/conditionally-const-invalid-places.rs:58:1 | LL | impl Struct {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0658]: generic const items are experimental - --> $DIR/conditionally-const-invalid-places.rs:21:15 + --> $DIR/conditionally-const-invalid-places.rs:20:15 | LL | const CONSTANT: () = (); | ^^^^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL | const CONSTANT: () = (); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: generic const items are experimental - --> $DIR/conditionally-const-invalid-places.rs:29:19 + --> $DIR/conditionally-const-invalid-places.rs:28:19 | LL | const CONSTANT: (); | ^^^^^^^^^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | const CONSTANT: (); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: generic const items are experimental - --> $DIR/conditionally-const-invalid-places.rs:37:19 + --> $DIR/conditionally-const-invalid-places.rs:36:19 | LL | const CONSTANT: () = (); | ^^^^^^^^^^^^^^^^^^ @@ -273,7 +273,7 @@ LL | const CONSTANT: () = (); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: generic const items are experimental - --> $DIR/conditionally-const-invalid-places.rs:47:19 + --> $DIR/conditionally-const-invalid-places.rs:46:19 | LL | const CONSTANT: () = (); | ^^^^^^^^^^^^^^^^^^ @@ -283,7 +283,7 @@ LL | const CONSTANT: () = (); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0392]: type parameter `T` is never used - --> $DIR/conditionally-const-invalid-places.rs:11:19 + --> $DIR/conditionally-const-invalid-places.rs:10:19 | LL | struct UnitStruct; | ^ unused type parameter @@ -291,7 +291,7 @@ LL | struct UnitStruct; = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union - --> $DIR/conditionally-const-invalid-places.rs:16:33 + --> $DIR/conditionally-const-invalid-places.rs:15:33 | LL | union Union { field: T } | ^^^^^^^^ @@ -303,19 +303,19 @@ LL | union Union { field: std::mem::ManuallyDrop } | +++++++++++++++++++++++ + error[E0275]: overflow evaluating the requirement `(): Trait` - --> $DIR/conditionally-const-invalid-places.rs:34:35 + --> $DIR/conditionally-const-invalid-places.rs:33:35 | LL | type Type = (); | ^^ | note: required by a bound in `NonConstTrait::Type` - --> $DIR/conditionally-const-invalid-places.rs:25:34 + --> $DIR/conditionally-const-invalid-places.rs:24:34 | LL | type Type: [const] Trait; | ^^^^^^^^^^^^^ required by this bound in `NonConstTrait::Type` error[E0658]: inherent associated types are unstable - --> $DIR/conditionally-const-invalid-places.rs:44:5 + --> $DIR/conditionally-const-invalid-places.rs:43:5 | LL | type Type = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/conditionally-const-trait-bound-assoc-tys.rs b/tests/ui/traits/const-traits/conditionally-const-trait-bound-assoc-tys.rs index b0bd8466f66b9..dfb828623ee68 100644 --- a/tests/ui/traits/const-traits/conditionally-const-trait-bound-assoc-tys.rs +++ b/tests/ui/traits/const-traits/conditionally-const-trait-bound-assoc-tys.rs @@ -2,8 +2,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -trait Trait { +const trait Trait { type Assoc; } @@ -11,7 +10,6 @@ impl const Trait for () { type Assoc = T; } -#[const_trait] -trait Bound {} +const trait Bound {} fn main() {} diff --git a/tests/ui/traits/const-traits/const-assoc-bound-in-trait-wc.rs b/tests/ui/traits/const-traits/const-assoc-bound-in-trait-wc.rs index 81acce65f2a9d..ccc6e0e4d51d8 100644 --- a/tests/ui/traits/const-traits/const-assoc-bound-in-trait-wc.rs +++ b/tests/ui/traits/const-traits/const-assoc-bound-in-trait-wc.rs @@ -3,8 +3,7 @@ #![feature(const_clone)] #![feature(const_trait_impl)] -#[const_trait] -trait A where Self::Target: [const] Clone { +const trait A where Self::Target: [const] Clone { type Target; } diff --git a/tests/ui/traits/const-traits/const-bound-in-host.rs b/tests/ui/traits/const-traits/const-bound-in-host.rs index b4c4f5a6de1d0..a6f607617f15c 100644 --- a/tests/ui/traits/const-traits/const-bound-in-host.rs +++ b/tests/ui/traits/const-traits/const-bound-in-host.rs @@ -3,7 +3,7 @@ #![feature(const_trait_impl)] -#[const_trait] trait Foo { +const trait Foo { fn foo(); } diff --git a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs index 9411127270833..9b2e93fa0dede 100644 --- a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs +++ b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.rs @@ -2,8 +2,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait MyTrait { +const trait MyTrait { fn do_something(&self); } diff --git a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr index 901c2cbd8a712..55106cf431159 100644 --- a/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr +++ b/tests/ui/traits/const-traits/const-bound-on-not-const-associated-fn.stderr @@ -1,23 +1,23 @@ error: `[const]` is not allowed here - --> $DIR/const-bound-on-not-const-associated-fn.rs:11:40 + --> $DIR/const-bound-on-not-const-associated-fn.rs:10:40 | LL | fn do_something_else() where Self: [const] MyTrait; | ^^^^^^^ | note: this function is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/const-bound-on-not-const-associated-fn.rs:11:8 + --> $DIR/const-bound-on-not-const-associated-fn.rs:10:8 | LL | fn do_something_else() where Self: [const] MyTrait; | ^^^^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/const-bound-on-not-const-associated-fn.rs:22:32 + --> $DIR/const-bound-on-not-const-associated-fn.rs:21:32 | LL | pub fn foo(&self) where T: [const] MyTrait { | ^^^^^^^ | note: this function is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/const-bound-on-not-const-associated-fn.rs:22:12 + --> $DIR/const-bound-on-not-const-associated-fn.rs:21:12 | LL | pub fn foo(&self) where T: [const] MyTrait { | ^^^ diff --git a/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr index 304d81bb91711..9990d1b3b9e56 100644 --- a/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr +++ b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr @@ -6,8 +6,8 @@ LL | const fn perform() {} | help: mark `NonConst` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait NonConst {} - | ++++++++++++++ +LL | const trait NonConst {} + | +++++ error: `[const]` can only be applied to `const` traits --> $DIR/const-bounds-non-const-trait.rs:6:21 @@ -18,8 +18,8 @@ LL | const fn perform() {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `NonConst` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait NonConst {} - | ++++++++++++++ +LL | const trait NonConst {} + | +++++ error: `const` can only be applied to `const` traits --> $DIR/const-bounds-non-const-trait.rs:10:15 @@ -29,8 +29,8 @@ LL | fn operate() {} | help: mark `NonConst` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait NonConst {} - | ++++++++++++++ +LL | const trait NonConst {} + | +++++ error: aborting due to 3 previous errors diff --git a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs index f7686ea6139b5..f80e379a13174 100644 --- a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs +++ b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.rs @@ -3,8 +3,7 @@ #![feature(const_trait_impl)] struct S; -#[const_trait] -trait T { +const trait T { fn foo(); } diff --git a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr index 1a7ec35f3ddba..04da8f730e209 100644 --- a/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr +++ b/tests/ui/traits/const-traits/const-check-fns-in-const-impl.stderr @@ -1,11 +1,11 @@ error[E0015]: cannot call non-const function `non_const` in constant functions - --> $DIR/const-check-fns-in-const-impl.rs:14:16 + --> $DIR/const-check-fns-in-const-impl.rs:13:16 | LL | fn foo() { non_const() } | ^^^^^^^^^^^ | note: function `non_const` is not const - --> $DIR/const-check-fns-in-const-impl.rs:11:1 + --> $DIR/const-check-fns-in-const-impl.rs:10:1 | LL | fn non_const() {} | ^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/const-closure-trait-method-fail.rs b/tests/ui/traits/const-traits/const-closure-trait-method-fail.rs index cbcc4aa7c3cdb..da9327226f771 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method-fail.rs +++ b/tests/ui/traits/const-traits/const-closure-trait-method-fail.rs @@ -2,8 +2,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Tr { +const trait Tr { fn a(self) -> i32; } diff --git a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr index faacc86512441..93563dd12f952 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr +++ b/tests/ui/traits/const-traits/const-closure-trait-method-fail.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): const Tr` is not satisfied - --> $DIR/const-closure-trait-method-fail.rs:18:23 + --> $DIR/const-closure-trait-method-fail.rs:17:23 | LL | const _: () = assert!(need_const_closure(Tr::a) == 42); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.rs b/tests/ui/traits/const-traits/const-closure-trait-method.rs index 6477aa63c680b..62de7c533ffb8 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method.rs +++ b/tests/ui/traits/const-traits/const-closure-trait-method.rs @@ -3,8 +3,7 @@ //@[next] compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -trait Tr { +const trait Tr { fn a(self) -> i32; } diff --git a/tests/ui/traits/const-traits/const-cond-for-rpitit.rs b/tests/ui/traits/const-traits/const-cond-for-rpitit.rs index da83e054dd9bb..0d010fe0de97a 100644 --- a/tests/ui/traits/const-traits/const-cond-for-rpitit.rs +++ b/tests/ui/traits/const-traits/const-cond-for-rpitit.rs @@ -4,13 +4,11 @@ #![feature(const_trait_impl)] #![allow(refining_impl_trait)] -#[const_trait] -pub trait Foo { +pub const trait Foo { fn method(self) -> impl [const] Bar; } -#[const_trait] -pub trait Bar {} +pub const trait Bar {} struct A(T); impl const Foo for A where A: [const] Bar { diff --git a/tests/ui/traits/const-traits/const-default-method-bodies.rs b/tests/ui/traits/const-traits/const-default-method-bodies.rs index 27e828c7ab91a..b2ddf1ba541e6 100644 --- a/tests/ui/traits/const-traits/const-default-method-bodies.rs +++ b/tests/ui/traits/const-traits/const-default-method-bodies.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -trait ConstDefaultFn: Sized { +const trait ConstDefaultFn: Sized { fn b(self); fn a(self) { diff --git a/tests/ui/traits/const-traits/const-default-method-bodies.stderr b/tests/ui/traits/const-traits/const-default-method-bodies.stderr index 22b6a9b5613a8..55a12f95a6d19 100644 --- a/tests/ui/traits/const-traits/const-default-method-bodies.stderr +++ b/tests/ui/traits/const-traits/const-default-method-bodies.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NonConstImpl: [const] ConstDefaultFn` is not satisfied - --> $DIR/const-default-method-bodies.rs:25:18 + --> $DIR/const-default-method-bodies.rs:24:18 | LL | NonConstImpl.a(); | ^ diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr index 48c8852a7b8d4..b4603f4882cc9 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.precise.stderr @@ -1,18 +1,18 @@ error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied - --> $DIR/const-drop-fail-2.rs:31:23 + --> $DIR/const-drop-fail-2.rs:30:23 | LL | const _: () = check::>( | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required for `ConstDropImplWithBounds` to implement `const Drop` - --> $DIR/const-drop-fail-2.rs:25:26 + --> $DIR/const-drop-fail-2.rs:24:26 | LL | impl const Drop for ConstDropImplWithBounds { | --------- ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | unsatisfied trait bound introduced here note: required by a bound in `check` - --> $DIR/const-drop-fail-2.rs:21:19 + --> $DIR/const-drop-fail-2.rs:20:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.rs b/tests/ui/traits/const-traits/const-drop-fail-2.rs index 3f98a9f715e8b..f5e5793b95c1c 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.rs +++ b/tests/ui/traits/const-traits/const-drop-fail-2.rs @@ -13,8 +13,7 @@ impl Drop for NonTrivialDrop { } } -#[const_trait] -trait A { fn a() { } } +const trait A { fn a() { } } impl A for NonTrivialDrop {} diff --git a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr index 48c8852a7b8d4..b4603f4882cc9 100644 --- a/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail-2.stock.stderr @@ -1,18 +1,18 @@ error[E0277]: the trait bound `NonTrivialDrop: const A` is not satisfied - --> $DIR/const-drop-fail-2.rs:31:23 + --> $DIR/const-drop-fail-2.rs:30:23 | LL | const _: () = check::>( | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required for `ConstDropImplWithBounds` to implement `const Drop` - --> $DIR/const-drop-fail-2.rs:25:26 + --> $DIR/const-drop-fail-2.rs:24:26 | LL | impl const Drop for ConstDropImplWithBounds { | --------- ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | unsatisfied trait bound introduced here note: required by a bound in `check` - --> $DIR/const-drop-fail-2.rs:21:19 + --> $DIR/const-drop-fail-2.rs:20:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` diff --git a/tests/ui/traits/const-traits/const-drop.rs b/tests/ui/traits/const-traits/const-drop.rs index dc985a8f62073..f7c3ec9be331d 100644 --- a/tests/ui/traits/const-traits/const-drop.rs +++ b/tests/ui/traits/const-traits/const-drop.rs @@ -49,8 +49,7 @@ mod t { pub struct HasConstDrop(pub ConstDrop); pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize); - #[const_trait] - pub trait SomeTrait { + pub const trait SomeTrait { fn foo(); } impl const SomeTrait for () { diff --git a/tests/ui/traits/const-traits/const-impl-recovery.rs b/tests/ui/traits/const-traits/const-impl-recovery.rs index 837124db04e20..0f1c6225d8f0a 100644 --- a/tests/ui/traits/const-traits/const-impl-recovery.rs +++ b/tests/ui/traits/const-traits/const-impl-recovery.rs @@ -1,12 +1,10 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Foo {} +const trait Foo {} const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword -#[const_trait] -trait Bar {} +const trait Bar {} const impl Bar for T {} //~ ERROR: expected identifier, found keyword diff --git a/tests/ui/traits/const-traits/const-impl-recovery.stderr b/tests/ui/traits/const-traits/const-impl-recovery.stderr index 7217fc8554356..709084c86e0ae 100644 --- a/tests/ui/traits/const-traits/const-impl-recovery.stderr +++ b/tests/ui/traits/const-traits/const-impl-recovery.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `impl` - --> $DIR/const-impl-recovery.rs:6:7 + --> $DIR/const-impl-recovery.rs:5:7 | LL | const impl Foo for i32 {} | ^^^^ expected identifier, found keyword @@ -11,7 +11,7 @@ LL + impl const Foo for i32 {} | error: expected identifier, found keyword `impl` - --> $DIR/const-impl-recovery.rs:11:7 + --> $DIR/const-impl-recovery.rs:9:7 | LL | const impl Bar for T {} | ^^^^ expected identifier, found keyword diff --git a/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr b/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr index bf73436b78d38..705ade389436b 100644 --- a/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr +++ b/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr @@ -8,8 +8,8 @@ LL | impl const A for () {} = note: adding a non-const method body in the future would be a breaking change help: mark `A` as `const` to allow it to have `const` implementations | -LL | #[const_trait] pub trait A {} - | ++++++++++++++ +LL | pub const trait A {} + | +++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/const-impl-trait.rs b/tests/ui/traits/const-traits/const-impl-trait.rs index c89aaa62d9922..e3fcf540643a9 100644 --- a/tests/ui/traits/const-traits/const-impl-trait.rs +++ b/tests/ui/traits/const-traits/const-impl-trait.rs @@ -16,8 +16,7 @@ const fn wrap( x } -#[const_trait] -trait Foo { +const trait Foo { fn huh() -> impl [const] PartialEq + [const] Destruct + Copy; } @@ -36,8 +35,7 @@ const _: () = { assert!(x == x); }; -#[const_trait] -trait T {} +const trait T {} struct S; impl const T for S {} diff --git a/tests/ui/traits/const-traits/const-in-closure.rs b/tests/ui/traits/const-traits/const-in-closure.rs index 0657c5af58837..73e348d022ae3 100644 --- a/tests/ui/traits/const-traits/const-in-closure.rs +++ b/tests/ui/traits/const-traits/const-in-closure.rs @@ -3,8 +3,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Trait { +const trait Trait { fn method(); } diff --git a/tests/ui/traits/const-traits/const-opaque.no.stderr b/tests/ui/traits/const-traits/const-opaque.no.stderr index 591b81f976745..9f17b0d4354d7 100644 --- a/tests/ui/traits/const-traits/const-opaque.no.stderr +++ b/tests/ui/traits/const-traits/const-opaque.no.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): const Foo` is not satisfied - --> $DIR/const-opaque.rs:31:22 + --> $DIR/const-opaque.rs:30:22 | LL | let opaque = bar(()); | --- ^^ @@ -7,7 +7,7 @@ LL | let opaque = bar(()); | required by a bound introduced by this call | note: required by a bound in `bar` - --> $DIR/const-opaque.rs:26:17 + --> $DIR/const-opaque.rs:25:17 | LL | const fn bar(t: T) -> impl [const] Foo { | ^^^^^^^^^^^ required by this bound in `bar` @@ -17,7 +17,7 @@ LL | impl const Foo for () { | +++++ error[E0277]: the trait bound `(): const Foo` is not satisfied - --> $DIR/const-opaque.rs:33:12 + --> $DIR/const-opaque.rs:32:12 | LL | opaque.method(); | ^^^^^^ diff --git a/tests/ui/traits/const-traits/const-opaque.rs b/tests/ui/traits/const-traits/const-opaque.rs index 56ebf0aefccfd..9b24cfa69a863 100644 --- a/tests/ui/traits/const-traits/const-opaque.rs +++ b/tests/ui/traits/const-traits/const-opaque.rs @@ -4,8 +4,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Foo { +const trait Foo { fn method(&self); } diff --git a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr index 3ba5da39106d6..b78dc0e98abe8 100644 --- a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr +++ b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr @@ -34,8 +34,8 @@ LL | const fn handle(_: &dyn const NonConst) {} | help: mark `NonConst` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait NonConst {} - | ++++++++++++++ +LL | const trait NonConst {} + | +++++ error: `[const]` can only be applied to `const` traits --> $DIR/const-trait-bounds-trait-objects.rs:16:23 @@ -45,8 +45,8 @@ LL | const fn take(_: &dyn [const] NonConst) {} | help: mark `NonConst` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait NonConst {} - | ++++++++++++++ +LL | const trait NonConst {} + | +++++ error: aborting due to 6 previous errors diff --git a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs index 5376baf15e0f1..fcc23fbb65104 100644 --- a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs +++ b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs @@ -10,8 +10,7 @@ #![feature(const_trait_impl, effects)] //~^ ERROR feature has been removed -#[const_trait] -trait Main { +const trait Main { fn compute() -> u32; } @@ -22,8 +21,7 @@ impl const Main for () { } } -#[const_trait] -trait Aux {} +const trait Aux {} impl const Aux for () {} diff --git a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr index 736fde33ce3a3..70add14c3712f 100644 --- a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr +++ b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr @@ -8,7 +8,7 @@ LL | #![feature(const_trait_impl, effects)] = note: removed, redundant with `#![feature(const_trait_impl)]` error[E0049]: associated function `compute` has 0 type parameters but its trait declaration has 1 type parameter - --> $DIR/const-trait-impl-parameter-mismatch.rs:19:16 + --> $DIR/const-trait-impl-parameter-mismatch.rs:18:16 | LL | fn compute() -> u32; | - expected 1 type parameter diff --git a/tests/ui/traits/const-traits/const-via-item-bound.rs b/tests/ui/traits/const-traits/const-via-item-bound.rs index 23f122b741308..c927e1f73ce71 100644 --- a/tests/ui/traits/const-traits/const-via-item-bound.rs +++ b/tests/ui/traits/const-traits/const-via-item-bound.rs @@ -5,8 +5,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Bar {} +const trait Bar {} trait Baz: const Bar {} diff --git a/tests/ui/traits/const-traits/cross-crate.gatednc.stderr b/tests/ui/traits/const-traits/cross-crate.gatednc.stderr index fe45ff188efb4..45e06c78cfb25 100644 --- a/tests/ui/traits/const-traits/cross-crate.gatednc.stderr +++ b/tests/ui/traits/const-traits/cross-crate.gatednc.stderr @@ -5,7 +5,7 @@ LL | NonConst.func(); | ^^^^ | note: trait `MyTrait` is implemented but not `const` - --> $DIR/auxiliary/cross-crate.rs:12:1 + --> $DIR/auxiliary/cross-crate.rs:11:1 | LL | impl MyTrait for NonConst { | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.rs b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.rs index ea97f755d55c4..3de92f571e707 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.rs +++ b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.rs @@ -1,13 +1,11 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Tr {} +const trait Tr {} impl Tr for () {} const fn foo() where T: [const] Tr {} -#[const_trait] -pub trait Foo { +pub const trait Foo { fn foo() { foo::<()>(); //~^ ERROR the trait bound `(): [const] Tr` is not satisfied diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr index 3ce646ec5027f..a436221d75412 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr +++ b/tests/ui/traits/const-traits/default-method-body-is-const-body-checking.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `(): [const] Tr` is not satisfied - --> $DIR/default-method-body-is-const-body-checking.rs:12:15 + --> $DIR/default-method-body-is-const-body-checking.rs:10:15 | LL | foo::<()>(); | ^^ | note: required by a bound in `foo` - --> $DIR/default-method-body-is-const-body-checking.rs:7:28 + --> $DIR/default-method-body-is-const-body-checking.rs:6:28 | LL | const fn foo() where T: [const] Tr {} | ^^^^^^^^^^ required by this bound in `foo` diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs index eb2c472e3bf7b..6de82edfbedc7 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs +++ b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -pub trait Tr { +pub const trait Tr { fn a(&self) {} fn b(&self) { diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr index f473a687efcb0..f93e57d5fd6b2 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr +++ b/tests/ui/traits/const-traits/default-method-body-is-const-same-trait-ck.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): [const] Tr` is not satisfied - --> $DIR/default-method-body-is-const-same-trait-ck.rs:9:12 + --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12 | LL | ().a() | ^ diff --git a/tests/ui/traits/const-traits/default-method-body-is-const-with-staged-api.rs b/tests/ui/traits/const-traits/default-method-body-is-const-with-staged-api.rs index 8b264ebd0e42a..9fccef759bb94 100644 --- a/tests/ui/traits/const-traits/default-method-body-is-const-with-staged-api.rs +++ b/tests/ui/traits/const-traits/default-method-body-is-const-with-staged-api.rs @@ -9,8 +9,7 @@ #![feature(const_trait_impl)] #![stable(feature = "foo", since = "3.3.3")] -#[const_trait] -trait Tr { +const trait Tr { fn a() {} } diff --git a/tests/ui/traits/const-traits/do-not-const-check-override.rs b/tests/ui/traits/const-traits/do-not-const-check-override.rs index 2b8e1d38ac99f..caa3e192e71f3 100644 --- a/tests/ui/traits/const-traits/do-not-const-check-override.rs +++ b/tests/ui/traits/const-traits/do-not-const-check-override.rs @@ -3,8 +3,7 @@ #![allow(incomplete_features)] #![feature(const_trait_impl, rustc_attrs)] -#[const_trait] -trait Foo { +const trait Foo { #[rustc_do_not_const_check] fn into_iter(&self) { println!("FEAR ME!") } } diff --git a/tests/ui/traits/const-traits/do-not-const-check.rs b/tests/ui/traits/const-traits/do-not-const-check.rs index 443b638573576..fecbfea8467bd 100644 --- a/tests/ui/traits/const-traits/do-not-const-check.rs +++ b/tests/ui/traits/const-traits/do-not-const-check.rs @@ -1,13 +1,11 @@ //@ check-pass #![feature(const_trait_impl, rustc_attrs)] -#[const_trait] -trait IntoIter { +const trait IntoIter { fn into_iter(self); } -#[const_trait] -trait Hmm: Sized { +const trait Hmm: Sized { #[rustc_do_not_const_check] fn chain(self, other: U) where U: IntoIter, { diff --git a/tests/ui/traits/const-traits/dont-ice-on-const-pred-for-bounds.rs b/tests/ui/traits/const-traits/dont-ice-on-const-pred-for-bounds.rs index d39e661ed9205..ae87d1c4e9c25 100644 --- a/tests/ui/traits/const-traits/dont-ice-on-const-pred-for-bounds.rs +++ b/tests/ui/traits/const-traits/dont-ice-on-const-pred-for-bounds.rs @@ -8,8 +8,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Trait { +const trait Trait { type Assoc: const Trait; } diff --git a/tests/ui/traits/const-traits/dont-observe-host.rs b/tests/ui/traits/const-traits/dont-observe-host.rs index 06050385f9168..f8477a3e5ea8e 100644 --- a/tests/ui/traits/const-traits/dont-observe-host.rs +++ b/tests/ui/traits/const-traits/dont-observe-host.rs @@ -3,8 +3,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Trait { +const trait Trait { fn method() {} } diff --git a/tests/ui/traits/const-traits/dont-prefer-param-env-for-infer-self-ty.rs b/tests/ui/traits/const-traits/dont-prefer-param-env-for-infer-self-ty.rs index f1fc98d72a547..f45265c2cc758 100644 --- a/tests/ui/traits/const-traits/dont-prefer-param-env-for-infer-self-ty.rs +++ b/tests/ui/traits/const-traits/dont-prefer-param-env-for-infer-self-ty.rs @@ -2,8 +2,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Foo {} +const trait Foo {} impl const Foo for (T,) where T: [const] Foo {} diff --git a/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.rs b/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.rs index 414b80ca0daab..062853635f285 100644 --- a/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.rs +++ b/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.rs @@ -2,8 +2,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Trait { +const trait Trait { type Out; } diff --git a/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.stderr b/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.stderr index 740a05be06ba6..1ae376c8b6b27 100644 --- a/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.stderr +++ b/tests/ui/traits/const-traits/double-error-for-unimplemented-trait.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): Trait` is not satisfied - --> $DIR/double-error-for-unimplemented-trait.rs:13:15 + --> $DIR/double-error-for-unimplemented-trait.rs:12:15 | LL | needs_const(&()); | ----------- ^^^ the trait `Trait` is not implemented for `()` @@ -7,18 +7,18 @@ LL | needs_const(&()); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/double-error-for-unimplemented-trait.rs:6:1 + --> $DIR/double-error-for-unimplemented-trait.rs:5:1 | -LL | trait Trait { - | ^^^^^^^^^^^ +LL | const trait Trait { + | ^^^^^^^^^^^^^^^^^ note: required by a bound in `needs_const` - --> $DIR/double-error-for-unimplemented-trait.rs:10:25 + --> $DIR/double-error-for-unimplemented-trait.rs:9:25 | LL | const fn needs_const(_: &T) {} | ^^^^^^^^^^^^^ required by this bound in `needs_const` error[E0277]: the trait bound `(): Trait` is not satisfied - --> $DIR/double-error-for-unimplemented-trait.rs:18:15 + --> $DIR/double-error-for-unimplemented-trait.rs:17:15 | LL | needs_const(&()); | ----------- ^^^ the trait `Trait` is not implemented for `()` @@ -26,12 +26,12 @@ LL | needs_const(&()); | required by a bound introduced by this call | help: this trait has no implementations, consider adding one - --> $DIR/double-error-for-unimplemented-trait.rs:6:1 + --> $DIR/double-error-for-unimplemented-trait.rs:5:1 | -LL | trait Trait { - | ^^^^^^^^^^^ +LL | const trait Trait { + | ^^^^^^^^^^^^^^^^^ note: required by a bound in `needs_const` - --> $DIR/double-error-for-unimplemented-trait.rs:10:25 + --> $DIR/double-error-for-unimplemented-trait.rs:9:25 | LL | const fn needs_const(_: &T) {} | ^^^^^^^^^^^^^ required by this bound in `needs_const` diff --git a/tests/ui/traits/const-traits/effect-param-infer.rs b/tests/ui/traits/const-traits/effect-param-infer.rs index fcacf458a9fa5..4ff2406ed15fd 100644 --- a/tests/ui/traits/const-traits/effect-param-infer.rs +++ b/tests/ui/traits/const-traits/effect-param-infer.rs @@ -5,8 +5,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -pub trait Foo { +pub const trait Foo { /* stuff */ } diff --git a/tests/ui/traits/const-traits/eval-bad-signature.rs b/tests/ui/traits/const-traits/eval-bad-signature.rs index 66e296d438806..02afdb93d2407 100644 --- a/tests/ui/traits/const-traits/eval-bad-signature.rs +++ b/tests/ui/traits/const-traits/eval-bad-signature.rs @@ -2,8 +2,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Value { +const trait Value { fn value() -> u32; } diff --git a/tests/ui/traits/const-traits/eval-bad-signature.stderr b/tests/ui/traits/const-traits/eval-bad-signature.stderr index 52de5283f7fdf..db5f434ee0e98 100644 --- a/tests/ui/traits/const-traits/eval-bad-signature.stderr +++ b/tests/ui/traits/const-traits/eval-bad-signature.stderr @@ -1,11 +1,11 @@ error[E0053]: method `value` has an incompatible type for trait - --> $DIR/eval-bad-signature.rs:17:19 + --> $DIR/eval-bad-signature.rs:16:19 | LL | fn value() -> i64 { | ^^^ expected `u32`, found `i64` | note: type in trait - --> $DIR/eval-bad-signature.rs:7:19 + --> $DIR/eval-bad-signature.rs:6:19 | LL | fn value() -> u32; | ^^^ diff --git a/tests/ui/traits/const-traits/feature-gate.rs b/tests/ui/traits/const-traits/feature-gate.rs index c2918f0249b9e..46f0e92021a14 100644 --- a/tests/ui/traits/const-traits/feature-gate.rs +++ b/tests/ui/traits/const-traits/feature-gate.rs @@ -5,15 +5,13 @@ #![cfg_attr(gated, feature(const_trait_impl))] struct S; -#[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder -trait T {} +const trait T {} //[stock]~ ERROR const trait impls are experimental impl const T for S {} //[stock]~^ ERROR const trait impls are experimental const fn f() {} //[stock]~ ERROR const trait impls are experimental fn g() {} //[stock]~ ERROR const trait impls are experimental -const trait Trait {} //[stock]~ ERROR const trait impls are experimental #[cfg(false)] const trait Trait {} //[stock]~ ERROR const trait impls are experimental macro_rules! discard { ($ty:ty) => {} } diff --git a/tests/ui/traits/const-traits/feature-gate.stock.stderr b/tests/ui/traits/const-traits/feature-gate.stock.stderr index 551c7ced7c1f4..b5e031094600e 100644 --- a/tests/ui/traits/const-traits/feature-gate.stock.stderr +++ b/tests/ui/traits/const-traits/feature-gate.stock.stderr @@ -1,45 +1,45 @@ error[E0658]: const trait impls are experimental - --> $DIR/feature-gate.rs:10:6 + --> $DIR/feature-gate.rs:8:1 | -LL | impl const T for S {} - | ^^^^^ +LL | const trait T {} + | ^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/feature-gate.rs:13:15 + --> $DIR/feature-gate.rs:9:6 | -LL | const fn f() {} - | ^^^^^^^ +LL | impl const T for S {} + | ^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/feature-gate.rs:14:9 + --> $DIR/feature-gate.rs:12:15 | -LL | fn g() {} - | ^^^^^ +LL | const fn f() {} + | ^^^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/feature-gate.rs:16:1 + --> $DIR/feature-gate.rs:13:9 | -LL | const trait Trait {} - | ^^^^^ +LL | fn g() {} + | ^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/feature-gate.rs:17:15 + --> $DIR/feature-gate.rs:15:15 | LL | #[cfg(false)] const trait Trait {} | ^^^^^ @@ -49,7 +49,7 @@ LL | #[cfg(false)] const trait Trait {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/feature-gate.rs:21:17 + --> $DIR/feature-gate.rs:19:17 | LL | discard! { impl [const] T } | ^^^^^^^ @@ -59,7 +59,7 @@ LL | discard! { impl [const] T } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/feature-gate.rs:22:17 + --> $DIR/feature-gate.rs:20:17 | LL | discard! { impl const T } | ^^^^^ @@ -68,16 +68,6 @@ LL | discard! { impl const T } = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -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. - --> $DIR/feature-gate.rs:8:1 - | -LL | #[const_trait] - | ^^^^^^^^^^^^^^ - | - = note: see issue #143874 for more information - = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/function-pointer-does-not-require-const.rs b/tests/ui/traits/const-traits/function-pointer-does-not-require-const.rs index 8acd195e546b2..faa4b51d66854 100644 --- a/tests/ui/traits/const-traits/function-pointer-does-not-require-const.rs +++ b/tests/ui/traits/const-traits/function-pointer-does-not-require-const.rs @@ -1,8 +1,7 @@ //@ check-pass #![feature(const_trait_impl)] -#[const_trait] -pub trait Test {} +pub const trait Test {} impl Test for () {} diff --git a/tests/ui/traits/const-traits/hir-const-check.rs b/tests/ui/traits/const-traits/hir-const-check.rs index 1b6fa1afab9fa..5473cdd040754 100644 --- a/tests/ui/traits/const-traits/hir-const-check.rs +++ b/tests/ui/traits/const-traits/hir-const-check.rs @@ -6,8 +6,7 @@ #![feature(const_trait_impl)] #![feature(const_try)] -#[const_trait] -pub trait MyTrait { +pub const trait MyTrait { fn method(&self) -> Option<()>; } diff --git a/tests/ui/traits/const-traits/ice-121536-const-method.rs b/tests/ui/traits/const-traits/ice-121536-const-method.rs index b89786bfd933f..a1dbd7551b7b5 100644 --- a/tests/ui/traits/const-traits/ice-121536-const-method.rs +++ b/tests/ui/traits/const-traits/ice-121536-const-method.rs @@ -2,8 +2,7 @@ pub struct Vec3; -#[const_trait] -pub trait Add { +pub const trait Add { fn add(self) -> Vec3; } diff --git a/tests/ui/traits/const-traits/ice-121536-const-method.stderr b/tests/ui/traits/const-traits/ice-121536-const-method.stderr index 408958abf6307..55f158b3ddecc 100644 --- a/tests/ui/traits/const-traits/ice-121536-const-method.stderr +++ b/tests/ui/traits/const-traits/ice-121536-const-method.stderr @@ -1,5 +1,5 @@ error[E0379]: functions in trait impls cannot be declared const - --> $DIR/ice-121536-const-method.rs:11:5 + --> $DIR/ice-121536-const-method.rs:10:5 | LL | const fn add(self) -> Vec3 { | ^^^^^ functions in trait impls cannot be const diff --git a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs index ea4db0515cd44..617c28cc34016 100644 --- a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs +++ b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs @@ -2,8 +2,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Foo {} +const trait Foo {} impl const Foo for i32 {} diff --git a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr index 5b417dcfe2cb2..082e7a1413584 100644 --- a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr +++ b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Foo` for type `i32` - --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:10:1 + --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:9:1 | LL | impl const Foo for i32 {} | ---------------------- first implementation here diff --git a/tests/ui/traits/const-traits/impl-with-default-fn-fail.rs b/tests/ui/traits/const-traits/impl-with-default-fn-fail.rs index 6df9696f2cbd7..7becb01027d75 100644 --- a/tests/ui/traits/const-traits/impl-with-default-fn-fail.rs +++ b/tests/ui/traits/const-traits/impl-with-default-fn-fail.rs @@ -1,7 +1,6 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Tr { +const trait Tr { fn req(&self); fn default() {} diff --git a/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr b/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr index 36c8163f1c567..61f989810bf3f 100644 --- a/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr +++ b/tests/ui/traits/const-traits/impl-with-default-fn-fail.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `req` - --> $DIR/impl-with-default-fn-fail.rs:12:1 + --> $DIR/impl-with-default-fn-fail.rs:11:1 | LL | fn req(&self); | -------------- `req` from trait diff --git a/tests/ui/traits/const-traits/impl-with-default-fn-pass.rs b/tests/ui/traits/const-traits/impl-with-default-fn-pass.rs index c776a29716ff7..f6888f5e997b7 100644 --- a/tests/ui/traits/const-traits/impl-with-default-fn-pass.rs +++ b/tests/ui/traits/const-traits/impl-with-default-fn-pass.rs @@ -2,8 +2,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -trait Tr { +const trait Tr { fn req(&self); fn default() {} diff --git a/tests/ui/traits/const-traits/imply-always-const.rs b/tests/ui/traits/const-traits/imply-always-const.rs index f6cab0681ec2e..44391b2753ec0 100644 --- a/tests/ui/traits/const-traits/imply-always-const.rs +++ b/tests/ui/traits/const-traits/imply-always-const.rs @@ -2,13 +2,11 @@ #![feature(const_trait_impl)] -#[const_trait] -trait A where Self::Assoc: const B { +const trait A where Self::Assoc: const B { type Assoc; } -#[const_trait] -trait B {} +const trait B {} fn needs_b() {} diff --git a/tests/ui/traits/const-traits/inherent-impl-const-bounds.rs b/tests/ui/traits/const-traits/inherent-impl-const-bounds.rs index 941f054280375..67701461b3892 100644 --- a/tests/ui/traits/const-traits/inherent-impl-const-bounds.rs +++ b/tests/ui/traits/const-traits/inherent-impl-const-bounds.rs @@ -3,10 +3,8 @@ struct S; -#[const_trait] -trait A {} -#[const_trait] -trait B {} +const trait A {} +const trait B {} impl const A for S {} impl const B for S {} diff --git a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr index ca73ae845550d..541a2000c2872 100644 --- a/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr +++ b/tests/ui/traits/const-traits/inline-incorrect-early-bound-in-ctfe.stderr @@ -23,9 +23,8 @@ LL | fn foo(self); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider making trait `Trait` const | -LL + #[const_trait] -LL | trait Trait { - | +LL | const trait Trait { + | +++++ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/issue-100222.rs b/tests/ui/traits/const-traits/issue-100222.rs index 4c93272b224f8..aebcb625cfd7b 100644 --- a/tests/ui/traits/const-traits/issue-100222.rs +++ b/tests/ui/traits/const-traits/issue-100222.rs @@ -5,12 +5,20 @@ #![allow(incomplete_features)] #![feature(const_trait_impl, associated_type_defaults)] -#[cfg_attr(any(yn, yy), const_trait)] -pub trait Index { - type Output; +#[cfg(any(yn, yy))] pub const trait Index { type Output; } +#[cfg(not(any(yn, yy)))] pub trait Index { type Output; } + +#[cfg(any(ny, yy))] +pub const trait IndexMut +where + Self: Index, +{ + const C: ::Output; + type Assoc = ::Output; + fn foo(&mut self, x: ::Output) -> ::Output; } -#[cfg_attr(any(ny, yy), const_trait)] +#[cfg(not(any(ny, yy)))] pub trait IndexMut where Self: Index, diff --git a/tests/ui/traits/const-traits/issue-79450.rs b/tests/ui/traits/const-traits/issue-79450.rs index 5ba5036ce277a..e74da811fc805 100644 --- a/tests/ui/traits/const-traits/issue-79450.rs +++ b/tests/ui/traits/const-traits/issue-79450.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -trait Tr { +const trait Tr { fn req(&self); fn prov(&self) { diff --git a/tests/ui/traits/const-traits/issue-79450.stderr b/tests/ui/traits/const-traits/issue-79450.stderr index d8a9e18980687..c10023e9f0efa 100644 --- a/tests/ui/traits/const-traits/issue-79450.stderr +++ b/tests/ui/traits/const-traits/issue-79450.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const function `_print` in constant functions - --> $DIR/issue-79450.rs:9:9 + --> $DIR/issue-79450.rs:8:9 | LL | println!("lul"); | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/issue-88155.stderr b/tests/ui/traits/const-traits/issue-88155.stderr index 4a912cc8274a7..514f1fed947ea 100644 --- a/tests/ui/traits/const-traits/issue-88155.stderr +++ b/tests/ui/traits/const-traits/issue-88155.stderr @@ -14,9 +14,8 @@ LL | fn assoc() -> bool; = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider making trait `A` const | -LL + #[const_trait] -LL | pub trait A { - | +LL | pub const trait A { + | +++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs b/tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs index 0eb7f54d596fb..0663e23f51700 100644 --- a/tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs +++ b/tests/ui/traits/const-traits/issue-92230-wf-super-trait-env.rs @@ -5,10 +5,8 @@ #![feature(const_trait_impl)] -#[const_trait] -pub trait Super {} -#[const_trait] -pub trait Sub: Super {} +pub const trait Super {} +pub const trait Sub: Super {} impl const Super for &A where A: [const] Super {} impl const Sub for &A where A: [const] Sub {} diff --git a/tests/ui/traits/const-traits/item-bound-entailment-fails.rs b/tests/ui/traits/const-traits/item-bound-entailment-fails.rs index 029597ea1f032..047da4cc938da 100644 --- a/tests/ui/traits/const-traits/item-bound-entailment-fails.rs +++ b/tests/ui/traits/const-traits/item-bound-entailment-fails.rs @@ -1,13 +1,13 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] trait Foo { +const trait Foo { type Assoc: [const] Bar where T: [const] Bar; } -#[const_trait] trait Bar {} +const trait Bar {} struct N(T); impl Bar for N where T: Bar {} struct C(T); diff --git a/tests/ui/traits/const-traits/item-bound-entailment.rs b/tests/ui/traits/const-traits/item-bound-entailment.rs index 6e053adb3850d..facd222e5aafe 100644 --- a/tests/ui/traits/const-traits/item-bound-entailment.rs +++ b/tests/ui/traits/const-traits/item-bound-entailment.rs @@ -3,13 +3,13 @@ #![feature(const_trait_impl)] -#[const_trait] trait Foo { +const trait Foo { type Assoc: [const] Bar where T: [const] Bar; } -#[const_trait] trait Bar {} +const trait Bar {} struct N(T); impl Bar for N where T: Bar {} struct C(T); diff --git a/tests/ui/traits/const-traits/minicore-drop-fail.rs b/tests/ui/traits/const-traits/minicore-drop-fail.rs index f3e7c7df4d419..d01d259040c6e 100644 --- a/tests/ui/traits/const-traits/minicore-drop-fail.rs +++ b/tests/ui/traits/const-traits/minicore-drop-fail.rs @@ -15,7 +15,7 @@ impl Drop for NotDropImpl { fn drop(&mut self) {} } -#[const_trait] trait Foo {} +const trait Foo {} impl Foo for () {} struct Conditional(T); diff --git a/tests/ui/traits/const-traits/minicore-fn-fail.rs b/tests/ui/traits/const-traits/minicore-fn-fail.rs index d4cd41a51ca5c..e0ce235e72a23 100644 --- a/tests/ui/traits/const-traits/minicore-fn-fail.rs +++ b/tests/ui/traits/const-traits/minicore-fn-fail.rs @@ -10,8 +10,7 @@ use minicore::*; const fn call_indirect(t: &T) { t() } -#[const_trait] -trait Foo {} +const trait Foo {} impl Foo for () {} const fn foo() {} diff --git a/tests/ui/traits/const-traits/minicore-fn-fail.stderr b/tests/ui/traits/const-traits/minicore-fn-fail.stderr index eb840d421f488..0c260f7f33a77 100644 --- a/tests/ui/traits/const-traits/minicore-fn-fail.stderr +++ b/tests/ui/traits/const-traits/minicore-fn-fail.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): [const] Foo` is not satisfied - --> $DIR/minicore-fn-fail.rs:19:19 + --> $DIR/minicore-fn-fail.rs:18:19 | LL | call_indirect(&foo::<()>); | ------------- ^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs index 8d1d3a4c79070..7cb83ecfb0b6d 100644 --- a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs +++ b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs @@ -17,7 +17,6 @@ fn const_negative() {} //~^ ERROR `const` trait not allowed with `!` trait polarity modifier //~| ERROR negative bounds are not supported -#[const_trait] -trait Trait {} +const trait Trait {} fn main() {} diff --git a/tests/ui/traits/const-traits/no-explicit-const-params.rs b/tests/ui/traits/const-traits/no-explicit-const-params.rs index 76663292223b2..cf641db0a8ce6 100644 --- a/tests/ui/traits/const-traits/no-explicit-const-params.rs +++ b/tests/ui/traits/const-traits/no-explicit-const-params.rs @@ -2,8 +2,7 @@ const fn foo() {} -#[const_trait] -trait Bar { +const trait Bar { fn bar(); } diff --git a/tests/ui/traits/const-traits/no-explicit-const-params.stderr b/tests/ui/traits/const-traits/no-explicit-const-params.stderr index 47fa65b2479be..efd90482f7742 100644 --- a/tests/ui/traits/const-traits/no-explicit-const-params.stderr +++ b/tests/ui/traits/const-traits/no-explicit-const-params.stderr @@ -1,5 +1,5 @@ error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/no-explicit-const-params.rs:15:5 + --> $DIR/no-explicit-const-params.rs:14:5 | LL | foo::(); | ^^^-------- help: remove the unnecessary generics @@ -13,7 +13,7 @@ LL | const fn foo() {} | ^^^ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/no-explicit-const-params.rs:17:12 + --> $DIR/no-explicit-const-params.rs:16:12 | LL | <() as Bar>::bar(); | ^^^------ help: remove the unnecessary generics @@ -21,13 +21,13 @@ LL | <() as Bar>::bar(); | expected 0 generic arguments | note: trait defined here, with 0 generic parameters - --> $DIR/no-explicit-const-params.rs:6:7 + --> $DIR/no-explicit-const-params.rs:5:13 | -LL | trait Bar { - | ^^^ +LL | const trait Bar { + | ^^^ error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/no-explicit-const-params.rs:22:5 + --> $DIR/no-explicit-const-params.rs:21:5 | LL | foo::(); | ^^^--------- help: remove the unnecessary generics @@ -41,7 +41,7 @@ LL | const fn foo() {} | ^^^ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/no-explicit-const-params.rs:24:12 + --> $DIR/no-explicit-const-params.rs:23:12 | LL | <() as Bar>::bar(); | ^^^------- help: remove the unnecessary generics @@ -49,13 +49,13 @@ LL | <() as Bar>::bar(); | expected 0 generic arguments | note: trait defined here, with 0 generic parameters - --> $DIR/no-explicit-const-params.rs:6:7 + --> $DIR/no-explicit-const-params.rs:5:13 | -LL | trait Bar { - | ^^^ +LL | const trait Bar { + | ^^^ error[E0277]: the trait bound `(): const Bar` is not satisfied - --> $DIR/no-explicit-const-params.rs:24:6 + --> $DIR/no-explicit-const-params.rs:23:6 | LL | <() as Bar>::bar(); | ^^ diff --git a/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.rs b/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.rs index 50c985096d127..c0051c62b6d65 100644 --- a/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.rs +++ b/tests/ui/traits/const-traits/non-const-op-in-closure-in-const.rs @@ -2,8 +2,7 @@ //@ check-pass -#[const_trait] -trait Convert { +const trait Convert { fn to(self) -> T; } diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr b/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr index ed671bee63ab5..a6bd8615d36d3 100644 --- a/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr +++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.min_spec.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Foo` for type `(_,)` - --> $DIR/overlap-const-with-nonconst.rs:23:1 + --> $DIR/overlap-const-with-nonconst.rs:21:1 | LL | / impl const Foo for T LL | | where diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs b/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs index f45690b2f78b9..10dfb200c6436 100644 --- a/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs +++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.rs @@ -5,12 +5,10 @@ //[spec]~^ WARN the feature `specialization` is incomplete #![cfg_attr(min_spec, feature(min_specialization))] -#[const_trait] -trait Bar {} +const trait Bar {} impl const Bar for T {} -#[const_trait] -trait Foo { +const trait Foo { fn method(&self); } impl const Foo for T diff --git a/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr b/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr index 35f4d9184cf5b..91628f65fdcdd 100644 --- a/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr +++ b/tests/ui/traits/const-traits/overlap-const-with-nonconst.spec.stderr @@ -9,7 +9,7 @@ LL | #![cfg_attr(spec, feature(specialization))] = note: `#[warn(incomplete_features)]` on by default error[E0119]: conflicting implementations of trait `Foo` for type `(_,)` - --> $DIR/overlap-const-with-nonconst.rs:23:1 + --> $DIR/overlap-const-with-nonconst.rs:21:1 | LL | / impl const Foo for T LL | | where diff --git a/tests/ui/traits/const-traits/predicate-entailment-fails.rs b/tests/ui/traits/const-traits/predicate-entailment-fails.rs index 0e6c277fd8220..d1a8c35442cf2 100644 --- a/tests/ui/traits/const-traits/predicate-entailment-fails.rs +++ b/tests/ui/traits/const-traits/predicate-entailment-fails.rs @@ -1,11 +1,11 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] trait Bar {} +const trait Bar {} impl const Bar for () {} -#[const_trait] trait TildeConst { +const trait TildeConst { type Bar where T: [const] Bar; fn foo() where T: [const] Bar; @@ -19,7 +19,7 @@ impl TildeConst for () { } -#[const_trait] trait NeverConst { +const trait NeverConst { type Bar where T: Bar; fn foo() where T: Bar; diff --git a/tests/ui/traits/const-traits/predicate-entailment-passes.rs b/tests/ui/traits/const-traits/predicate-entailment-passes.rs index fe8714831866a..c2bac51024f39 100644 --- a/tests/ui/traits/const-traits/predicate-entailment-passes.rs +++ b/tests/ui/traits/const-traits/predicate-entailment-passes.rs @@ -3,10 +3,10 @@ #![feature(const_trait_impl)] -#[const_trait] trait Bar {} +const trait Bar {} impl const Bar for () {} -#[const_trait] trait TildeConst { +const trait TildeConst { fn foo() where T: [const] Bar; } impl TildeConst for () { @@ -14,7 +14,7 @@ impl TildeConst for () { } -#[const_trait] trait AlwaysConst { +const trait AlwaysConst { fn foo() where T: const Bar; } impl AlwaysConst for i32 { diff --git a/tests/ui/traits/const-traits/project.rs b/tests/ui/traits/const-traits/project.rs index 139299753e5c7..4750591b2babe 100644 --- a/tests/ui/traits/const-traits/project.rs +++ b/tests/ui/traits/const-traits/project.rs @@ -2,11 +2,9 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -pub trait Owo::T> {} +pub const trait Owo::T> {} -#[const_trait] -pub trait Uwu: Owo { +pub const trait Uwu: Owo { type T; } diff --git a/tests/ui/traits/const-traits/spec-effectvar-ice.stderr b/tests/ui/traits/const-traits/spec-effectvar-ice.stderr index ef5e58e1c3dfa..8dbbd302c655c 100644 --- a/tests/ui/traits/const-traits/spec-effectvar-ice.stderr +++ b/tests/ui/traits/const-traits/spec-effectvar-ice.stderr @@ -8,8 +8,8 @@ LL | impl const Foo for T {} = note: adding a non-const method body in the future would be a breaking change help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo {} - | ++++++++++++++ +LL | const trait Foo {} + | +++++ error: const `impl` for trait `Foo` which is not `const` --> $DIR/spec-effectvar-ice.rs:13:15 @@ -21,8 +21,8 @@ LL | impl const Foo for T where T: const Specialize {} = note: adding a non-const method body in the future would be a breaking change help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo {} - | ++++++++++++++ +LL | const trait Foo {} + | +++++ error: `const` can only be applied to `const` traits --> $DIR/spec-effectvar-ice.rs:13:34 @@ -32,8 +32,8 @@ LL | impl const Foo for T where T: const Specialize {} | help: mark `Specialize` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Specialize {} - | ++++++++++++++ +LL | const trait Specialize {} + | +++++ error: specialization impl does not specialize any associated items --> $DIR/spec-effectvar-ice.rs:13:1 diff --git a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs index 212d869d94d39..5125d2580238f 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs +++ b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.rs @@ -10,11 +10,9 @@ #[rustc_specialization_trait] trait Specialize {} -#[const_trait] -trait Foo {} +const trait Foo {} -#[const_trait] -trait Bar { +const trait Bar { fn bar(); } @@ -33,8 +31,7 @@ where fn bar() {} } -#[const_trait] -trait Baz { +const trait Baz { fn baz(); } diff --git a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr index 074e6237cc20d..85e9fda5c2a31 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr +++ b/tests/ui/traits/const-traits/specialization/const-default-bound-non-const-specialized-bound.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Bar` - --> $DIR/const-default-bound-non-const-specialized-bound.rs:28:1 + --> $DIR/const-default-bound-non-const-specialized-bound.rs:26:1 | LL | / impl const Bar for T LL | | where @@ -13,7 +13,7 @@ LL | | T: Specialize, | |__________________^ conflicting implementation error[E0119]: conflicting implementations of trait `Baz` - --> $DIR/const-default-bound-non-const-specialized-bound.rs:48:1 + --> $DIR/const-default-bound-non-const-specialized-bound.rs:45:1 | LL | / impl const Baz for T LL | | where diff --git a/tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs b/tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs index 6991b7deda317..3be2ff4ee6117 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs +++ b/tests/ui/traits/const-traits/specialization/const-default-const-specialized.rs @@ -6,8 +6,7 @@ #![feature(const_trait_impl)] #![feature(min_specialization)] -#[const_trait] -trait Value { +const trait Value { fn value() -> u32; } diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr index 38fc5ddfbef52..520a6833f5a58 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.min_spec.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo` - --> $DIR/const-default-impl-non-const-specialized-impl.rs:22:1 + --> $DIR/const-default-impl-non-const-specialized-impl.rs:21:1 | LL | impl const Value for T { | ------------------------- first implementation here diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs index acf0a967a884d..f7cd4599561cb 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.rs @@ -6,8 +6,7 @@ //[spec]~^ WARN the feature `specialization` is incomplete #![cfg_attr(min_spec, feature(min_specialization))] -#[const_trait] -trait Value { +const trait Value { fn value() -> u32; } diff --git a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr index b59c42f518936..397d678559451 100644 --- a/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr +++ b/tests/ui/traits/const-traits/specialization/const-default-impl-non-const-specialized-impl.spec.stderr @@ -9,7 +9,7 @@ LL | #![cfg_attr(spec, feature(specialization))] = note: `#[warn(incomplete_features)]` on by default error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo` - --> $DIR/const-default-impl-non-const-specialized-impl.rs:22:1 + --> $DIR/const-default-impl-non-const-specialized-impl.rs:21:1 | LL | impl const Value for T { | ------------------------- first implementation here diff --git a/tests/ui/traits/const-traits/specialization/default-keyword.rs b/tests/ui/traits/const-traits/specialization/default-keyword.rs index bc45a70777ca5..5b074015d1998 100644 --- a/tests/ui/traits/const-traits/specialization/default-keyword.rs +++ b/tests/ui/traits/const-traits/specialization/default-keyword.rs @@ -3,8 +3,7 @@ #![feature(const_trait_impl)] #![feature(min_specialization)] -#[const_trait] -trait Foo { +const trait Foo { fn foo(); } diff --git a/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs b/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs index 754f1c6d09d5d..dbdbf5918556f 100644 --- a/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs +++ b/tests/ui/traits/const-traits/specialization/issue-95187-same-trait-bound-different-constness.rs @@ -11,11 +11,9 @@ #[rustc_specialization_trait] trait Specialize {} -#[const_trait] -trait Foo {} +const trait Foo {} -#[const_trait] -trait Bar { +const trait Bar { fn bar(); } @@ -34,8 +32,7 @@ where fn bar() {} } -#[const_trait] -trait Baz { +const trait Baz { fn baz(); } diff --git a/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs b/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs index b1a1b4a239955..c68f80dfc7286 100644 --- a/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs +++ b/tests/ui/traits/const-traits/specialization/non-const-default-const-specialized.rs @@ -6,8 +6,7 @@ #![feature(const_trait_impl)] #![feature(min_specialization)] -#[const_trait] -trait Value { +const trait Value { fn value() -> u32; } diff --git a/tests/ui/traits/const-traits/specialization/specialize-on-conditionally-const.rs b/tests/ui/traits/const-traits/specialization/specialize-on-conditionally-const.rs index 0106bb13875ac..a0630d1a80629 100644 --- a/tests/ui/traits/const-traits/specialization/specialize-on-conditionally-const.rs +++ b/tests/ui/traits/const-traits/specialization/specialize-on-conditionally-const.rs @@ -7,12 +7,10 @@ #![feature(rustc_attrs)] #![feature(min_specialization)] -#[const_trait] #[rustc_specialization_trait] -trait Specialize {} +const trait Specialize {} -#[const_trait] -trait Foo { +const trait Foo { fn foo(); } @@ -27,8 +25,7 @@ where fn foo() {} } -#[const_trait] -trait Bar { +const trait Bar { fn bar() {} } diff --git a/tests/ui/traits/const-traits/specializing-constness-2.rs b/tests/ui/traits/const-traits/specializing-constness-2.rs index 86c2cee9fedbc..455dd111603da 100644 --- a/tests/ui/traits/const-traits/specializing-constness-2.rs +++ b/tests/ui/traits/const-traits/specializing-constness-2.rs @@ -1,13 +1,11 @@ #![feature(const_trait_impl, min_specialization, rustc_attrs)] //@ known-bug: #110395 #[rustc_specialization_trait] -#[const_trait] -pub trait Sup {} +pub const trait Sup {} impl const Sup for () {} -#[const_trait] -pub trait A { +pub const trait A { fn a() -> u32; } diff --git a/tests/ui/traits/const-traits/specializing-constness-2.stderr b/tests/ui/traits/const-traits/specializing-constness-2.stderr index 2a34cd1c4f82d..bd6ffa544d0ec 100644 --- a/tests/ui/traits/const-traits/specializing-constness-2.stderr +++ b/tests/ui/traits/const-traits/specializing-constness-2.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `T: [const] A` is not satisfied - --> $DIR/specializing-constness-2.rs:27:6 + --> $DIR/specializing-constness-2.rs:25:6 | LL | ::a(); | ^ diff --git a/tests/ui/traits/const-traits/specializing-constness.rs b/tests/ui/traits/const-traits/specializing-constness.rs index b64d8b21b24be..6e9931e8a740a 100644 --- a/tests/ui/traits/const-traits/specializing-constness.rs +++ b/tests/ui/traits/const-traits/specializing-constness.rs @@ -1,18 +1,15 @@ #![feature(const_trait_impl, min_specialization, rustc_attrs)] #[rustc_specialization_trait] -#[const_trait] -pub trait Sup {} +pub const trait Sup {} impl const Sup for () {} -#[const_trait] -pub trait A { +pub const trait A { fn a() -> u32; } -#[const_trait] -pub trait Spec {} +pub const trait Spec {} impl const A for T { default fn a() -> u32 { diff --git a/tests/ui/traits/const-traits/specializing-constness.stderr b/tests/ui/traits/const-traits/specializing-constness.stderr index f411ebcdfcac5..e55b24f6f4fd1 100644 --- a/tests/ui/traits/const-traits/specializing-constness.stderr +++ b/tests/ui/traits/const-traits/specializing-constness.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `A` - --> $DIR/specializing-constness.rs:23:1 + --> $DIR/specializing-constness.rs:20:1 | LL | impl const A for T { | ----------------------------------- first implementation here diff --git a/tests/ui/traits/const-traits/staged-api.rs b/tests/ui/traits/const-traits/staged-api.rs index d24b26be569ca..6d0a84797ea24 100644 --- a/tests/ui/traits/const-traits/staged-api.rs +++ b/tests/ui/traits/const-traits/staged-api.rs @@ -86,13 +86,11 @@ const fn implicitly_stable_const_context() { } // check that const stability of impls and traits must match -#[const_trait] #[rustc_const_unstable(feature = "beef", issue = "none")] -trait U {} +const trait U {} -#[const_trait] #[rustc_const_stable(since = "0.0.0", feature = "beef2")] -trait S {} +const trait S {} // implied stable impl const U for u8 {} diff --git a/tests/ui/traits/const-traits/staged-api.stderr b/tests/ui/traits/const-traits/staged-api.stderr index 3e85834eb94ae..15328ae3b4553 100644 --- a/tests/ui/traits/const-traits/staged-api.stderr +++ b/tests/ui/traits/const-traits/staged-api.stderr @@ -1,22 +1,22 @@ error: const stability on the impl does not match the const stability on the trait - --> $DIR/staged-api.rs:98:1 + --> $DIR/staged-api.rs:96:1 | LL | impl const U for u8 {} | ^^^^^^^^^^^^^^^^^^^^^^ | note: this impl is (implicitly) stable... - --> $DIR/staged-api.rs:98:1 + --> $DIR/staged-api.rs:96:1 | LL | impl const U for u8 {} | ^^^^^^^^^^^^^^^^^^^^^^ note: ...but the trait is unstable - --> $DIR/staged-api.rs:91:7 + --> $DIR/staged-api.rs:90:13 | -LL | trait U {} - | ^ +LL | const trait U {} + | ^ error: trait implementations cannot be const stable yet - --> $DIR/staged-api.rs:102:1 + --> $DIR/staged-api.rs:100:1 | LL | impl const U for u16 {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,24 +24,24 @@ LL | impl const U for u16 {} = note: see issue #143874 for more information error: const stability on the impl does not match the const stability on the trait - --> $DIR/staged-api.rs:102:1 + --> $DIR/staged-api.rs:100:1 | LL | impl const U for u16 {} | ^^^^^^^^^^^^^^^^^^^^^^^ | note: this impl is (implicitly) stable... - --> $DIR/staged-api.rs:102:1 + --> $DIR/staged-api.rs:100:1 | LL | impl const U for u16 {} | ^^^^^^^^^^^^^^^^^^^^^^^ note: ...but the trait is unstable - --> $DIR/staged-api.rs:91:7 + --> $DIR/staged-api.rs:90:13 | -LL | trait U {} - | ^ +LL | const trait U {} + | ^ error: trait implementations cannot be const stable yet - --> $DIR/staged-api.rs:113:1 + --> $DIR/staged-api.rs:111:1 | LL | impl const S for u16 {} | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,21 +49,21 @@ LL | impl const S for u16 {} = note: see issue #143874 for more information error: const stability on the impl does not match the const stability on the trait - --> $DIR/staged-api.rs:117:1 + --> $DIR/staged-api.rs:115:1 | LL | impl const S for u32 {} | ^^^^^^^^^^^^^^^^^^^^^^^ | note: this impl is unstable... - --> $DIR/staged-api.rs:117:1 + --> $DIR/staged-api.rs:115:1 | LL | impl const S for u32 {} | ^^^^^^^^^^^^^^^^^^^^^^^ note: ...but the trait is stable - --> $DIR/staged-api.rs:95:7 + --> $DIR/staged-api.rs:93:13 | -LL | trait S {} - | ^ +LL | const trait S {} + | ^ error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` --> $DIR/staged-api.rs:38:5 diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr index c9dc239bef334..39fea4cbbf1c5 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr @@ -1,69 +1,68 @@ error: `[const]` is not allowed here - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:14:32 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ +LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} + | ^^^^^^^ | note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/super-traits-fail-2.rs:11:1 + --> $DIR/super-traits-fail-2.rs:14:21 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:14:32 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:14:32 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:14:32 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } + | +++++ error[E0015]: cannot call non-const method `::a` in constant functions - --> $DIR/super-traits-fail-2.rs:20:7 + --> $DIR/super-traits-fail-2.rs:21:7 | LL | x.a(); | ^^^ | note: method `a` is not const because trait `Foo` is not const - --> $DIR/super-traits-fail-2.rs:6:1 + --> $DIR/super-traits-fail-2.rs:6:21 | -LL | trait Foo { - | ^^^^^^^^^ this trait is not const -LL | fn a(&self); - | ------------ this method is not const +LL | #[cfg(any(ny, nn))] trait Foo { fn a(&self); } + | ^^^^^^^^^ ------------ this method is not const + | | + | this trait is not const = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider making trait `Foo` const | -LL + #[const_trait] -LL | trait Foo { - | +LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } + | +++++ error: aborting due to 5 previous errors diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr index bfbf6980ab833..652bcb66e8d56 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr @@ -1,81 +1,80 @@ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:8:38 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:8:38 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:8:38 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:8:38 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:8:38 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yy, ny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } + | +++++ error[E0015]: cannot call non-const method `::a` in constant functions - --> $DIR/super-traits-fail-2.rs:20:7 + --> $DIR/super-traits-fail-2.rs:21:7 | LL | x.a(); | ^^^ | note: method `a` is not const because trait `Foo` is not const - --> $DIR/super-traits-fail-2.rs:6:1 + --> $DIR/super-traits-fail-2.rs:6:21 | -LL | trait Foo { - | ^^^^^^^^^ this trait is not const -LL | fn a(&self); - | ------------ this method is not const +LL | #[cfg(any(ny, nn))] trait Foo { fn a(&self); } + | ^^^^^^^^^ ------------ this method is not const + | | + | this trait is not const = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider making trait `Foo` const | -LL + #[const_trait] -LL | trait Foo { - | +LL | #[cfg(any(ny, nn))] const trait Foo { fn a(&self); } + | +++++ error: aborting due to 6 previous errors diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.rs b/tests/ui/traits/const-traits/super-traits-fail-2.rs index 36e7c1c4e4acc..7dd888b87b0c1 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.rs +++ b/tests/ui/traits/const-traits/super-traits-fail-2.rs @@ -2,19 +2,20 @@ #![feature(const_trait_impl)] //@ revisions: yy yn ny nn -#[cfg_attr(any(yy, yn), const_trait)] -trait Foo { - fn a(&self); -} +#[cfg(any(yy, yn))] const trait Foo { fn a(&self); } +#[cfg(any(ny, nn))] trait Foo { fn a(&self); } -#[cfg_attr(any(yy, ny), const_trait)] -trait Bar: [const] Foo {} -//[ny,nn]~^ ERROR: `[const]` can only be applied to `const` traits -//[ny,nn]~| ERROR: `[const]` can only be applied to `const` traits -//[ny,nn]~| ERROR: `[const]` can only be applied to `const` traits +#[cfg(any(yy, ny))] const trait Bar: [const] Foo {} +//[ny]~^ ERROR: `[const]` can only be applied to `const` traits +//[ny]~| ERROR: `[const]` can only be applied to `const` traits +//[ny]~| ERROR: `[const]` can only be applied to `const` traits //[ny]~| ERROR: `[const]` can only be applied to `const` traits //[ny]~| ERROR: `[const]` can only be applied to `const` traits -//[yn,nn]~^^^^^^ ERROR: `[const]` is not allowed here +#[cfg(any(yn, nn))] trait Bar: [const] Foo {} +//[yn,nn]~^ ERROR: `[const]` is not allowed here +//[nn]~^^ ERROR: `[const]` can only be applied to `const` traits +//[nn]~| ERROR: `[const]` can only be applied to `const` traits +//[nn]~| ERROR: `[const]` can only be applied to `const` traits const fn foo(x: &T) { x.a(); diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr index 657e8ee82e322..65c6f833ccea1 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr @@ -1,17 +1,17 @@ error: `[const]` is not allowed here - --> $DIR/super-traits-fail-2.rs:11:12 + --> $DIR/super-traits-fail-2.rs:14:32 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ +LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} + | ^^^^^^^ | note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/super-traits-fail-2.rs:11:1 + --> $DIR/super-traits-fail-2.rs:14:21 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[cfg(any(yn, nn))] trait Bar: [const] Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: [const] Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:20:7 + --> $DIR/super-traits-fail-2.rs:21:7 | LL | x.a(); | ^ diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr index 4ae4bbde99bb2..c17a67132116e 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yy.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `T: [const] Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:20:7 + --> $DIR/super-traits-fail-2.rs:21:7 | LL | x.a(); | ^ diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nnn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nnn.stderr index ea487cbd563f2..b31d7eab53eaa 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.nnn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.nnn.stderr @@ -1,27 +1,57 @@ error: `[const]` is not allowed here - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:27:44 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ | note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/super-traits-fail-3.rs:23:1 + --> $DIR/super-traits-fail-3.rs:27:33 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0658]: const trait impls are experimental - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:15:33 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ +LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); } + | ^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:19:33 + | +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^ + | + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:19:50 + | +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ + | + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:27:44 + | +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ + | + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:34:17 | LL | const fn foo(x: &T) { | ^^^^^^^ @@ -31,53 +61,53 @@ LL | const fn foo(x: &T) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:27:44 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:27:44 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:27:44 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:34:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Bar: [const] Foo {} - | ++++++++++++++ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:34:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` @@ -85,31 +115,30 @@ LL | const fn foo(x: &T) { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Bar: [const] Foo {} - | ++++++++++++++ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} + | +++++ error[E0015]: cannot call non-const method `::a` in constant functions - --> $DIR/super-traits-fail-3.rs:36:7 + --> $DIR/super-traits-fail-3.rs:38:7 | LL | x.a(); | ^^^ | note: method `a` is not const because trait `Foo` is not const - --> $DIR/super-traits-fail-3.rs:17:1 + --> $DIR/super-traits-fail-3.rs:17:33 | -LL | trait Foo { - | ^^^^^^^^^ this trait is not const -LL | fn a(&self); - | ------------ this method is not const - = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]` +LL | #[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); } + | ^^^^^^^^^ ------------ this method is not const + | | + | this trait is not const + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable const traits = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider making trait `Foo` const | -LL + #[const_trait] -LL | trait Foo { - | +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ -error: aborting due to 9 previous errors +error: aborting due to 12 previous errors Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nny.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nny.stderr index ea487cbd563f2..ee43dd9d5fc52 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.nny.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.nny.stderr @@ -1,27 +1,45 @@ -error: `[const]` is not allowed here - --> $DIR/super-traits-fail-3.rs:23:12 +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:15:33 + | +LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); } + | ^^^^^ | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:19:33 | -note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/super-traits-fail-3.rs:23:1 +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^ | -LL | trait Bar: [const] Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:27:44 + | +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ + | + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:34:17 | LL | const fn foo(x: &T) { | ^^^^^^^ @@ -31,85 +49,85 @@ LL | const fn foo(x: &T) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | const fn foo(x: &T) { - | ^^^^^^^ can't be applied to `Bar` +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Bar: [const] Foo {} - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | const fn foo(x: &T) { - | ^^^^^^^ can't be applied to `Bar` +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Bar: [const] Foo {} - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error[E0015]: cannot call non-const method `::a` in constant functions - --> $DIR/super-traits-fail-3.rs:36:7 + --> $DIR/super-traits-fail-3.rs:38:7 | LL | x.a(); | ^^^ | note: method `a` is not const because trait `Foo` is not const - --> $DIR/super-traits-fail-3.rs:17:1 + --> $DIR/super-traits-fail-3.rs:17:33 | -LL | trait Foo { - | ^^^^^^^^^ this trait is not const -LL | fn a(&self); - | ------------ this method is not const - = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable `#[const_trait]` +LL | #[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); } + | ^^^^^^^^^ ------------ this method is not const + | | + | this trait is not const + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable const traits = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider making trait `Foo` const | -LL + #[const_trait] -LL | trait Foo { - | +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ -error: aborting due to 9 previous errors +error: aborting due to 11 previous errors Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr index b00ad706a5fa1..1c56aa1297944 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr @@ -1,54 +1,97 @@ +error: `[const]` is not allowed here + --> $DIR/super-traits-fail-3.rs:27:44 + | +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ + | +note: this trait is not `const`, so it cannot have `[const]` trait bounds + --> $DIR/super-traits-fail-3.rs:27:33 + | +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0658]: const trait impls are experimental - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:15:33 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ +LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); } + | ^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:19:33 | -LL | const fn foo(x: &T) { - | ^^^^^^^ +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -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. - --> $DIR/super-traits-fail-3.rs:15:37 +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | #[cfg_attr(any(yyy, yyn, nyy, nyn), const_trait)] - | ^^^^^^^^^^^ +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -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. - --> $DIR/super-traits-fail-3.rs:21:37 +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:27:44 | -LL | #[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)] - | ^^^^^^^^^^^ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: cannot call conditionally-const method `::a` in constant functions - --> $DIR/super-traits-fail-3.rs:36:7 +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:34:17 | -LL | x.a(); - | ^^^ +LL | const fn foo(x: &T) { + | ^^^^^^^ | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors +error: `[const]` can only be applied to `const` traits + --> $DIR/super-traits-fail-3.rs:34:17 + | +LL | const fn foo(x: &T) { + | ^^^^^^^ can't be applied to `Bar` + | +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations + | +LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} + | +++++ + +error: `[const]` can only be applied to `const` traits + --> $DIR/super-traits-fail-3.rs:34:17 + | +LL | const fn foo(x: &T) { + | ^^^^^^^ can't be applied to `Bar` + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations + | +LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} + | +++++ + +error[E0015]: cannot call non-const method `::a` in constant functions + --> $DIR/super-traits-fail-3.rs:38:7 + | +LL | x.a(); + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nyy.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nyy.stderr index b00ad706a5fa1..692e84176a78b 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.nyy.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.nyy.stderr @@ -1,45 +1,55 @@ error[E0658]: const trait impls are experimental - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:15:33 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ +LL | #[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); } + | ^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: const trait impls are experimental - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:19:33 | -LL | const fn foo(x: &T) { - | ^^^^^^^ +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -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. - --> $DIR/super-traits-fail-3.rs:15:37 +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | #[cfg_attr(any(yyy, yyn, nyy, nyn), const_trait)] - | ^^^^^^^^^^^ +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -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. - --> $DIR/super-traits-fail-3.rs:21:37 +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:27:44 | -LL | #[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)] - | ^^^^^^^^^^^ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ + | + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/super-traits-fail-3.rs:34:17 + | +LL | const fn foo(x: &T) { + | ^^^^^^^ | = note: see issue #143874 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: cannot call conditionally-const method `::a` in constant functions - --> $DIR/super-traits-fail-3.rs:36:7 + --> $DIR/super-traits-fail-3.rs:38:7 | LL | x.a(); | ^^^ @@ -49,6 +59,6 @@ LL | x.a(); = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.rs b/tests/ui/traits/const-traits/super-traits-fail-3.rs index d74bd34678407..7dd434c528d09 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.rs +++ b/tests/ui/traits/const-traits/super-traits-fail-3.rs @@ -12,31 +12,33 @@ /// nny: feature not enabled, Foo is not const, Bar is const /// nnn: feature not enabled, Foo is not const, Bar is not const -#[cfg_attr(any(yyy, yyn, nyy, nyn), const_trait)] -//[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 -trait Foo { - fn a(&self); -} +#[cfg(any(yyy, yyn, nyy, nyn))] const trait Foo { fn a(&self); } +//[nyy,nyn,nny,nnn]~^ ERROR: const trait impls are experimental +#[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); } -#[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)] -//[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 -trait Bar: [const] Foo {} -//[yny,ynn,nny,nnn]~^ ERROR: `[const]` can only be applied to `const` traits -//[yny,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `const` traits -//[yny,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `const` traits -//[yny]~^^^^ ERROR: `[const]` can only be applied to `const` traits -//[yny]~| ERROR: `[const]` can only be applied to `const` traits -//[yyn,ynn,nny,nnn]~^^^^^^ ERROR: `[const]` is not allowed here -//[nyy,nyn,nny,nnn]~^^^^^^^ ERROR: const trait impls are experimental +#[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} +//[nyy,nyn,nny,nnn]~^ ERROR: const trait impls are experimental +//[nyy,nyn,nny,nnn]~| ERROR: const trait impls are experimental +//[yny,nny]~^^^ ERROR: `[const]` can only be applied to `const` traits +//[yny,nny]~| ERROR: `[const]` can only be applied to `const` traits +//[yny,nny]~| ERROR: `[const]` can only be applied to `const` traits +//[yny,nny]~| ERROR: `[const]` can only be applied to `const` traits +//[yny,nny]~| ERROR: `[const]` can only be applied to `const` traits +#[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} +//[yyn,ynn,nyn,nnn]~^ ERROR: `[const]` is not allowed here +//[nyy,nyn,nny,nnn]~^^ ERROR: const trait impls are experimental +//[ynn,nnn]~^^^ ERROR: `[const]` can only be applied to `const` traits +//[ynn,nnn]~| ERROR: `[const]` can only be applied to `const` traits +//[ynn,nnn]~| ERROR: `[const]` can only be applied to `const` traits const fn foo(x: &T) { - //[yyn,ynn,nny,nnn]~^ ERROR: `[const]` can only be applied to `const` traits - //[yyn,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `const` traits + //[yyn,ynn,nyn,nnn]~^ ERROR: `[const]` can only be applied to `const` traits + //[yyn,ynn,nyn,nnn]~| ERROR: `[const]` can only be applied to `const` traits //[nyy,nyn,nny,nnn]~^^^ ERROR: const trait impls are experimental x.a(); //[yyn]~^ ERROR: the trait bound `T: [const] Foo` is not satisfied - //[ynn,yny,nny,nnn]~^^ ERROR: cannot call non-const method `::a` in constant functions - //[nyy,nyn]~^^^ ERROR: cannot call conditionally-const method `::a` in constant functions + //[ynn,yny,nny,nnn,nyn]~^^ ERROR: cannot call non-const method `::a` in constant functions + //[nyy]~^^^ ERROR: cannot call conditionally-const method `::a` in constant functions } fn main() {} diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.ynn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.ynn.stderr index 5951caebe7335..4b02310d75fa5 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.ynn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.ynn.stderr @@ -1,63 +1,63 @@ error: `[const]` is not allowed here - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:27:44 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ | note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/super-traits-fail-3.rs:23:1 + --> $DIR/super-traits-fail-3.rs:27:33 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:27:44 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:27:44 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:27:44 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:34:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | help: mark `Bar` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Bar: [const] Foo {} - | ++++++++++++++ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:34:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` @@ -65,28 +65,27 @@ LL | const fn foo(x: &T) { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Bar` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Bar: [const] Foo {} - | ++++++++++++++ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} + | +++++ error[E0015]: cannot call non-const method `::a` in constant functions - --> $DIR/super-traits-fail-3.rs:36:7 + --> $DIR/super-traits-fail-3.rs:38:7 | LL | x.a(); | ^^^ | note: method `a` is not const because trait `Foo` is not const - --> $DIR/super-traits-fail-3.rs:17:1 + --> $DIR/super-traits-fail-3.rs:17:33 | -LL | trait Foo { - | ^^^^^^^^^ this trait is not const -LL | fn a(&self); - | ------------ this method is not const +LL | #[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); } + | ^^^^^^^^^ ------------ this method is not const + | | + | this trait is not const = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider making trait `Foo` const | -LL + #[const_trait] -LL | trait Foo { - | +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: aborting due to 7 previous errors diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.yny.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.yny.stderr index 563495204ad7b..cf86cbbd0e251 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.yny.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.yny.stderr @@ -1,81 +1,80 @@ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:19:50 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ can't be applied to `Foo` +LL | #[cfg(any(yyy, yny, nyy, nny))] const trait Bar: [const] Foo {} + | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Foo` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Foo { - | ++++++++++++++ +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error[E0015]: cannot call non-const method `::a` in constant functions - --> $DIR/super-traits-fail-3.rs:36:7 + --> $DIR/super-traits-fail-3.rs:38:7 | LL | x.a(); | ^^^ | note: method `a` is not const because trait `Foo` is not const - --> $DIR/super-traits-fail-3.rs:17:1 + --> $DIR/super-traits-fail-3.rs:17:33 | -LL | trait Foo { - | ^^^^^^^^^ this trait is not const -LL | fn a(&self); - | ------------ this method is not const +LL | #[cfg(any(yny, ynn, nny, nnn))] trait Foo { fn a(&self); } + | ^^^^^^^^^ ------------ this method is not const + | | + | this trait is not const = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider making trait `Foo` const | -LL + #[const_trait] -LL | trait Foo { - | +LL | #[cfg(any(yny, ynn, nny, nnn))] const trait Foo { fn a(&self); } + | +++++ error: aborting due to 6 previous errors diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr index de3664dae841f..7b5a1f7a6a230 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr @@ -1,28 +1,28 @@ error: `[const]` is not allowed here - --> $DIR/super-traits-fail-3.rs:23:12 + --> $DIR/super-traits-fail-3.rs:27:44 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^ | note: this trait is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/super-traits-fail-3.rs:23:1 + --> $DIR/super-traits-fail-3.rs:27:33 | -LL | trait Bar: [const] Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] trait Bar: [const] Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:34:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | help: mark `Bar` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Bar: [const] Foo {} - | ++++++++++++++ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} + | +++++ error: `[const]` can only be applied to `const` traits - --> $DIR/super-traits-fail-3.rs:32:17 + --> $DIR/super-traits-fail-3.rs:34:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` @@ -30,11 +30,11 @@ LL | const fn foo(x: &T) { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: mark `Bar` as `const` to allow it to have `const` implementations | -LL | #[const_trait] trait Bar: [const] Foo {} - | ++++++++++++++ +LL | #[cfg(any(yyn, ynn, nyn, nnn))] const trait Bar: [const] Foo {} + | +++++ error[E0277]: the trait bound `T: [const] Foo` is not satisfied - --> $DIR/super-traits-fail-3.rs:36:7 + --> $DIR/super-traits-fail-3.rs:38:7 | LL | x.a(); | ^ diff --git a/tests/ui/traits/const-traits/super-traits-fail.rs b/tests/ui/traits/const-traits/super-traits-fail.rs index 15e05be4d8628..4f835fd4191ca 100644 --- a/tests/ui/traits/const-traits/super-traits-fail.rs +++ b/tests/ui/traits/const-traits/super-traits-fail.rs @@ -2,12 +2,10 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Foo { +const trait Foo { fn a(&self); } -#[const_trait] -trait Bar: [const] Foo {} +const trait Bar: [const] Foo {} struct S; impl Foo for S { diff --git a/tests/ui/traits/const-traits/super-traits-fail.stderr b/tests/ui/traits/const-traits/super-traits-fail.stderr index 3010a5df0c31f..37ce0586deb4e 100644 --- a/tests/ui/traits/const-traits/super-traits-fail.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `S: [const] Foo` is not satisfied - --> $DIR/super-traits-fail.rs:17:20 + --> $DIR/super-traits-fail.rs:15:20 | LL | impl const Bar for S {} | ^ diff --git a/tests/ui/traits/const-traits/super-traits.rs b/tests/ui/traits/const-traits/super-traits.rs index b5fd985ae439e..169627149a300 100644 --- a/tests/ui/traits/const-traits/super-traits.rs +++ b/tests/ui/traits/const-traits/super-traits.rs @@ -2,13 +2,11 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -trait Foo { +const trait Foo { fn a(&self); } -#[const_trait] -trait Bar: [const] Foo {} +const trait Bar: [const] Foo {} struct S; impl const Foo for S { diff --git a/tests/ui/traits/const-traits/syntactical-unstable.rs b/tests/ui/traits/const-traits/syntactical-unstable.rs index 5c542d327f151..6518dd0ac4bb3 100644 --- a/tests/ui/traits/const-traits/syntactical-unstable.rs +++ b/tests/ui/traits/const-traits/syntactical-unstable.rs @@ -9,8 +9,7 @@ use std::ops::Deref; extern crate staged_api; use staged_api::MyTrait; -#[const_trait] -trait Foo: [const] MyTrait { +const trait Foo: [const] MyTrait { //~^ ERROR use of unstable const library feature `unstable` type Item: [const] MyTrait; //~^ ERROR use of unstable const library feature `unstable` diff --git a/tests/ui/traits/const-traits/syntactical-unstable.stderr b/tests/ui/traits/const-traits/syntactical-unstable.stderr index b8cc8e69f75b3..e2a65c724438b 100644 --- a/tests/ui/traits/const-traits/syntactical-unstable.stderr +++ b/tests/ui/traits/const-traits/syntactical-unstable.stderr @@ -1,16 +1,16 @@ error[E0658]: use of unstable const library feature `unstable` - --> $DIR/syntactical-unstable.rs:13:20 + --> $DIR/syntactical-unstable.rs:12:26 | -LL | trait Foo: [const] MyTrait { - | ------- ^^^^^^^ - | | - | trait is not stable as const yet +LL | const trait Foo: [const] MyTrait { + | ------- ^^^^^^^ + | | + | trait is not stable as const yet | = help: add `#![feature(unstable)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable const library feature `unstable` - --> $DIR/syntactical-unstable.rs:19:45 + --> $DIR/syntactical-unstable.rs:18:45 | LL | const fn where_clause() where T: [const] MyTrait {} | ------- ^^^^^^^ @@ -21,7 +21,7 @@ LL | const fn where_clause() where T: [const] MyTrait {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable const library feature `unstable` - --> $DIR/syntactical-unstable.rs:22:53 + --> $DIR/syntactical-unstable.rs:21:53 | LL | const fn nested() where T: Deref {} | ------- ^^^^^^^ @@ -32,7 +32,7 @@ LL | const fn nested() where T: Deref {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable const library feature `unstable` - --> $DIR/syntactical-unstable.rs:25:33 + --> $DIR/syntactical-unstable.rs:24:33 | LL | const fn rpit() -> impl [const] MyTrait { Local } | ------- ^^^^^^^ @@ -43,7 +43,7 @@ LL | const fn rpit() -> impl [const] MyTrait { Local } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable const library feature `unstable` - --> $DIR/syntactical-unstable.rs:29:12 + --> $DIR/syntactical-unstable.rs:28:12 | LL | impl const MyTrait for Local { | ^^^^^^^ trait is not stable as const yet @@ -52,7 +52,7 @@ LL | impl const MyTrait for Local { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable const library feature `unstable` - --> $DIR/syntactical-unstable.rs:15:24 + --> $DIR/syntactical-unstable.rs:14:24 | LL | type Item: [const] MyTrait; | ------- ^^^^^^^ diff --git a/tests/ui/traits/const-traits/trait-default-body-stability.rs b/tests/ui/traits/const-traits/trait-default-body-stability.rs index a8157d37ce3f9..1053f54aa6fce 100644 --- a/tests/ui/traits/const-traits/trait-default-body-stability.rs +++ b/tests/ui/traits/const-traits/trait-default-body-stability.rs @@ -39,8 +39,7 @@ impl const FromResidual for T { #[stable(feature = "foo", since = "1.0")] #[rustc_const_unstable(feature = "const_tr", issue = "none")] -#[const_trait] -pub trait Tr { +pub const trait Tr { #[stable(feature = "foo", since = "1.0")] fn bar() -> T { T? diff --git a/tests/ui/traits/const-traits/trait-fn-const.rs b/tests/ui/traits/const-traits/trait-fn-const.rs index 07eac032a82a6..b8ad7b867a5a3 100644 --- a/tests/ui/traits/const-traits/trait-fn-const.rs +++ b/tests/ui/traits/const-traits/trait-fn-const.rs @@ -1,8 +1,7 @@ // Regression test for issue #113378. #![feature(const_trait_impl)] -#[const_trait] -trait Trait { +const trait Trait { const fn fun(); //~ ERROR functions in traits cannot be declared const } diff --git a/tests/ui/traits/const-traits/trait-fn-const.stderr b/tests/ui/traits/const-traits/trait-fn-const.stderr index 4d0b03046d27d..6e1ad29a3c2c1 100644 --- a/tests/ui/traits/const-traits/trait-fn-const.stderr +++ b/tests/ui/traits/const-traits/trait-fn-const.stderr @@ -1,9 +1,8 @@ error[E0379]: functions in traits cannot be declared const - --> $DIR/trait-fn-const.rs:6:5 + --> $DIR/trait-fn-const.rs:5:5 | -LL | #[const_trait] - | -------------- this declares all associated functions implicitly const -LL | trait Trait { +LL | const trait Trait { + | ----- this declares all associated functions implicitly const LL | const fn fun(); | ^^^^^- | | @@ -11,7 +10,7 @@ LL | const fn fun(); | help: remove the `const` error[E0379]: functions in trait impls cannot be declared const - --> $DIR/trait-fn-const.rs:10:5 + --> $DIR/trait-fn-const.rs:9:5 | LL | impl const Trait for () { | ----- this declares all associated functions implicitly const @@ -22,7 +21,7 @@ LL | const fn fun() {} | help: remove the `const` error[E0379]: functions in trait impls cannot be declared const - --> $DIR/trait-fn-const.rs:14:5 + --> $DIR/trait-fn-const.rs:13:5 | LL | const fn fun() {} | ^^^^^ functions in trait impls cannot be const @@ -38,7 +37,7 @@ LL | impl const Trait for u32 { | +++++ error[E0379]: functions in traits cannot be declared const - --> $DIR/trait-fn-const.rs:18:5 + --> $DIR/trait-fn-const.rs:17:5 | LL | const fn fun(); | ^^^^^ functions in traits cannot be const @@ -48,11 +47,10 @@ help: remove the `const` ... LL - const fn fun(); LL + fn fun(); | -help: ... and declare the trait to be a `#[const_trait]` instead - | -LL + #[const_trait] -LL | trait NonConst { +help: ... and declare the trait to be const instead | +LL | const trait NonConst { + | +++++ error: aborting due to 4 previous errors diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.rs b/tests/ui/traits/const-traits/trait-where-clause-const.rs index ccb514086cc87..548c5529945dc 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-const.rs +++ b/tests/ui/traits/const-traits/trait-where-clause-const.rs @@ -6,11 +6,9 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Bar {} +const trait Bar {} -#[const_trait] -trait Foo { +const trait Foo { fn a(); fn b() where Self: [const] Bar; fn c(); diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.stderr b/tests/ui/traits/const-traits/trait-where-clause-const.stderr index 71f9bdff8786e..20dd395b820bf 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-const.stderr +++ b/tests/ui/traits/const-traits/trait-where-clause-const.stderr @@ -1,23 +1,23 @@ error[E0277]: the trait bound `T: [const] Bar` is not satisfied - --> $DIR/trait-where-clause-const.rs:21:5 + --> $DIR/trait-where-clause-const.rs:19:5 | LL | T::b(); | ^ | note: required by a bound in `Foo::b` - --> $DIR/trait-where-clause-const.rs:15:24 + --> $DIR/trait-where-clause-const.rs:13:24 | LL | fn b() where Self: [const] Bar; | ^^^^^^^^^^^ required by this bound in `Foo::b` error[E0277]: the trait bound `T: [const] Bar` is not satisfied - --> $DIR/trait-where-clause-const.rs:23:12 + --> $DIR/trait-where-clause-const.rs:21:12 | LL | T::c::(); | ^ | note: required by a bound in `Foo::c` - --> $DIR/trait-where-clause-const.rs:16:13 + --> $DIR/trait-where-clause-const.rs:14:13 | LL | fn c(); | ^^^^^^^^^^^ required by this bound in `Foo::c` diff --git a/tests/ui/traits/const-traits/trait-where-clause-run.rs b/tests/ui/traits/const-traits/trait-where-clause-run.rs index c40f071f45728..d24a2abb17833 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-run.rs +++ b/tests/ui/traits/const-traits/trait-where-clause-run.rs @@ -3,13 +3,11 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Bar { +const trait Bar { fn bar() -> u8; } -#[const_trait] -trait Foo { +const trait Foo { fn foo() -> u8 where Self: [const] Bar { ::bar() * 6 } diff --git a/tests/ui/traits/const-traits/trait-where-clause-self-referential.rs b/tests/ui/traits/const-traits/trait-where-clause-self-referential.rs index 3a5350cd4ea3d..39829adbaf4b5 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-self-referential.rs +++ b/tests/ui/traits/const-traits/trait-where-clause-self-referential.rs @@ -2,8 +2,7 @@ //@ compile-flags: -Znext-solver #![feature(const_trait_impl)] -#[const_trait] -trait Foo { +const trait Foo { fn bar() where Self: [const] Foo; } diff --git a/tests/ui/traits/const-traits/trait-where-clause.rs b/tests/ui/traits/const-traits/trait-where-clause.rs index 6aebab79090a9..3ff53f590f812 100644 --- a/tests/ui/traits/const-traits/trait-where-clause.rs +++ b/tests/ui/traits/const-traits/trait-where-clause.rs @@ -1,7 +1,6 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Bar {} +const trait Bar {} trait Foo { fn a(); diff --git a/tests/ui/traits/const-traits/trait-where-clause.stderr b/tests/ui/traits/const-traits/trait-where-clause.stderr index dda91e6bca1ed..57d87f74565e2 100644 --- a/tests/ui/traits/const-traits/trait-where-clause.stderr +++ b/tests/ui/traits/const-traits/trait-where-clause.stderr @@ -1,35 +1,35 @@ error: `[const]` is not allowed here - --> $DIR/trait-where-clause.rs:8:24 + --> $DIR/trait-where-clause.rs:7:24 | LL | fn b() where Self: [const] Bar; | ^^^^^^^ | note: this function is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/trait-where-clause.rs:8:8 + --> $DIR/trait-where-clause.rs:7:8 | LL | fn b() where Self: [const] Bar; | ^ error: `[const]` is not allowed here - --> $DIR/trait-where-clause.rs:10:13 + --> $DIR/trait-where-clause.rs:9:13 | LL | fn c(); | ^^^^^^^ | note: this function is not `const`, so it cannot have `[const]` trait bounds - --> $DIR/trait-where-clause.rs:10:8 + --> $DIR/trait-where-clause.rs:9:8 | LL | fn c(); | ^ error[E0277]: the trait bound `T: Bar` is not satisfied - --> $DIR/trait-where-clause.rs:16:5 + --> $DIR/trait-where-clause.rs:15:5 | LL | T::b(); | ^ the trait `Bar` is not implemented for `T` | note: required by a bound in `Foo::b` - --> $DIR/trait-where-clause.rs:8:24 + --> $DIR/trait-where-clause.rs:7:24 | LL | fn b() where Self: [const] Bar; | ^^^^^^^^^^^ required by this bound in `Foo::b` @@ -39,13 +39,13 @@ LL | fn test1() { | +++++ error[E0277]: the trait bound `T: Bar` is not satisfied - --> $DIR/trait-where-clause.rs:18:12 + --> $DIR/trait-where-clause.rs:17:12 | LL | T::c::(); | ^ the trait `Bar` is not implemented for `T` | note: required by a bound in `Foo::c` - --> $DIR/trait-where-clause.rs:10:13 + --> $DIR/trait-where-clause.rs:9:13 | LL | fn c(); | ^^^^^^^^^^^ required by this bound in `Foo::c` diff --git a/tests/ui/traits/const-traits/unconstrained-var-specialization.rs b/tests/ui/traits/const-traits/unconstrained-var-specialization.rs index 43a3311445012..4330e0aead1ac 100644 --- a/tests/ui/traits/const-traits/unconstrained-var-specialization.rs +++ b/tests/ui/traits/const-traits/unconstrained-var-specialization.rs @@ -7,8 +7,7 @@ // In the default impl below, `A` is constrained by the projection predicate, and if the host effect // predicate for `const Foo` doesn't resolve vars, then specialization will fail. -#[const_trait] -trait Foo {} +const trait Foo {} pub trait Iterator { type Item; diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs index c82b442750097..57641423643e8 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.rs @@ -7,8 +7,7 @@ fn require() {} -#[const_trait] -trait Trait { +const trait Trait { fn make() -> u32; } diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr index 9750d806ce97a..1a2bc6c2c5f59 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr @@ -7,88 +7,88 @@ LL | #![feature(const_trait_impl, generic_const_exprs)] = help: remove one of these features error[E0391]: cycle detected when evaluating type-level constant - --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + --> $DIR/unsatisfied-const-trait-bound.rs:28:35 | LL | fn accept0(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `accept0::{constant#0}`... - --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + --> $DIR/unsatisfied-const-trait-bound.rs:28:35 | LL | fn accept0(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ note: ...which requires checking if `accept0::{constant#0}` is a trivial const... - --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + --> $DIR/unsatisfied-const-trait-bound.rs:28:35 | LL | fn accept0(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ note: ...which requires building MIR for `accept0::{constant#0}`... - --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + --> $DIR/unsatisfied-const-trait-bound.rs:28:35 | LL | fn accept0(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ note: ...which requires building an abstract representation for `accept0::{constant#0}`... - --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + --> $DIR/unsatisfied-const-trait-bound.rs:28:35 | LL | fn accept0(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ note: ...which requires building THIR for `accept0::{constant#0}`... - --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + --> $DIR/unsatisfied-const-trait-bound.rs:28:35 | LL | fn accept0(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ note: ...which requires type-checking `accept0::{constant#0}`... - --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + --> $DIR/unsatisfied-const-trait-bound.rs:28:35 | LL | fn accept0(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ = note: ...which again requires evaluating type-level constant, completing the cycle note: cycle used when checking that `accept0` is well-formed - --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + --> $DIR/unsatisfied-const-trait-bound.rs:28:35 | LL | fn accept0(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ = 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 error[E0391]: cycle detected when checking if `accept1::{constant#0}` is a trivial const - --> $DIR/unsatisfied-const-trait-bound.rs:33:49 + --> $DIR/unsatisfied-const-trait-bound.rs:32:49 | LL | const fn accept1(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ | note: ...which requires building MIR for `accept1::{constant#0}`... - --> $DIR/unsatisfied-const-trait-bound.rs:33:49 + --> $DIR/unsatisfied-const-trait-bound.rs:32:49 | LL | const fn accept1(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ note: ...which requires building an abstract representation for `accept1::{constant#0}`... - --> $DIR/unsatisfied-const-trait-bound.rs:33:49 + --> $DIR/unsatisfied-const-trait-bound.rs:32:49 | LL | const fn accept1(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ note: ...which requires building THIR for `accept1::{constant#0}`... - --> $DIR/unsatisfied-const-trait-bound.rs:33:49 + --> $DIR/unsatisfied-const-trait-bound.rs:32:49 | LL | const fn accept1(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ note: ...which requires type-checking `accept1::{constant#0}`... - --> $DIR/unsatisfied-const-trait-bound.rs:33:49 + --> $DIR/unsatisfied-const-trait-bound.rs:32:49 | LL | const fn accept1(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ note: ...which requires evaluating type-level constant... - --> $DIR/unsatisfied-const-trait-bound.rs:33:49 + --> $DIR/unsatisfied-const-trait-bound.rs:32:49 | LL | const fn accept1(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `accept1::{constant#0}`... - --> $DIR/unsatisfied-const-trait-bound.rs:33:49 + --> $DIR/unsatisfied-const-trait-bound.rs:32:49 | LL | const fn accept1(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ = note: ...which again requires checking if `accept1::{constant#0}` is a trivial const, completing the cycle note: cycle used when const-evaluating + checking `accept1::{constant#0}` - --> $DIR/unsatisfied-const-trait-bound.rs:33:49 + --> $DIR/unsatisfied-const-trait-bound.rs:32:49 | LL | const fn accept1(_: Container<{ T::make() }>) {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/variance.rs b/tests/ui/traits/const-traits/variance.rs index 90b5c50161d51..73014703adc03 100644 --- a/tests/ui/traits/const-traits/variance.rs +++ b/tests/ui/traits/const-traits/variance.rs @@ -2,8 +2,7 @@ #![allow(internal_features)] #![rustc_variance_of_opaques] -#[const_trait] -trait Foo {} +const trait Foo {} impl const Foo for () {} diff --git a/tests/ui/traits/const-traits/variance.stderr b/tests/ui/traits/const-traits/variance.stderr index f55069311848a..1367ec6929a52 100644 --- a/tests/ui/traits/const-traits/variance.stderr +++ b/tests/ui/traits/const-traits/variance.stderr @@ -1,5 +1,5 @@ error: ['a: *] - --> $DIR/variance.rs:10:21 + --> $DIR/variance.rs:9:21 | LL | fn foo<'a: 'a>() -> impl const Foo {} | ^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/next-solver/canonical/effect-var.rs b/tests/ui/traits/next-solver/canonical/effect-var.rs index 82dbde0413c49..872a70417f485 100644 --- a/tests/ui/traits/next-solver/canonical/effect-var.rs +++ b/tests/ui/traits/next-solver/canonical/effect-var.rs @@ -3,8 +3,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Foo { +const trait Foo { fn foo(); } diff --git a/triagebot.toml b/triagebot.toml index 325a62235c71c..b9739149ea837 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1419,6 +1419,7 @@ compiler_leads = [ ] compiler = [ "@BoxyUwU", + "@chenyukang", "@compiler-errors", "@davidtwco", "@eholk",