diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index 7985686798519..c7fa2527eb2f3 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -49,7 +49,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// At the end of processing, the substitution S (once /// canonicalized) then represents the values that you computed /// for each of the canonical inputs to your query. - pub fn instantiate_canonical_with_fresh_inference_vars( &self, span: Span, diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 41995ca509ef6..86229dbfad746 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -27,15 +27,12 @@ use super::glb::Glb; use super::lub::Lub; use super::sub::Sub; use super::type_variable::TypeVariableValue; -use super::unify_key::replace_if_possible; -use super::unify_key::{ConstVarValue, ConstVariableValue}; -use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use super::{InferCtxt, MiscVariable, TypeTrace}; - use crate::traits::{Obligation, PredicateObligations}; - use rustc_data_structures::sso::SsoHashMap; use rustc_hir::def_id::DefId; +use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; +use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; @@ -140,8 +137,8 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { return Ok(a); } - let a = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table(), a); - let b = replace_if_possible(&mut self.inner.borrow_mut().const_unification_table(), b); + let a = self.shallow_resolve(a); + let b = self.shallow_resolve(b); let a_is_expected = relation.a_is_expected(); diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index e9d3b6a8aa1a4..0a11a81c29425 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -30,17 +30,13 @@ //! solving a set of constraints. In contrast, the type inferencer assigns a value to each type //! variable only once, and it does so as soon as it can, so it is reasonable to ask what the type //! inferencer knows "so far". - +use super::InferCtxt; +use rustc_data_structures::fx::FxHashMap; +use rustc_middle::infer::unify_key::ToType; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; - -use rustc_data_structures::fx::FxHashMap; - use std::collections::hash_map::Entry; -use super::unify_key::ToType; -use super::InferCtxt; - pub struct TypeFreshener<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, ty_freshen_count: u32, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index bd59bf4dea883..cefe7aae396b4 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -70,8 +70,6 @@ mod sub; pub mod type_variable; mod undo_log; -pub use rustc_middle::infer::unify_key; - #[must_use] #[derive(Debug)] pub struct InferOk<'tcx, T> { @@ -558,9 +556,9 @@ impl<'tcx> fmt::Display for FixupError<'tcx> { } } -/// Helper type of a temporary returned by `tcx.infer_ctxt()`. -/// Necessary because we can't write the following bound: -/// `F: for<'b, 'tcx> where 'tcx FnOnce(InferCtxt<'b, 'tcx>)`. +/// A temporary returned by `tcx.infer_ctxt()`. This is necessary +/// for multiple `InferCtxt` to share the same `in_progress_typeck_results` +/// without using `Rc` or something similar. pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, fresh_typeck_results: Option>>, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 50a3df21a3bc9..d43c661dda6fa 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2548,7 +2548,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { /// Return `Some` only if we are sure this type does *not* /// allow zero initialization. fn ty_find_init_error<'tcx>( - tcx: TyCtxt<'tcx>, + cx: &LateContext<'tcx>, ty: Ty<'tcx>, init: InitKind, ) -> Option { @@ -2575,7 +2575,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { Adt(adt_def, substs) if !adt_def.is_union() => { // First check if this ADT has a layout attribute (like `NonNull` and friends). use std::ops::Bound; - match tcx.layout_scalar_valid_range(adt_def.did()) { + match cx.tcx.layout_scalar_valid_range(adt_def.did()) { // We exploit here that `layout_scalar_valid_range` will never // return `Bound::Excluded`. (And we have tests checking that we // handle the attribute correctly.) @@ -2603,12 +2603,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // Proceed recursively, check all fields. let variant = &adt_def.variant(VariantIdx::from_u32(0)); variant.fields.iter().find_map(|field| { - ty_find_init_error(tcx, field.ty(tcx, substs), init).map( + ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map( |(mut msg, span)| { if span.is_none() { // Point to this field, should be helpful for figuring // out where the source of the error is. - let span = tcx.def_span(field.did); + let span = cx.tcx.def_span(field.did); write!( &mut msg, " (in this {} field)", @@ -2627,7 +2627,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // Multi-variant enum. _ => { if init == InitKind::Uninit && is_multi_variant(*adt_def) { - let span = tcx.def_span(adt_def.did()); + let span = cx.tcx.def_span(adt_def.did()); Some(( "enums have to be initialized to a variant".to_string(), Some(span), @@ -2642,7 +2642,16 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { } Tuple(..) => { // Proceed recursively, check all fields. - ty.tuple_fields().iter().find_map(|field| ty_find_init_error(tcx, field, init)) + ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init)) + } + Array(ty, len) => { + if matches!(len.try_eval_usize(cx.tcx, cx.param_env), Some(v) if v > 0) { + // Array length known at array non-empty -- recurse. + ty_find_init_error(cx, *ty, init) + } else { + // Empty array or size unknown. + None + } } // Conservative fallback. _ => None, @@ -2655,7 +2664,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // We are extremely conservative with what we warn about. let conjured_ty = cx.typeck_results().expr_ty(expr); if let Some((msg, span)) = - with_no_trimmed_paths!(ty_find_init_error(cx.tcx, conjured_ty, init)) + with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init)) { cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| { let mut err = lint.build(&format!( diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index dd303aaada900..f2627885d030d 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -1,13 +1,8 @@ -use crate::ty::{self, InferConst, Ty, TyCtxt}; -use rustc_data_structures::snapshot_vec; -use rustc_data_structures::undo_log::UndoLogs; -use rustc_data_structures::unify::{ - self, EqUnifyValue, InPlace, NoError, UnificationTable, UnifyKey, UnifyValue, -}; +use crate::ty::{self, Ty, TyCtxt}; +use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue}; use rustc_span::def_id::DefId; use rustc_span::symbol::Symbol; use rustc_span::Span; - use std::cmp; use std::marker::PhantomData; @@ -165,23 +160,3 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> { }) } } - -impl<'tcx> EqUnifyValue for ty::Const<'tcx> {} - -pub fn replace_if_possible<'tcx, V, L>( - table: &mut UnificationTable, V, L>>, - c: ty::Const<'tcx>, -) -> ty::Const<'tcx> -where - V: snapshot_vec::VecLike>>, - L: UndoLogs>>>, -{ - if let ty::ConstKind::Infer(InferConst::Var(vid)) = c.val() { - match table.probe_value(vid).val.known() { - Some(c) => c, - None => c, - } - } else { - c - } -} diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 00445690f8f02..c414d7c031c04 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -29,10 +29,11 @@ impl<'tcx> LibFeatureCollector<'tcx> { } fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option, Span)> { - let stab_attrs = [sym::stable, sym::unstable, sym::rustc_const_unstable]; + let stab_attrs = + [sym::stable, sym::unstable, sym::rustc_const_stable, sym::rustc_const_unstable]; - // Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`, - // `#[rustc_const_unstable (..)]`). + // Find a stability attribute: one of #[stable(…)], #[unstable(…)], + // #[rustc_const_stable(…)], or #[rustc_const_unstable(…)]. if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) { let meta_kind = attr.meta_kind(); if let Some(MetaItemKind::List(ref metas)) = meta_kind { @@ -52,7 +53,9 @@ impl<'tcx> LibFeatureCollector<'tcx> { // This additional check for stability is to make sure we // don't emit additional, irrelevant errors for malformed // attributes. - if *stab_attr != sym::stable || since.is_some() { + let is_unstable = + matches!(*stab_attr, sym::unstable | sym::rustc_const_unstable); + if since.is_some() || is_unstable { return Some((feature, since, attr.span)); } } diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 00a93ccc9aa09..02f6b4060599e 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -1,7 +1,7 @@ //! Checks validity of naked functions. use rustc_ast::{Attribute, InlineAsmOptions}; -use rustc_errors::struct_span_err; +use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{FnKind, Visitor}; @@ -274,12 +274,25 @@ impl<'tcx> CheckInlineAssembly<'tcx> { } if !asm.options.contains(InlineAsmOptions::NORETURN) { + let last_span = asm + .operands + .last() + .map_or_else(|| asm.template_strs.last().unwrap().2, |op| op.1) + .shrink_to_hi(); + struct_span_err!( self.tcx.sess, span, E0787, "asm in naked functions must use `noreturn` option" ) + .span_suggestion( + last_span, + "consider specifying that the asm block is responsible \ + for returning from the function", + String::from(", options(noreturn)"), + Applicability::MachineApplicable, + ) .emit(); } } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 6cceec8621304..54f7c68060f63 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -131,16 +131,18 @@ fn object_safety_violations_for_trait( }), ); - violations.extend( - tcx.associated_items(trait_def_id) - .in_definition_order() - .filter(|item| item.kind == ty::AssocKind::Type) - .filter(|item| !tcx.generics_of(item.def_id).params.is_empty()) - .map(|item| { - let ident = item.ident(tcx); - ObjectSafetyViolation::GAT(ident.name, ident.span) - }), - ); + if !tcx.features().generic_associated_types_extended { + violations.extend( + tcx.associated_items(trait_def_id) + .in_definition_order() + .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| !tcx.generics_of(item.def_id).params.is_empty()) + .map(|item| { + let ident = item.ident(tcx); + ObjectSafetyViolation::GAT(ident.name, ident.span) + }), + ); + } debug!( "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}", diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 9c871eea1cdda..18a3775954317 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -11,8 +11,8 @@ use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; +use rustc_middle::ty::{self, GenericParamDefKind, Ty}; use rustc_middle::ty::{ToPolyTraitRef, ToPredicate}; use rustc_span::def_id::DefId; @@ -487,18 +487,80 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .collect(); for assoc_type in assoc_types { - if !tcx.generics_of(assoc_type).params.is_empty() { + let defs: &ty::Generics = tcx.generics_of(assoc_type); + + if !defs.params.is_empty() && !tcx.features().generic_associated_types_extended { tcx.sess.delay_span_bug( obligation.cause.span, "GATs in trait object shouldn't have been considered", ); return Err(SelectionError::Unimplemented); } + // This maybe belongs in wf, but that can't (doesn't) handle // higher-ranked things. // Prevent, e.g., `dyn Iterator`. for bound in self.tcx().item_bounds(assoc_type) { - let subst_bound = bound.subst(tcx, trait_predicate.trait_ref.substs); + let subst_bound = + if defs.count() == 0 { + bound.subst(tcx, trait_predicate.trait_ref.substs) + } else { + let mut substs = smallvec::SmallVec::with_capacity(defs.count()); + substs.extend(trait_predicate.trait_ref.substs.iter()); + let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> = + smallvec::SmallVec::with_capacity( + bound.kind().bound_vars().len() + defs.count(), + ); + bound_vars.extend(bound.kind().bound_vars().into_iter()); + InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param + .kind + { + GenericParamDefKind::Type { .. } => { + let kind = ty::BoundTyKind::Param(param.name); + let bound_var = ty::BoundVariableKind::Ty(kind); + bound_vars.push(bound_var); + tcx.mk_ty(ty::Bound( + ty::INNERMOST, + ty::BoundTy { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind, + }, + )) + .into() + } + GenericParamDefKind::Lifetime => { + let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name); + let bound_var = ty::BoundVariableKind::Region(kind); + bound_vars.push(bound_var); + tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind, + }, + )) + .into() + } + GenericParamDefKind::Const { .. } => { + let bound_var = ty::BoundVariableKind::Const; + bound_vars.push(bound_var); + tcx.mk_const(ty::ConstS { + ty: tcx.type_of(param.def_id), + val: ty::ConstKind::Bound( + ty::INNERMOST, + ty::BoundVar::from_usize(bound_vars.len() - 1), + ), + }) + .into() + } + }); + let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); + let assoc_ty_substs = tcx.intern_substs(&substs); + + let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter()); + let bound = bound.kind().skip_binder().subst(tcx, assoc_ty_substs); + tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars)) + }; let normalized_bound = normalize_with_depth_to( self, obligation.param_env, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index 6c55f8212940e..55a5eb966c222 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -14,7 +14,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index e7cfa3a7c1493..62ca728868b45 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -68,9 +68,9 @@ impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> { } } -/// Helper type of a temporary returned by `Inherited::build(...)`. -/// Necessary because we can't write the following bound: -/// `F: for<'b, 'tcx> where 'tcx FnOnce(Inherited<'b, 'tcx>)`. +/// A temporary returned by `Inherited::build(...)`. This is necessary +/// for multiple `InferCtxt` to share the same `in_progress_typeck_results` +/// without using `Rc` or something similar. pub struct InheritedBuilder<'tcx> { infcx: infer::InferCtxtBuilder<'tcx>, def_id: LocalDefId, diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index e3782fe5911df..6edcc12bcf5a6 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -15,8 +15,8 @@ use rustc_hir::def::Namespace; use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; +use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::middle::stability; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 0639d6eed62a5..db6898c1308a2 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -56,7 +56,7 @@ impl Layout { /// must not overflow (i.e., the rounded value must be less than /// or equal to `usize::MAX`). #[stable(feature = "alloc_layout", since = "1.28.0")] - #[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")] + #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")] #[inline] pub const fn from_size_align(size: usize, align: usize) -> Result { if !align.is_power_of_two() { @@ -93,7 +93,7 @@ impl Layout { /// This function is unsafe as it does not verify the preconditions from /// [`Layout::from_size_align`]. #[stable(feature = "alloc_layout", since = "1.28.0")] - #[rustc_const_stable(feature = "alloc_layout", since = "1.36.0")] + #[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")] #[must_use] #[inline] pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { @@ -103,7 +103,7 @@ impl Layout { /// The minimum size in bytes for a memory block of this layout. #[stable(feature = "alloc_layout", since = "1.28.0")] - #[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")] + #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")] #[must_use] #[inline] pub const fn size(&self) -> usize { @@ -112,7 +112,7 @@ impl Layout { /// The minimum byte alignment for a memory block of this layout. #[stable(feature = "alloc_layout", since = "1.28.0")] - #[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")] + #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")] #[must_use = "this returns the minimum alignment, \ without modifying the layout"] #[inline] diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 7deb3358c95d5..3195205b1b677 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1092,7 +1092,7 @@ impl char { /// ``` #[must_use] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.32.0")] + #[rustc_const_stable(feature = "const_char_is_ascii", since = "1.32.0")] #[inline] pub const fn is_ascii(&self) -> bool { *self as u32 <= 0x7F diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 8ad4317c145ac..474a632773fb8 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1638,7 +1638,7 @@ extern "rust-intrinsic" { /// let num_trailing = unsafe { cttz_nonzero(x) }; /// assert_eq!(num_trailing, 3); /// ``` - #[rustc_const_stable(feature = "const_cttz", since = "1.53.0")] + #[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")] pub fn cttz_nonzero(x: T) -> T; /// Reverses the bytes in an integer type `T`. @@ -1718,7 +1718,7 @@ extern "rust-intrinsic" { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_div` method. For example, /// [`u32::checked_div`] - #[rustc_const_stable(feature = "const_int_unchecked_arith", since = "1.52.0")] + #[rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0")] pub fn unchecked_div(x: T, y: T) -> T; /// Returns the remainder of an unchecked division, resulting in /// undefined behavior when `y == 0` or `x == T::MIN && y == -1` @@ -1726,7 +1726,7 @@ extern "rust-intrinsic" { /// Safe wrappers for this intrinsic are available on the integer /// primitives via the `checked_rem` method. For example, /// [`u32::checked_rem`] - #[rustc_const_stable(feature = "const_int_unchecked_arith", since = "1.52.0")] + #[rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0")] pub fn unchecked_rem(x: T, y: T) -> T; /// Performs an unchecked left shift, resulting in undefined behavior when diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 445a7ba6e2d66..7dfcc36ce9391 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -97,7 +97,6 @@ // Library features: #![feature(const_align_offset)] #![feature(const_align_of_val)] -#![feature(const_alloc_layout)] #![feature(const_arguments_as_str)] #![feature(const_array_into_iter_constructors)] #![feature(const_bigint_helper_methods)] diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 9db5a9a288940..58d682fc4c8d4 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -622,7 +622,7 @@ impl MaybeUninit { /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️ /// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.59.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init_by_value", since = "1.59.0")] #[inline(always)] #[rustc_diagnostic_item = "assume_init"] #[track_caller] @@ -788,7 +788,7 @@ impl MaybeUninit { /// } /// ``` #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] - #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.59.0")] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init_ref", since = "1.59.0")] #[inline(always)] pub const unsafe fn assume_init_ref(&self) -> &T { // SAFETY: the caller must guarantee that `self` is initialized. diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 8a99bed6a96ab..005f8749e01e6 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -299,7 +299,7 @@ pub fn forget_unsized(t: T) { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] -#[rustc_const_stable(feature = "const_size_of", since = "1.24.0")] +#[rustc_const_stable(feature = "const_mem_size_of", since = "1.24.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of")] pub const fn size_of() -> usize { intrinsics::size_of::() @@ -581,7 +581,7 @@ pub const unsafe fn align_of_val_raw(val: *const T) -> usize { #[inline] #[must_use] #[stable(feature = "needs_drop", since = "1.21.0")] -#[rustc_const_stable(feature = "const_needs_drop", since = "1.36.0")] +#[rustc_const_stable(feature = "const_mem_needs_drop", since = "1.36.0")] #[rustc_diagnostic_item = "needs_drop"] pub const fn needs_drop() -> bool { intrinsics::needs_drop::() diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 3665573ab0ff2..ec460286d0378 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -270,7 +270,7 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")] /// ``` #[stable(feature = "reverse_bits", since = "1.37.0")] - #[rustc_const_stable(feature = "const_int_methods", since = "1.37.0")] + #[rustc_const_stable(feature = "reverse_bits", since = "1.37.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -603,7 +603,7 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);")] /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.52.0")] + #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -656,7 +656,7 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);")] /// ``` #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.52.0")] + #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index f4f1d274d105b..8cbece0417b07 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -281,7 +281,7 @@ impl u8 { /// ``` #[must_use] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] - #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.43.0")] + #[rustc_const_stable(feature = "const_u8_is_ascii", since = "1.43.0")] #[inline] pub const fn is_ascii(&self) -> bool { *self & 128 == 0 diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index c36529314784e..0ffbde33a0d1e 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -74,7 +74,7 @@ macro_rules! nonzero_integers { /// Returns the value as a primitive type. #[$stability] #[inline] - #[rustc_const_stable(feature = "nonzero", since = "1.34.0")] + #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] pub const fn get(self) -> $Int { self.0 } diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 4751faeb93678..514ac69f7e049 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -273,7 +273,7 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")] /// ``` #[stable(feature = "reverse_bits", since = "1.37.0")] - #[rustc_const_stable(feature = "const_math", since = "1.37.0")] + #[rustc_const_stable(feature = "reverse_bits", since = "1.37.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -591,7 +591,7 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);")] /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.52.0")] + #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -642,7 +642,7 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);")] /// ``` #[stable(feature = "wrapping", since = "1.7.0")] - #[rustc_const_stable(feature = "const_checked_int_methods", since = "1.52.0")] + #[rustc_const_stable(feature = "const_checked_int_div", since = "1.52.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index acab8de8c70f5..b5ca9e35dced1 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -549,7 +549,7 @@ impl Option { #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"] #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_option", since = "1.48.0")] + #[rustc_const_stable(feature = "const_option_basics", since = "1.48.0")] pub const fn is_some(&self) -> bool { matches!(*self, Some(_)) } @@ -592,7 +592,7 @@ impl Option { `.and_then(|_| panic!(\"`Option` had a value when expected `None`\"))` instead"] #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_option", since = "1.48.0")] + #[rustc_const_stable(feature = "const_option_basics", since = "1.48.0")] pub const fn is_none(&self) -> bool { !self.is_some() } @@ -621,7 +621,7 @@ impl Option { /// println!("still can print text: {text:?}"); /// ``` #[inline] - #[rustc_const_stable(feature = "const_option", since = "1.48.0")] + #[rustc_const_stable(feature = "const_option_basics", since = "1.48.0")] #[stable(feature = "rust1", since = "1.0.0")] pub const fn as_ref(&self) -> Option<&T> { match *self { diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 68d80022b4c80..e2a19c1b5818e 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -510,7 +510,7 @@ pub const fn null_mut() -> *mut T { /// see the [module documentation][crate::ptr] for details. #[inline(always)] #[must_use] -#[rustc_const_stable(feature = "strict_provenance", since = "1.61.0")] +#[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")] #[unstable(feature = "strict_provenance", issue = "95228")] pub const fn invalid(addr: usize) -> *const T { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. @@ -537,7 +537,7 @@ pub const fn invalid(addr: usize) -> *const T { /// see the [module documentation][crate::ptr] for details. #[inline(always)] #[must_use] -#[rustc_const_stable(feature = "strict_provenance", since = "1.61.0")] +#[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")] #[unstable(feature = "strict_provenance", issue = "95228")] pub const fn invalid_mut(addr: usize) -> *mut T { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index c1b19895f006c..7516d4bba4cdf 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -4,6 +4,7 @@ use crate::fmt; use crate::hash; use crate::marker::Unsize; use crate::mem::{self, MaybeUninit}; +use crate::num::NonZeroUsize; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::ptr::Unique; use crate::slice::{self, SliceIndex}; @@ -253,6 +254,53 @@ impl NonNull { (self.cast(), super::metadata(self.as_ptr())) } + /// Gets the "address" portion of the pointer. + /// + /// This API and its claimed semantics are part of the Strict Provenance experiment, + /// see the [module documentation][crate::ptr] for details. + #[must_use] + #[inline] + #[unstable(feature = "strict_provenance", issue = "95228")] + pub fn addr(self) -> NonZeroUsize + where + T: Sized, + { + // SAFETY: The pointer is guaranteed by the type to be non-null, + // meaning that the address will be non-zero. + unsafe { NonZeroUsize::new_unchecked(self.pointer.addr()) } + } + + /// Creates a new pointer with the given address. + /// + /// This API and its claimed semantics are part of the Strict Provenance experiment, + /// see the [module documentation][crate::ptr] for details. + #[must_use] + #[inline] + #[unstable(feature = "strict_provenance", issue = "95228")] + pub fn with_addr(self, addr: NonZeroUsize) -> Self + where + T: Sized, + { + // SAFETY: The result of `ptr::from::with_addr` is non-null because `addr` is guaranteed to be non-zero. + unsafe { NonNull::new_unchecked(self.pointer.with_addr(addr.get()) as *mut _) } + } + + /// Creates a new pointer by mapping `self`'s address to a new one. + /// + /// This is a convenience for [`with_addr`][Self::with_addr], see that method for details. + /// + /// This API and its claimed semantics are part of the Strict Provenance experiment, + /// see the [module documentation][crate::ptr] for details. + #[must_use] + #[inline] + #[unstable(feature = "strict_provenance", issue = "95228")] + pub fn map_addr(self, f: impl FnOnce(NonZeroUsize) -> NonZeroUsize) -> Self + where + T: Sized, + { + self.with_addr(f(self.addr())) + } + /// Acquires the underlying `*mut` pointer. /// /// # Examples diff --git a/library/core/src/result.rs b/library/core/src/result.rs index afd0c8572291d..641749be36637 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -536,7 +536,7 @@ impl Result { /// assert_eq!(x.is_ok(), false); /// ``` #[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"] - #[rustc_const_stable(feature = "const_result", since = "1.48.0")] + #[rustc_const_stable(feature = "const_result_basics", since = "1.48.0")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub const fn is_ok(&self) -> bool { @@ -580,7 +580,7 @@ impl Result { /// assert_eq!(x.is_err(), true); /// ``` #[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"] - #[rustc_const_stable(feature = "const_result", since = "1.48.0")] + #[rustc_const_stable(feature = "const_result_basics", since = "1.48.0")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub const fn is_err(&self) -> bool { @@ -698,7 +698,7 @@ impl Result { /// assert_eq!(x.as_ref(), Err(&"Error")); /// ``` #[inline] - #[rustc_const_stable(feature = "const_result", since = "1.48.0")] + #[rustc_const_stable(feature = "const_result_basics", since = "1.48.0")] #[stable(feature = "rust1", since = "1.0.0")] pub const fn as_ref(&self) -> Result<&T, &E> { match *self { diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index c11a35ab947a8..6285d1c1cbb56 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2498,7 +2498,7 @@ macro_rules! atomic_int_ptr_sized { stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), stable(feature = "atomic_nand", since = "1.27.0"), - rustc_const_stable(feature = "const_integer_atomics", since = "1.24.0"), + rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"), stable(feature = "rust1", since = "1.0.0"), "isize", "", @@ -2518,7 +2518,7 @@ macro_rules! atomic_int_ptr_sized { stable(feature = "atomic_access", since = "1.15.0"), stable(feature = "atomic_from", since = "1.23.0"), stable(feature = "atomic_nand", since = "1.27.0"), - rustc_const_stable(feature = "const_integer_atomics", since = "1.24.0"), + rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"), stable(feature = "rust1", since = "1.0.0"), "usize", "", diff --git a/library/core/src/time.rs b/library/core/src/time.rs index bd72d82b71c00..6c97305b1a849 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -333,7 +333,7 @@ impl Duration { /// /// [`subsec_nanos`]: Duration::subsec_nanos #[stable(feature = "duration", since = "1.3.0")] - #[rustc_const_stable(feature = "duration", since = "1.32.0")] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] #[must_use] #[inline] pub const fn as_secs(&self) -> u64 { @@ -356,7 +356,7 @@ impl Duration { /// assert_eq!(duration.subsec_millis(), 432); /// ``` #[stable(feature = "duration_extras", since = "1.27.0")] - #[rustc_const_stable(feature = "duration_extras", since = "1.32.0")] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] #[must_use] #[inline] pub const fn subsec_millis(&self) -> u32 { @@ -379,7 +379,7 @@ impl Duration { /// assert_eq!(duration.subsec_micros(), 234_567); /// ``` #[stable(feature = "duration_extras", since = "1.27.0")] - #[rustc_const_stable(feature = "duration_extras", since = "1.32.0")] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] #[must_use] #[inline] pub const fn subsec_micros(&self) -> u32 { @@ -402,7 +402,7 @@ impl Duration { /// assert_eq!(duration.subsec_nanos(), 10_000_000); /// ``` #[stable(feature = "duration", since = "1.3.0")] - #[rustc_const_stable(feature = "duration", since = "1.32.0")] + #[rustc_const_stable(feature = "duration_consts", since = "1.32.0")] #[must_use] #[inline] pub const fn subsec_nanos(&self) -> u32 { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 5f90a76ab74ee..3af277a556b4f 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -13,7 +13,6 @@ #![feature(const_convert)] #![feature(const_heap)] #![feature(const_maybe_uninit_as_mut_ptr)] -#![feature(const_maybe_uninit_assume_init)] #![feature(const_maybe_uninit_assume_init_read)] #![feature(const_nonnull_new)] #![feature(const_num_from_num)] @@ -87,6 +86,7 @@ #![feature(int_roundings)] #![feature(slice_group_by)] #![feature(split_array)] +#![feature(strict_provenance)] #![feature(trusted_random_access)] #![feature(unsize)] #![feature(unzip_option)] diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 6a39ab79f4965..03fe56022b069 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -1,4 +1,5 @@ use core::cell::RefCell; +use core::num::NonZeroUsize; use core::ptr; use core::ptr::*; use std::fmt::{Debug, Display}; @@ -691,3 +692,80 @@ fn thin_box() { } } } + +#[test] +fn nonnull_tagged_pointer_with_provenance() { + let raw_pointer = Box::into_raw(Box::new(10)); + + let mut p = TaggedPointer::new(raw_pointer).unwrap(); + assert_eq!(p.tag(), 0); + + p.set_tag(1); + assert_eq!(p.tag(), 1); + assert_eq!(unsafe { *p.pointer().as_ptr() }, 10); + + p.set_tag(3); + assert_eq!(p.tag(), 3); + assert_eq!(unsafe { *p.pointer().as_ptr() }, 10); + + unsafe { Box::from_raw(p.pointer().as_ptr()) }; + + /// A non-null pointer type which carries several bits of metadata and maintains provenance. + #[repr(transparent)] + pub struct TaggedPointer(NonNull); + + impl Clone for TaggedPointer { + fn clone(&self) -> Self { + Self(self.0) + } + } + + impl Copy for TaggedPointer {} + + impl TaggedPointer { + /// The ABI-required minimum alignment of the `P` type. + pub const ALIGNMENT: usize = core::mem::align_of::(); + /// A mask for data-carrying bits of the address. + pub const DATA_MASK: usize = !Self::ADDRESS_MASK; + /// Number of available bits of storage in the address. + pub const NUM_BITS: u32 = Self::ALIGNMENT.trailing_zeros(); + /// A mask for the non-data-carrying bits of the address. + pub const ADDRESS_MASK: usize = usize::MAX << Self::NUM_BITS; + + /// Create a new tagged pointer from a possibly null pointer. + pub fn new(pointer: *mut T) -> Option> { + Some(TaggedPointer(NonNull::new(pointer)?)) + } + + /// Consume this tagged pointer and produce a raw mutable pointer to the + /// memory location. + pub fn pointer(self) -> NonNull { + // SAFETY: The `addr` guaranteed to have bits set in the Self::ADDRESS_MASK, so the result will be non-null. + self.0.map_addr(|addr| unsafe { + NonZeroUsize::new_unchecked(addr.get() & Self::ADDRESS_MASK) + }) + } + + /// Consume this tagged pointer and produce the data it carries. + pub fn tag(&self) -> usize { + self.0.addr().get() & Self::DATA_MASK + } + + /// Update the data this tagged pointer carries to a new value. + pub fn set_tag(&mut self, data: usize) { + assert_eq!( + data & Self::ADDRESS_MASK, + 0, + "cannot set more data beyond the lowest NUM_BITS" + ); + let data = data & Self::DATA_MASK; + + // SAFETY: This value will always be non-zero because the upper bits (from + // ADDRESS_MASK) will always be non-zero. This a property of the type and its + // construction. + self.0 = self.0.map_addr(|addr| unsafe { + NonZeroUsize::new_unchecked((addr.get() & Self::ADDRESS_MASK) | data) + }) + } + } +} diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 70a7d7a8cabc1..036f291997607 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -235,7 +235,7 @@ impl IpAddr { /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true); /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true); /// ``` - #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(feature = "ip_shared", since = "1.12.0")] #[must_use] #[inline] @@ -259,7 +259,7 @@ impl IpAddr { /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true); /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true); /// ``` - #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(feature = "ip_shared", since = "1.12.0")] #[must_use] #[inline] @@ -309,7 +309,7 @@ impl IpAddr { /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true); /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true); /// ``` - #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(feature = "ip_shared", since = "1.12.0")] #[must_use] #[inline] @@ -387,7 +387,7 @@ impl IpAddr { /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true); /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false); /// ``` - #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(feature = "ipaddr_checker", since = "1.16.0")] #[must_use] #[inline] @@ -408,7 +408,7 @@ impl IpAddr { /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false); /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true); /// ``` - #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(feature = "ipaddr_checker", since = "1.16.0")] #[must_use] #[inline] @@ -454,7 +454,7 @@ impl Ipv4Addr { /// /// let addr = Ipv4Addr::new(127, 0, 0, 1); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")] + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] #[inline] @@ -516,7 +516,7 @@ impl Ipv4Addr { /// let addr = Ipv4Addr::new(127, 0, 0, 1); /// assert_eq!(addr.octets(), [127, 0, 0, 1]); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] #[inline] @@ -540,7 +540,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true); /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")] + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] #[stable(feature = "ip_shared", since = "1.12.0")] #[must_use] #[inline] @@ -562,7 +562,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true); /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] #[must_use] #[inline] @@ -593,7 +593,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true); /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] #[must_use] #[inline] @@ -621,7 +621,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true); /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] #[must_use] #[inline] @@ -823,7 +823,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true); /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] #[must_use] #[inline] @@ -845,7 +845,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true); /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] #[must_use] #[inline] @@ -873,7 +873,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true); /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] #[must_use] #[inline] @@ -901,7 +901,7 @@ impl Ipv4Addr { /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff) /// ); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -928,7 +928,7 @@ impl Ipv4Addr { /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(), /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff)); /// ``` - #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -1216,7 +1216,7 @@ impl Ipv6Addr { /// /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); /// ``` - #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")] + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] #[inline] @@ -1278,7 +1278,7 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(), /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]); /// ``` - #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] #[inline] @@ -1315,7 +1315,7 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true); /// ``` - #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] #[must_use] #[inline] @@ -1339,7 +1339,7 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true); /// ``` - #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] #[must_use] #[inline] @@ -1624,7 +1624,7 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true); /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false); /// ``` - #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] #[must_use] #[inline] @@ -1693,7 +1693,7 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(), /// Some(Ipv4Addr::new(0, 0, 0, 1))); /// ``` - #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] + #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")] #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -1740,7 +1740,7 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(), /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); /// ``` - #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")] + #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")] #[stable(feature = "ipv6_to_octets", since = "1.12.0")] #[must_use] #[inline] diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index ca29261b1c98d..587e453ceef91 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -193,7 +193,7 @@ macro_rules! __thread_local_inner { #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] { static mut VAL: $t = INIT_EXPR; - Some(&VAL) + $crate::option::Option::Some(&VAL) } // If the platform has support for `#[thread_local]`, use it. @@ -209,7 +209,7 @@ macro_rules! __thread_local_inner { // just get going. if !$crate::mem::needs_drop::<$t>() { unsafe { - return Some(&VAL) + return $crate::option::Option::Some(&VAL) } } @@ -223,7 +223,7 @@ macro_rules! __thread_local_inner { let ptr = ptr as *mut $t; unsafe { - debug_assert_eq!(STATE, 1); + $crate::debug_assert_eq!(STATE, 1); STATE = 2; $crate::ptr::drop_in_place(ptr); } @@ -239,14 +239,14 @@ macro_rules! __thread_local_inner { destroy, ); STATE = 1; - Some(&VAL) + $crate::option::Option::Some(&VAL) } // 1 == the destructor is registered and the value // is valid, so return the pointer. - 1 => Some(&VAL), + 1 => $crate::option::Option::Some(&VAL), // otherwise the destructor has already run, so we // can't give access. - _ => None, + _ => $crate::option::Option::None, } } } @@ -269,7 +269,7 @@ macro_rules! __thread_local_inner { if let $crate::option::Option::Some(value) = init.take() { return value; } else if $crate::cfg!(debug_assertions) { - unreachable!("missing initial value"); + $crate::unreachable!("missing initial value"); } } __init() @@ -344,7 +344,7 @@ macro_rules! __thread_local_inner { if let $crate::option::Option::Some(value) = init.take() { return value; } else if $crate::cfg!(debug_assertions) { - unreachable!("missing default value"); + $crate::unreachable!("missing default value"); } } __init() diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs index e3f5d07478304..8455dd9ef95f4 100644 --- a/src/test/rustdoc/const-display.rs +++ b/src/test/rustdoc/const-display.rs @@ -64,7 +64,7 @@ impl Foo { // @has 'foo/struct.Foo.html' '//*[@id="method.stable_impl"]/h4[@class="code-header"]' 'pub const fn stable_impl() -> u32' // @has - '//span[@class="since"]' '1.0.0 (const: 1.2.0)' #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "rust1", since = "1.2.0")] + #[rustc_const_stable(feature = "const2", since = "1.2.0")] pub const fn stable_impl() -> u32 { 42 } } @@ -75,12 +75,12 @@ impl Bar { // Do not show non-const stabilities that are the same as the enclosing item. // @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.2.0$' #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "rust1", since = "1.2.0")] + #[rustc_const_stable(feature = "const2", since = "1.2.0")] pub const fn stable_impl() -> u32 { 42 } // Show const-stability even for unstable functions. // @matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.3.0$' #[unstable(feature = "foo2", issue = "none")] - #[rustc_const_stable(feature = "rust1", since = "1.3.0")] + #[rustc_const_stable(feature = "const3", since = "1.3.0")] pub const fn const_stable_unstable() -> u32 { 42 } } diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr index 5520f815f3e54..35dc9cca33b5a 100644 --- a/src/test/ui/asm/naked-functions.stderr +++ b/src/test/ui/asm/naked-functions.stderr @@ -97,6 +97,11 @@ LL | | LL | | sym G, LL | | ); | |_____^ + | +help: consider specifying that the asm block is responsible for returning from the function + | +LL | sym G, options(noreturn), + | +++++++++++++++++++ error[E0787]: naked functions must contain a single asm block --> $DIR/naked-functions.rs:53:1 @@ -131,18 +136,33 @@ error[E0787]: asm in naked functions must use `noreturn` option | LL | asm!(""); | ^^^^^^^^ + | +help: consider specifying that the asm block is responsible for returning from the function + | +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: asm in naked functions must use `noreturn` option --> $DIR/naked-functions.rs:85:5 | LL | asm!(""); | ^^^^^^^^ + | +help: consider specifying that the asm block is responsible for returning from the function + | +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: asm in naked functions must use `noreturn` option --> $DIR/naked-functions.rs:87:5 | LL | asm!(""); | ^^^^^^^^ + | +help: consider specifying that the asm block is responsible for returning from the function + | +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: naked functions must contain a single asm block --> $DIR/naked-functions.rs:81:1 @@ -198,6 +218,11 @@ error[E0787]: asm in naked functions must use `noreturn` option | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider specifying that the asm block is responsible for returning from the function + | +LL | asm!("", options(noreturn), options(readonly, nostack), options(pure)); + | +++++++++++++++++++ error[E0787]: asm options unsupported in naked functions: `may_unwind` --> $DIR/naked-functions.rs:118:5 diff --git a/src/test/ui/consts/assert-type-intrinsics.rs b/src/test/ui/consts/assert-type-intrinsics.rs index 31ff6aed03b2f..38e5c454edf75 100644 --- a/src/test/ui/consts/assert-type-intrinsics.rs +++ b/src/test/ui/consts/assert-type-intrinsics.rs @@ -1,7 +1,7 @@ // error-pattern: any use of this value will cause an error #![feature(never_type)] -#![feature(const_maybe_uninit_assume_init, const_assert_type2)] +#![feature(const_assert_type2)] #![feature(core_intrinsics)] use std::intrinsics; diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.rs b/src/test/ui/consts/const-eval/simd/insert_extract.rs index a1d6c5e51b498..3472c05d12fa8 100644 --- a/src/test/ui/consts/const-eval/simd/insert_extract.rs +++ b/src/test/ui/consts/const-eval/simd/insert_extract.rs @@ -2,7 +2,7 @@ #![feature(repr_simd)] #![feature(platform_intrinsics)] #![feature(staged_api)] -#![stable(feature = "foo", since = "1.33.7")] +#![stable(feature = "foo", since = "1.3.37")] #![allow(non_camel_case_types)] #[repr(simd)] struct i8x1(i8); diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.base.stderr similarity index 91% rename from src/test/ui/generic-associated-types/gat-in-trait-path.stderr rename to src/test/ui/generic-associated-types/gat-in-trait-path.base.stderr index a55642490f975..c2054f64e2d6b 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.base.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/gat-in-trait-path.rs:21:17 + --> $DIR/gat-in-trait-path.rs:27:17 | LL | fn f(_arg : Box Foo = &'a ()>>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/gat-in-trait-path.rs:5:10 + --> $DIR/gat-in-trait-path.rs:11:10 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.rs b/src/test/ui/generic-associated-types/gat-in-trait-path.rs index 7bbcf950ae183..c82450ccff149 100644 --- a/src/test/ui/generic-associated-types/gat-in-trait-path.rs +++ b/src/test/ui/generic-associated-types/gat-in-trait-path.rs @@ -1,5 +1,11 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + #![feature(generic_associated_types)] #![feature(associated_type_defaults)] +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] trait Foo { type A<'a> where Self: 'a; @@ -19,7 +25,7 @@ impl Foo for Fooer { } fn f(_arg : Box Foo = &'a ()>>) {} -//~^ the trait `Foo` cannot be made into an object +//[base]~^ the trait `Foo` cannot be made into an object fn main() { diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.base.stderr similarity index 90% rename from src/test/ui/generic-associated-types/issue-67510-pass.stderr rename to src/test/ui/generic-associated-types/issue-67510-pass.base.stderr index 7dd1bdf891eb5..74a616aaabe3a 100644 --- a/src/test/ui/generic-associated-types/issue-67510-pass.stderr +++ b/src/test/ui/generic-associated-types/issue-67510-pass.base.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `X` cannot be made into an object - --> $DIR/issue-67510-pass.rs:7:23 + --> $DIR/issue-67510-pass.rs:13:23 | LL | fn _func1<'a>(_x: Box=&'a ()>>) {} | ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-67510-pass.rs:4:10 + --> $DIR/issue-67510-pass.rs:10:10 | LL | trait X { | - this trait cannot be made into an object... diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.rs b/src/test/ui/generic-associated-types/issue-67510-pass.rs index 99f0e84fa6df4..c5b02ff9a6400 100644 --- a/src/test/ui/generic-associated-types/issue-67510-pass.rs +++ b/src/test/ui/generic-associated-types/issue-67510-pass.rs @@ -1,10 +1,16 @@ +// revisions: base extended +//[base] check-fail +//[extended] check-pass + #![feature(generic_associated_types)] +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] trait X { type Y<'a>; } fn _func1<'a>(_x: Box=&'a ()>>) {} -//~^ ERROR the trait `X` cannot be made into an object +//[base]~^ ERROR the trait `X` cannot be made into an object fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.base.stderr similarity index 93% rename from src/test/ui/generic-associated-types/issue-76535.stderr rename to src/test/ui/generic-associated-types/issue-76535.base.stderr index 64eeec1b2fcbe..5decd58bbcd0b 100644 --- a/src/test/ui/generic-associated-types/issue-76535.stderr +++ b/src/test/ui/generic-associated-types/issue-76535.base.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for associated type `SuperTrait::SubType` - --> $DIR/issue-76535.rs:36:33 + --> $DIR/issue-76535.rs:40:33 | LL | let sub: Box> = Box::new(SuperStruct::new(0)); | ^^^^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-76535.rs:6:10 + --> $DIR/issue-76535.rs:10:10 | LL | type SubType<'a>: SubTrait where Self: 'a; | ^^^^^^^ -- @@ -15,13 +15,13 @@ LL | let sub: Box = SubStruct>> = Box::new(SuperS | ~~~~~~~~~~~ error[E0038]: the trait `SuperTrait` cannot be made into an object - --> $DIR/issue-76535.rs:36:14 + --> $DIR/issue-76535.rs:40:14 | LL | let sub: Box> = Box::new(SuperStruct::new(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-76535.rs:6:10 + --> $DIR/issue-76535.rs:10:10 | LL | pub trait SuperTrait { | ---------- this trait cannot be made into an object... @@ -30,13 +30,13 @@ LL | type SubType<'a>: SubTrait where Self: 'a; = help: consider moving `SubType` to another trait error[E0038]: the trait `SuperTrait` cannot be made into an object - --> $DIR/issue-76535.rs:36:57 + --> $DIR/issue-76535.rs:40:57 | LL | let sub: Box> = Box::new(SuperStruct::new(0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-76535.rs:6:10 + --> $DIR/issue-76535.rs:10:10 | LL | pub trait SuperTrait { | ---------- this trait cannot be made into an object... diff --git a/src/test/ui/generic-associated-types/issue-76535.extended.stderr b/src/test/ui/generic-associated-types/issue-76535.extended.stderr new file mode 100644 index 0000000000000..067d0489b486b --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-76535.extended.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `SuperTrait::SubType` + --> $DIR/issue-76535.rs:40:33 + | +LL | let sub: Box> = Box::new(SuperStruct::new(0)); + | ^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-76535.rs:10:10 + | +LL | type SubType<'a>: SubTrait where Self: 'a; + | ^^^^^^^ -- +help: add missing lifetime argument + | +LL | let sub: Box = SubStruct>> = Box::new(SuperStruct::new(0)); + | ~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/issue-76535.rs b/src/test/ui/generic-associated-types/issue-76535.rs index 20c6924afa614..46f217ba06bc8 100644 --- a/src/test/ui/generic-associated-types/issue-76535.rs +++ b/src/test/ui/generic-associated-types/issue-76535.rs @@ -1,4 +1,8 @@ +// revisions: base extended + #![feature(generic_associated_types)] +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] pub trait SubTrait {} @@ -35,6 +39,6 @@ impl SuperTrait for SuperStruct { fn main() { let sub: Box> = Box::new(SuperStruct::new(0)); //~^ ERROR missing generics for associated type - //~^^ ERROR the trait - //~| ERROR the trait + //[base]~^^ ERROR the trait + //[base]~| ERROR the trait } diff --git a/src/test/ui/generic-associated-types/issue-78671.stderr b/src/test/ui/generic-associated-types/issue-78671.base.stderr similarity index 91% rename from src/test/ui/generic-associated-types/issue-78671.stderr rename to src/test/ui/generic-associated-types/issue-78671.base.stderr index 17dd0ff4a0c94..6bcd004b1a92e 100644 --- a/src/test/ui/generic-associated-types/issue-78671.stderr +++ b/src/test/ui/generic-associated-types/issue-78671.base.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for associated type `CollectionFamily::Member` - --> $DIR/issue-78671.rs:7:47 + --> $DIR/issue-78671.rs:11:47 | LL | Box::new(Family) as &dyn CollectionFamily | ^^^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-78671.rs:4:10 + --> $DIR/issue-78671.rs:8:10 | LL | type Member; | ^^^^^^ - @@ -15,13 +15,13 @@ LL | Box::new(Family) as &dyn CollectionFamily=usize> | ~~~~~~~~~ error[E0038]: the trait `CollectionFamily` cannot be made into an object - --> $DIR/issue-78671.rs:7:25 + --> $DIR/issue-78671.rs:11:25 | LL | Box::new(Family) as &dyn CollectionFamily | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-78671.rs:4:10 + --> $DIR/issue-78671.rs:8:10 | LL | trait CollectionFamily { | ---------------- this trait cannot be made into an object... diff --git a/src/test/ui/generic-associated-types/issue-78671.extended.stderr b/src/test/ui/generic-associated-types/issue-78671.extended.stderr new file mode 100644 index 0000000000000..f1b48933516f6 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-78671.extended.stderr @@ -0,0 +1,19 @@ +error[E0107]: missing generics for associated type `CollectionFamily::Member` + --> $DIR/issue-78671.rs:11:47 + | +LL | Box::new(Family) as &dyn CollectionFamily + | ^^^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-78671.rs:8:10 + | +LL | type Member; + | ^^^^^^ - +help: add missing generic argument + | +LL | Box::new(Family) as &dyn CollectionFamily=usize> + | ~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/issue-78671.rs b/src/test/ui/generic-associated-types/issue-78671.rs index 7ccf376e5cb63..c09dac28bda6c 100644 --- a/src/test/ui/generic-associated-types/issue-78671.rs +++ b/src/test/ui/generic-associated-types/issue-78671.rs @@ -1,4 +1,8 @@ +// revisions: base extended + #![feature(generic_associated_types)] +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] trait CollectionFamily { type Member; @@ -6,7 +10,7 @@ trait CollectionFamily { fn floatify() { Box::new(Family) as &dyn CollectionFamily //~^ ERROR: missing generics for associated type - //~| ERROR: the trait `CollectionFamily` cannot be made into an object + //[base]~^^ ERROR: the trait `CollectionFamily` cannot be made into an object } struct Family; diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.base.stderr similarity index 93% rename from src/test/ui/generic-associated-types/issue-79422.stderr rename to src/test/ui/generic-associated-types/issue-79422.base.stderr index 8b6f9b866e5ef..404c975d64a21 100644 --- a/src/test/ui/generic-associated-types/issue-79422.stderr +++ b/src/test/ui/generic-associated-types/issue-79422.base.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for associated type `MapLike::VRefCont` - --> $DIR/issue-79422.rs:42:36 + --> $DIR/issue-79422.rs:48:36 | LL | as Box>>; | ^^^^^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-79422.rs:20:10 + --> $DIR/issue-79422.rs:24:10 | LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; | ^^^^^^^^ -- @@ -15,13 +15,13 @@ LL | as Box = dyn RefCont<'_, u8>>>; | ~~~~~~~~~~~~ error[E0038]: the trait `MapLike` cannot be made into an object - --> $DIR/issue-79422.rs:42:12 + --> $DIR/issue-79422.rs:48:12 | LL | as Box>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-79422.rs:20:10 + --> $DIR/issue-79422.rs:24:10 | LL | trait MapLike { | ------- this trait cannot be made into an object... @@ -30,13 +30,13 @@ LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; = help: consider moving `VRefCont` to another trait error[E0038]: the trait `MapLike` cannot be made into an object - --> $DIR/issue-79422.rs:41:13 + --> $DIR/issue-79422.rs:45:13 | LL | let m = Box::new(std::collections::BTreeMap::::new()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-79422.rs:20:10 + --> $DIR/issue-79422.rs:24:10 | LL | trait MapLike { | ------- this trait cannot be made into an object... diff --git a/src/test/ui/generic-associated-types/issue-79422.extended.stderr b/src/test/ui/generic-associated-types/issue-79422.extended.stderr new file mode 100644 index 0000000000000..9478fc8979211 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-79422.extended.stderr @@ -0,0 +1,35 @@ +error[E0107]: missing generics for associated type `MapLike::VRefCont` + --> $DIR/issue-79422.rs:48:36 + | +LL | as Box>>; + | ^^^^^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-79422.rs:24:10 + | +LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; + | ^^^^^^^^ -- +help: add missing lifetime argument + | +LL | as Box = dyn RefCont<'_, u8>>>; + | ~~~~~~~~~~~~ + +error[E0271]: type mismatch resolving ` as MapLike>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)` + --> $DIR/issue-79422.rs:45:13 + | +LL | let m = Box::new(std::collections::BTreeMap::::new()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as MapLike>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)` + | +note: expected this to be `(dyn RefCont<'_, u8> + 'static)` + --> $DIR/issue-79422.rs:29:25 + | +LL | type VRefCont<'a> = &'a V where Self: 'a; + | ^^^^^ + = note: expected trait object `(dyn RefCont<'_, u8> + 'static)` + found reference `&u8` + = note: required for the cast to the object type `dyn MapLike + 'static)>` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0271. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/generic-associated-types/issue-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs index b9a3c583f7c89..7749975e68727 100644 --- a/src/test/ui/generic-associated-types/issue-79422.rs +++ b/src/test/ui/generic-associated-types/issue-79422.rs @@ -1,4 +1,8 @@ +// revisions: base extended + #![feature(generic_associated_types)] +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] trait RefCont<'a, T> { fn t(&'a self) -> &'a T; @@ -39,8 +43,9 @@ impl MapLike for Source { fn main() { let m = Box::new(std::collections::BTreeMap::::new()) + //[base]~^ ERROR the trait + //[extended]~^^ type mismatch as Box>>; //~^ ERROR missing generics for associated type - //~^^ ERROR the trait - //~^^^^ ERROR the trait + //[base]~^^ ERROR the trait } diff --git a/src/test/ui/generic-associated-types/trait-objects.stderr b/src/test/ui/generic-associated-types/trait-objects.base.stderr similarity index 93% rename from src/test/ui/generic-associated-types/trait-objects.stderr rename to src/test/ui/generic-associated-types/trait-objects.base.stderr index 5ab37910207ca..1df76a21bf9b4 100644 --- a/src/test/ui/generic-associated-types/trait-objects.stderr +++ b/src/test/ui/generic-associated-types/trait-objects.base.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `StreamingIterator` cannot be made into an object - --> $DIR/trait-objects.rs:10:21 + --> $DIR/trait-objects.rs:14:21 | LL | fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/trait-objects.rs:4:10 + --> $DIR/trait-objects.rs:8:10 | LL | trait StreamingIterator { | ----------------- this trait cannot be made into an object... diff --git a/src/test/ui/generic-associated-types/trait-objects.extended.stderr b/src/test/ui/generic-associated-types/trait-objects.extended.stderr new file mode 100644 index 0000000000000..7cc3dad992110 --- /dev/null +++ b/src/test/ui/generic-associated-types/trait-objects.extended.stderr @@ -0,0 +1,12 @@ +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/trait-objects.rs:16:7 + | +LL | fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { + | ------------------------------------------------------ help: add explicit lifetime `'a` to the type of `x`: `&'a mut (dyn StreamingIterator Item = &'a i32> + 'a)` +LL | +LL | x.size_hint().0 + | ^^^^^^^^^ lifetime `'a` required + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/generic-associated-types/trait-objects.rs b/src/test/ui/generic-associated-types/trait-objects.rs index 559e6758a32af..644e56ce21f10 100644 --- a/src/test/ui/generic-associated-types/trait-objects.rs +++ b/src/test/ui/generic-associated-types/trait-objects.rs @@ -1,4 +1,8 @@ +// revisions: base extended + #![feature(generic_associated_types)] +#![cfg_attr(extended, feature(generic_associated_types_extended))] +#![cfg_attr(extended, allow(incomplete_features))] trait StreamingIterator { type Item<'a> where Self: 'a; @@ -8,8 +12,9 @@ trait StreamingIterator { } fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { - //~^ the trait `StreamingIterator` cannot be made into an object + //[base]~^ the trait `StreamingIterator` cannot be made into an object x.size_hint().0 + //[extended]~^ explicit lifetime required } fn main() {} diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs index 122933c3c4e46..5cd323c01db8c 100644 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ b/src/test/ui/lint/uninitialized-zeroed.rs @@ -81,6 +81,9 @@ fn main() { let _val: *const dyn Send = mem::zeroed(); //~ ERROR: does not permit zero-initialization let _val: *const dyn Send = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + let _val: [fn(); 2] = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: [fn(); 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + // Things that can be zero, but not uninit. let _val: bool = mem::zeroed(); let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized @@ -94,6 +97,9 @@ fn main() { let _val: Fruit = mem::zeroed(); let _val: Fruit = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + let _val: [bool; 2] = mem::zeroed(); + let _val: [bool; 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + // Transmute-from-0 let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization @@ -110,6 +116,8 @@ fn main() { let _val: MaybeUninit<&'static i32> = mem::zeroed(); let _val: i32 = mem::zeroed(); let _val: bool = MaybeUninit::zeroed().assume_init(); + let _val: [bool; 0] = MaybeUninit::uninit().assume_init(); + let _val: [!; 0] = MaybeUninit::zeroed().assume_init(); // Some things that happen to work due to rustc implementation details, // but are not guaranteed to keep working. let _val: i32 = mem::uninitialized(); diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index 0af185ef61b5e..b6a66f0a95ad1 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -329,8 +329,30 @@ LL | let _val: *const dyn Send = mem::uninitialized(); | = note: the vtable of a wide raw pointer must be non-null +error: the type `[fn(); 2]` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:84:31 + | +LL | let _val: [fn(); 2] = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + +error: the type `[fn(); 2]` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:85:31 + | +LL | let _val: [fn(); 2] = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: function pointers must be non-null + error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:86:26 + --> $DIR/uninitialized-zeroed.rs:89:26 | LL | let _val: bool = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -341,7 +363,7 @@ LL | let _val: bool = mem::uninitialized(); = note: booleans must be either `true` or `false` error: the type `Wrap` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:89:32 + --> $DIR/uninitialized-zeroed.rs:92:32 | LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -356,7 +378,7 @@ LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ error: the type `NonBig` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:92:28 + --> $DIR/uninitialized-zeroed.rs:95:28 | LL | let _val: NonBig = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -367,7 +389,7 @@ LL | let _val: NonBig = mem::uninitialized(); = note: `NonBig` must be initialized inside its custom valid range error: the type `Fruit` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:95:27 + --> $DIR/uninitialized-zeroed.rs:98:27 | LL | let _val: Fruit = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -384,8 +406,19 @@ LL | | Banana, LL | | } | |_^ +error: the type `[bool; 2]` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:101:31 + | +LL | let _val: [bool; 2] = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: booleans must be either `true` or `false` + error: the type `&i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:98:34 + --> $DIR/uninitialized-zeroed.rs:104:34 | LL | let _val: &'static i32 = mem::transmute(0usize); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -396,7 +429,7 @@ LL | let _val: &'static i32 = mem::transmute(0usize); = note: references must be non-null error: the type `&[i32]` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:99:36 + --> $DIR/uninitialized-zeroed.rs:105:36 | LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -407,7 +440,7 @@ LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); = note: references must be non-null error: the type `NonZeroU32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:100:32 + --> $DIR/uninitialized-zeroed.rs:106:32 | LL | let _val: NonZeroU32 = mem::transmute(0); | ^^^^^^^^^^^^^^^^^ @@ -418,7 +451,7 @@ LL | let _val: NonZeroU32 = mem::transmute(0); = note: `std::num::NonZeroU32` must be non-null error: the type `NonNull` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:103:34 + --> $DIR/uninitialized-zeroed.rs:109:34 | LL | let _val: NonNull = MaybeUninit::zeroed().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -429,7 +462,7 @@ LL | let _val: NonNull = MaybeUninit::zeroed().assume_init(); = note: `std::ptr::NonNull` must be non-null error: the type `NonNull` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:104:34 + --> $DIR/uninitialized-zeroed.rs:110:34 | LL | let _val: NonNull = MaybeUninit::uninit().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -440,7 +473,7 @@ LL | let _val: NonNull = MaybeUninit::uninit().assume_init(); = note: `std::ptr::NonNull` must be non-null error: the type `bool` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:105:26 + --> $DIR/uninitialized-zeroed.rs:111:26 | LL | let _val: bool = MaybeUninit::uninit().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -450,5 +483,5 @@ LL | let _val: bool = MaybeUninit::uninit().assume_init(); | = note: booleans must be either `true` or `false` -error: aborting due to 36 previous errors +error: aborting due to 39 previous errors diff --git a/src/test/ui/macros/issue-95533.rs b/src/test/ui/macros/issue-95533.rs new file mode 100644 index 0000000000000..905c14dc5fd21 --- /dev/null +++ b/src/test/ui/macros/issue-95533.rs @@ -0,0 +1,8 @@ +// check-pass + +#![no_implicit_prelude] +// the macro should not rely on the prelude being imported +::std::thread_local! { static P: () = (); } +::std::thread_local! { static Q: () = const { () }; } + +fn main () {}