diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index cbf01feae06a0..89b203f80a435 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -18,7 +18,7 @@ use rustc_middle::mir::{ }; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCauseCode; -use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; +use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable}; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::Span; @@ -1145,6 +1145,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } let ty = ty.fold_with(&mut OpaqueFolder { tcx }); + let mut failed = false; let ty = tcx.fold_regions(ty, |r, _depth| { let r_vid = self.to_region_vid(r); @@ -1160,15 +1161,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { .filter(|&u_r| !self.universal_regions.is_local_free_region(u_r)) .find(|&u_r| self.eval_equal(u_r, r_vid)) .map(|u_r| ty::Region::new_var(tcx, u_r)) - // In the case of a failure, use `ReErased`. We will eventually - // return `None` in this case. - .unwrap_or(tcx.lifetimes.re_erased) + // In case we could not find a named region to map to, + // we will return `None` below. + .unwrap_or_else(|| { + failed = true; + r + }) }); debug!("try_promote_type_test_subject: folded ty = {:?}", ty); // This will be true if we failed to promote some region. - if ty.has_erased_regions() { + if failed { return None; } diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md index 20f51441c2911..ad77d72c913a8 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0795.md +++ b/compiler/rustc_error_codes/src/error_codes/E0795.md @@ -3,7 +3,7 @@ Invalid argument for the `offset_of!` macro. Erroneous code example: ```compile_fail,E0795 -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] let x = std::mem::offset_of!(Option, Some); ``` @@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option` can be found by specifying the field name `0`: ``` -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] let x: usize = std::mem::offset_of!(Option, Some.0); ``` diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 2f2b551e6ecf7..371b651f5e857 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -549,7 +549,9 @@ declare_features! ( /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)), /// Allows using enums in offset_of! - (unstable, offset_of_enum, "1.75.0", Some(106655)), + (unstable, offset_of_enum, "1.75.0", Some(120141)), + /// Allows using multiple nested field accesses in offset_of! + (unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows macro attributes on expressions, statements and non-inline modules. diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index 3761d52951709..b5f42e98127ee 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -78,14 +78,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) -> bool { let tcx = self.tcx(); let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; - let (hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) - | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(sig, _), - generics, - .. - })) = tcx.hir_node_by_def_id(parent_id) - else { - return false; + let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => { + (sig, generics, None) + } + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(sig, _), + generics, + owner_id, + .. + }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + _ => return false, }; let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return false; @@ -94,6 +97,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let is_object_safe = match self_ty.kind { hir::TyKind::TraitObject(objects, ..) => { objects.iter().all(|o| match o.trait_ref.path.res { + Res::Def(DefKind::Trait, id) if Some(id) == owner => { + // When we're dealing with a recursive trait, we don't want to downgrade + // the error, so we consider them to be object safe always. (#119652) + true + } Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id), _ => false, }) @@ -122,7 +130,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ], Applicability::MachineApplicable, ); - } else { + } else if diag.is_error() { // We'll emit the object safety error already, with a structured suggestion. diag.downgrade_to_delayed_bug(); } @@ -148,8 +156,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if !is_object_safe { diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`")); - // We'll emit the object safety error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); + if diag.is_error() { + // We'll emit the object safety error already, with a structured suggestion. + diag.downgrade_to_delayed_bug(); + } } else { let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { // There are more than one trait bound, we need surrounding parentheses. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 4b1ad28f0941d..33d7ba6268a20 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3246,6 +3246,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let container = self.to_ty(container).normalized; + if let Some(ident_2) = fields.get(1) + && !self.tcx.features().offset_of_nested + { + rustc_session::parse::feature_err( + &self.tcx.sess, + sym::offset_of_nested, + ident_2.span, + "only a single ident or integer is stable as the field in offset_of", + ) + .emit(); + } + let mut field_indices = Vec::with_capacity(fields.len()); let mut current_container = container; let mut fields = fields.into_iter(); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 67c35d717a1ec..80467ca9381e3 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -60,6 +60,7 @@ use rustc_hir::{HirIdMap, Node}; use rustc_hir_analysis::astconv::AstConv; use rustc_hir_analysis::check::check_abi; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::traits::ObligationInspector; use rustc_middle::query::Providers; use rustc_middle::traits; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -139,7 +140,7 @@ fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> { let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity(); - typeck_with_fallback(tcx, def_id, fallback) + typeck_with_fallback(tcx, def_id, fallback, None) } /// Used only to get `TypeckResults` for type inference during error recovery. @@ -149,14 +150,28 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T let span = tcx.hir().span(tcx.local_def_id_to_hir_id(def_id)); Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used") }; - typeck_with_fallback(tcx, def_id, fallback) + typeck_with_fallback(tcx, def_id, fallback, None) } -#[instrument(level = "debug", skip(tcx, fallback), ret)] +/// Same as `typeck` but `inspect` is invoked on evaluation of each root obligation. +/// Inspecting obligations only works with the new trait solver. +/// This function is *only to be used* by external tools, it should not be +/// called from within rustc. Note, this is not a query, and thus is not cached. +pub fn inspect_typeck<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + inspect: ObligationInspector<'tcx>, +) -> &'tcx ty::TypeckResults<'tcx> { + let fallback = move || tcx.type_of(def_id.to_def_id()).instantiate_identity(); + typeck_with_fallback(tcx, def_id, fallback, Some(inspect)) +} + +#[instrument(level = "debug", skip(tcx, fallback, inspector), ret)] fn typeck_with_fallback<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, fallback: impl Fn() -> Ty<'tcx> + 'tcx, + inspector: Option>, ) -> &'tcx ty::TypeckResults<'tcx> { // Closures' typeck results come from their outermost function, // as they are part of the same "inference environment". @@ -178,6 +193,9 @@ fn typeck_with_fallback<'tcx>( let param_env = tcx.param_env(def_id); let inh = Inherited::new(tcx, def_id); + if let Some(inspector) = inspector { + inh.infcx.attach_obligation_inspector(inspector); + } let mut fcx = FnCtxt::new(&inh, param_env, def_id); if let Some(hir::FnSig { header, decl, .. }) = fn_sig { diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index e60e3ffeaa72c..0f1af81d9f04c 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -90,6 +90,7 @@ impl<'tcx> InferCtxt<'tcx> { universe: self.universe.clone(), intercrate, next_trait_solver: self.next_trait_solver, + obligation_inspector: self.obligation_inspector.clone(), } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 002aad19c4981..1eab8575fc0c4 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -13,7 +13,9 @@ use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use self::opaque_types::OpaqueTypeStorage; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; -use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt}; +use crate::traits::{ + self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt, +}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -334,6 +336,8 @@ pub struct InferCtxt<'tcx> { pub intercrate: bool, next_trait_solver: bool, + + pub obligation_inspector: Cell>>, } impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { @@ -708,6 +712,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { universe: Cell::new(ty::UniverseIndex::ROOT), intercrate, next_trait_solver, + obligation_inspector: Cell::new(None), } } } @@ -1718,6 +1723,15 @@ impl<'tcx> InferCtxt<'tcx> { } } } + + /// Attach a callback to be invoked on each root obligation evaluated in the new trait solver. + pub fn attach_obligation_inspector(&self, inspector: ObligationInspector<'tcx>) { + debug_assert!( + self.obligation_inspector.get().is_none(), + "shouldn't override a set obligation inspector" + ); + self.obligation_inspector.set(Some(inspector)); + } } impl<'tcx> TypeErrCtxt<'_, 'tcx> { diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index fdae093aac8b4..72ec07375ac0e 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -13,12 +13,15 @@ use std::hash::{Hash, Hasher}; use hir::def_id::LocalDefId; use rustc_hir as hir; +use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::solve::Certainty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; pub use self::ImplSource::*; pub use self::SelectionError::*; +use crate::infer::InferCtxt; pub use self::engine::{TraitEngine, TraitEngineExt}; pub use self::project::MismatchedProjectionTypes; @@ -116,6 +119,11 @@ pub type PredicateObligations<'tcx> = Vec>; pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>; +/// A callback that can be provided to `inspect_typeck`. Invoked on evaluation +/// of root obligations. +pub type ObligationInspector<'tcx> = + fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result); + pub struct FulfillmentError<'tcx> { pub obligation: PredicateObligation<'tcx>, pub code: FulfillmentErrorCode<'tcx>, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 5a95f2083f666..abb0a7a465aa1 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2567,8 +2567,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { debug!(?param.ident, ?param.ident.span, ?use_span); let elidable = matches!(use_ctxt, LifetimeCtxt::Ref); + let deletion_span = + if param.bounds.is_empty() { deletion_span() } else { None }; - let deletion_span = deletion_span(); self.r.lint_buffer.buffer_lint_with_diagnostic( lint::builtin::SINGLE_USE_LIFETIMES, param.id, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 44795022cbab3..7b0138d50baed 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1153,6 +1153,7 @@ symbols! { offset, offset_of, offset_of_enum, + offset_of_nested, ok_or_else, omit_gdb_pretty_printer_section, on, diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index c847425ebf46a..f08622816ec28 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -11,7 +11,7 @@ use rustc_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use super::eval_ctxt::GenerateProofTree; -use super::{Certainty, InferCtxtEvalExt}; +use super::{Certainty, Goal, InferCtxtEvalExt}; /// A trait engine using the new trait solver. /// @@ -43,6 +43,21 @@ impl<'tcx> FulfillmentCtxt<'tcx> { ); FulfillmentCtxt { obligations: Vec::new(), usable_in_snapshot: infcx.num_open_snapshots() } } + + fn inspect_evaluated_obligation( + &self, + infcx: &InferCtxt<'tcx>, + obligation: &PredicateObligation<'tcx>, + result: &Result<(bool, Certainty, Vec>>), NoSolution>, + ) { + if let Some(inspector) = infcx.obligation_inspector.get() { + let result = match result { + Ok((_, c, _)) => Ok(*c), + Err(NoSolution) => Err(NoSolution), + }; + (inspector)(infcx, &obligation, result); + } + } } impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { @@ -100,65 +115,66 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { let mut has_changed = false; for obligation in mem::take(&mut self.obligations) { let goal = obligation.clone().into(); - let (changed, certainty, nested_goals) = - match infcx.evaluate_root_goal(goal, GenerateProofTree::IfEnabled).0 { - Ok(result) => result, - Err(NoSolution) => { - errors.push(FulfillmentError { - obligation: obligation.clone(), - code: match goal.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { - FulfillmentErrorCode::ProjectionError( - // FIXME: This could be a `Sorts` if the term is a type - MismatchedProjectionTypes { err: TypeError::Mismatch }, - ) - } - ty::PredicateKind::NormalizesTo(..) => { - FulfillmentErrorCode::ProjectionError( - MismatchedProjectionTypes { err: TypeError::Mismatch }, - ) - } - ty::PredicateKind::AliasRelate(_, _, _) => { - FulfillmentErrorCode::ProjectionError( - MismatchedProjectionTypes { err: TypeError::Mismatch }, - ) - } - ty::PredicateKind::Subtype(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( - goal.predicate.kind().rebind((pred.a, pred.b)), - ); - let expected_found = ExpectedFound::new(true, a, b); - FulfillmentErrorCode::SubtypeError( - expected_found, - TypeError::Sorts(expected_found), - ) - } - ty::PredicateKind::Coerce(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( - goal.predicate.kind().rebind((pred.a, pred.b)), - ); - let expected_found = ExpectedFound::new(false, a, b); - FulfillmentErrorCode::SubtypeError( - expected_found, - TypeError::Sorts(expected_found), - ) - } - ty::PredicateKind::Clause(_) - | ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::Ambiguous => { - FulfillmentErrorCode::SelectionError( - SelectionError::Unimplemented, - ) - } - ty::PredicateKind::ConstEquate(..) => { - bug!("unexpected goal: {goal:?}") - } - }, - root_obligation: obligation, - }); - continue; - } - }; + let result = infcx.evaluate_root_goal(goal, GenerateProofTree::IfEnabled).0; + self.inspect_evaluated_obligation(infcx, &obligation, &result); + let (changed, certainty, nested_goals) = match result { + Ok(result) => result, + Err(NoSolution) => { + errors.push(FulfillmentError { + obligation: obligation.clone(), + code: match goal.predicate.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { + FulfillmentErrorCode::ProjectionError( + // FIXME: This could be a `Sorts` if the term is a type + MismatchedProjectionTypes { err: TypeError::Mismatch }, + ) + } + ty::PredicateKind::NormalizesTo(..) => { + FulfillmentErrorCode::ProjectionError( + MismatchedProjectionTypes { err: TypeError::Mismatch }, + ) + } + ty::PredicateKind::AliasRelate(_, _, _) => { + FulfillmentErrorCode::ProjectionError( + MismatchedProjectionTypes { err: TypeError::Mismatch }, + ) + } + ty::PredicateKind::Subtype(pred) => { + let (a, b) = infcx.instantiate_binder_with_placeholders( + goal.predicate.kind().rebind((pred.a, pred.b)), + ); + let expected_found = ExpectedFound::new(true, a, b); + FulfillmentErrorCode::SubtypeError( + expected_found, + TypeError::Sorts(expected_found), + ) + } + ty::PredicateKind::Coerce(pred) => { + let (a, b) = infcx.instantiate_binder_with_placeholders( + goal.predicate.kind().rebind((pred.a, pred.b)), + ); + let expected_found = ExpectedFound::new(false, a, b); + FulfillmentErrorCode::SubtypeError( + expected_found, + TypeError::Sorts(expected_found), + ) + } + ty::PredicateKind::Clause(_) + | ty::PredicateKind::ObjectSafe(_) + | ty::PredicateKind::Ambiguous => { + FulfillmentErrorCode::SelectionError( + SelectionError::Unimplemented, + ) + } + ty::PredicateKind::ConstEquate(..) => { + bug!("unexpected goal: {goal:?}") + } + }, + root_obligation: obligation, + }); + continue; + } + }; // Push any nested goals that we get from unifying our canonical response // with our obligation onto the fulfillment context. self.obligations.extend(nested_goals.into_iter().map(|goal| { diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index eba2ac57012b9..b0a08cd9b792c 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -12,7 +12,7 @@ use std::fmt::{self, Debug, Display, Formatter}; use std::ops::Range; #[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub struct Ty(pub usize); +pub struct Ty(usize); impl Debug for Ty { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -138,7 +138,7 @@ impl Const { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct ConstId(pub usize); +pub struct ConstId(usize); type Ident = Opaque; diff --git a/library/core/benches/ascii.rs b/library/core/benches/ascii.rs index 64938745a4a16..71ec9fed2fe75 100644 --- a/library/core/benches/ascii.rs +++ b/library/core/benches/ascii.rs @@ -63,6 +63,7 @@ macro_rules! benches { } } +use std::fmt::Write; use test::black_box; use test::Bencher; @@ -351,3 +352,30 @@ static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 256] = [ N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, ]; + +const ASCII_PATH: &[u8] = b"home/kyubey/rust/build/x86_64-unknown-linux-gnu/stage0/lib:/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-tools/release/deps"; +const RUST_INCANTATION: &[u8] = br#"AR_x86_64_unknown_linux_gnu="ar" CARGO_INCREMENTAL="0" CARGO_PROFILE_RELEASE_DEBUG="1" CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS="false" CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS="false" CARGO_TARGET_DIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-std" CC_x86_64_unknown_linux_gnu="cc" CFG_COMPILER_HOST_TRIPLE="x86_64-unknown-linux-gnu" CFG_RELEASE_CHANNEL="dev" CFLAGS_x86_64_unknown_linux_gnu="-ffunction-sections -fdata-sections -fPIC -m64" CXXFLAGS_x86_64_unknown_linux_gnu="-ffunction-sections -fdata-sections -fPIC -m64" CXX_x86_64_unknown_linux_gnu="c++" LD_LIBRARY_PATH="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-sysroot/lib/rustlib/x86_64-unknown-linux-gnu/lib" LIBC_CHECK_CFG="1" RANLIB_x86_64_unknown_linux_gnu="ar s" REAL_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" RUSTBUILD_NATIVE_DIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/native" RUSTC="/home/kyubey/workspace/rust/build/bootstrap/debug/rustc" RUSTC_BOOTSTRAP="1" RUSTC_BREAK_ON_ICE="1" RUSTC_ERROR_METADATA_DST="/home/kyubey/workspace/rust/build/tmp/extended-error-metadata" RUSTC_FORCE_UNSTABLE="1" RUSTC_HOST_FUSE_LD_LLD="1" RUSTC_INSTALL_BINDIR="bin" RUSTC_LIBDIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/lib" RUSTC_LINT_FLAGS="-Wrust_2018_idioms -Wunused_lifetimes -Wsemicolon_in_expressions_from_macros" RUSTC_REAL="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/bin/rustc" RUSTC_SNAPSHOT="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/bin/rustc" RUSTC_SNAPSHOT_LIBDIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/lib" RUSTC_STAGE="0" RUSTC_SYSROOT="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0-sysroot" RUSTC_VERBOSE="0" RUSTDOC="/home/kyubey/workspace/rust/build/bootstrap/debug/rustdoc" RUSTDOCFLAGS="-C target-cpu=native --cfg=bootstrap -Csymbol-mangling-version=legacy -Zunstable-options -Zunstable-options --check-cfg=values(bootstrap) --check-cfg=values(stdarch_intel_sde) --check-cfg=values(no_fp_fmt_parse) --check-cfg=values(no_global_oom_handling) --check-cfg=values(no_rc) --check-cfg=values(no_sync) --check-cfg=values(freebsd12) --check-cfg=values(freebsd13) --check-cfg=values(backtrace_in_libstd) --check-cfg=values(target_env,\"libnx\") --check-cfg=values(target_arch,\"asmjs\",\"spirv\",\"nvptx\",\"xtensa\") -Clink-arg=-fuse-ld=lld -Clink-arg=-Wl,--threads=1 -Wrustdoc::invalid_codeblock_attributes --crate-version 1.72.0-dev -Zcrate-attr=doc(html_root_url=\"https://doc.rust-lang.org/nightly/\") -Zcrate-attr=warn(rust_2018_idioms)" RUSTDOC_FUSE_LD_LLD="1" RUSTDOC_LIBDIR="/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/lib" RUSTDOC_REAL="/path/to/nowhere/rustdoc/not/required" RUSTFLAGS="-C target-cpu=native --cfg=bootstrap -Csymbol-mangling-version=legacy -Zunstable-options -Zunstable-options --check-cfg=values(bootstrap) --check-cfg=values(stdarch_intel_sde) --check-cfg=values(no_fp_fmt_parse) --check-cfg=values(no_global_oom_handling) --check-cfg=values(no_rc) --check-cfg=values(no_sync) --check-cfg=values(freebsd12) --check-cfg=values(freebsd13) --check-cfg=values(backtrace_in_libstd) --check-cfg=values(target_env,\"libnx\") --check-cfg=values(target_arch,\"asmjs\",\"spirv\",\"nvptx\",\"xtensa\") -Zmacro-backtrace -Clink-args=-Wl,-z,origin -Clink-args=-Wl,-rpath,$ORIGIN/../lib -Clink-args=-fuse-ld=lld -Csplit-debuginfo=off -Cprefer-dynamic -Zinline-mir -Clto=off -Zcrate-attr=doc(html_root_url=\"https://doc.rust-lang.org/nightly/\")" RUST_COMPILER_RT_ROOT="/home/kyubey/workspace/rust/src/llvm-project/compiler-rt" RUST_TEST_THREADS="48" WINAPI_NO_BUNDLED_LIBRARIES="1" __CARGO_DEFAULT_LIB_METADATA="bootstrapstd" "/home/kyubey/workspace/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "bench" "--target" "x86_64-unknown-linux-gnu" "-Zcheck-cfg=names,values,output" "-Zbinary-dep-depinfo" "-j" "48" "--features" " panic-unwind backtrace compiler-builtins-c" "--manifest-path" "/home/kyubey/workspace/rust/library/sysroot/Cargo.toml" "-p" "core" "--" "bench_ascii_escape_display" "--quiet" "-Z" "unstable-options" "--format" "json""#; + +#[bench] +fn bench_ascii_escape_display_no_escape(b: &mut Bencher) { + let mut writer = String::with_capacity(8 * 1024); + + b.iter(move || { + writer.clear(); + let iter = ASCII_PATH.escape_ascii(); + write!(writer, "{}", iter).unwrap(); + writer.len() + }) +} + +#[bench] +fn bench_ascii_escape_display_mixed(b: &mut Bencher) { + let mut writer = String::with_capacity(8 * 1024); + + b.iter(move || { + writer.clear(); + let iter = RUST_INCANTATION.escape_ascii(); + write!(writer, "{}", iter).unwrap(); + writer.len() + }) +} diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index ef8e4d098ed95..02867789b79dd 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -96,6 +96,17 @@ pub fn escape_default(c: u8) -> EscapeDefault { EscapeDefault(escape::EscapeIterInner::new(data, range)) } +impl EscapeDefault { + pub(crate) fn empty() -> Self { + let data = [Char::Null; 4]; + EscapeDefault(escape::EscapeIterInner::new(data, 0..0)) + } + + pub(crate) fn as_str(&self) -> &str { + self.0.as_str() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for EscapeDefault { type Item = u8; diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 6122332da0d24..7d6f746845e31 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -24,6 +24,14 @@ impl U> FlatMap { pub(in crate::iter) fn new(iter: I, f: F) -> FlatMap { FlatMap { inner: FlattenCompat::new(iter.map(f)) } } + + pub(crate) fn into_parts(self) -> (Option, Option, Option) { + ( + self.inner.frontiter, + self.inner.iter.into_inner().map(Map::into_inner), + self.inner.backiter, + ) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index 462a7e8773320..7781ed088b76c 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -24,6 +24,10 @@ impl Fuse { pub(in crate::iter) fn new(iter: I) -> Fuse { Fuse { iter: Some(iter) } } + + pub(crate) fn into_inner(self) -> Option { + self.iter + } } #[stable(feature = "fused", since = "1.26.0")] diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index e27fc7257f6cc..c882c9e7f3f51 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -69,6 +69,10 @@ impl Map { pub(in crate::iter) fn new(iter: I, f: F) -> Map { Map { iter, f } } + + pub(crate) fn into_inner(self) -> I { + self.iter + } } #[stable(feature = "core_impl_debug", since = "1.9.0")] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 1a8f245c8be30..81bf6f28693f1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -111,6 +111,7 @@ // // Library features: // tidy-alphabetical-start +#![cfg_attr(not(bootstrap), feature(offset_of_nested))] #![feature(char_indices_offset)] #![feature(const_align_of_val)] #![feature(const_align_of_val_raw)] @@ -176,7 +177,6 @@ #![feature(isqrt)] #![feature(maybe_uninit_uninit_array)] #![feature(non_null_convenience)] -#![feature(offset_of)] #![feature(offset_of_enum)] #![feature(panic_internals)] #![feature(ptr_alignment_type)] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 407954001e4ce..f04ccce40f109 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1303,11 +1303,12 @@ impl SizedTypeProperties for T {} /// Enum variants may be traversed as if they were fields. Variants themselves do /// not have an offset. /// +/// However, on stable only a single field name is supported, which blocks the use of +/// enum support. +/// /// Visibility is respected - all types and fields must be visible to the call site: /// /// ``` -/// #![feature(offset_of)] -/// /// mod nested { /// #[repr(C)] /// pub struct Struct { @@ -1330,8 +1331,6 @@ impl SizedTypeProperties for T {} /// not *identical*, e.g.: /// /// ``` -/// #![feature(offset_of)] -/// /// struct Wrapper(T, U); /// /// type A = Wrapper; @@ -1359,8 +1358,7 @@ impl SizedTypeProperties for T {} /// # Examples /// /// ``` -/// #![feature(offset_of)] -/// # #![feature(offset_of_enum)] +/// #![feature(offset_of_enum, offset_of_nested)] /// /// use std::mem; /// #[repr(C)] @@ -1396,7 +1394,7 @@ impl SizedTypeProperties for T {} /// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); /// ``` #[cfg(not(bootstrap))] -#[unstable(feature = "offset_of", issue = "106655")] +#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")] #[allow_internal_unstable(builtin_syntax, hint_must_use)] pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { // The `{}` is for better error messages @@ -1404,7 +1402,7 @@ pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { } #[cfg(bootstrap)] -#[unstable(feature = "offset_of", issue = "106655")] +#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")] #[allow_internal_unstable(builtin_syntax, hint_must_use)] #[allow(missing_docs)] pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) { diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 7d60686597a0d..bda691b16d4a7 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -171,6 +171,39 @@ macro_rules! nonzero_integer { } } + /// Converts a primitive mutable reference to a non-zero mutable reference + /// without checking whether the referenced value is non-zero. + /// This results in undefined behavior if `*n` is zero. + /// + /// # Safety + /// The referenced value must not be currently zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub unsafe fn from_mut_unchecked(n: &mut $Int) -> &mut Self { + // SAFETY: Self is repr(transparent), and the value is assumed to be non-zero. + unsafe { + let n_alias = &mut *n; + core::intrinsics::assert_unsafe_precondition!( + concat!(stringify!($Ty), "::from_mut_unchecked requires the argument to dereference as non-zero"), + (n_alias: &mut $Int) => *n_alias != 0 + ); + &mut *(n as *mut $Int as *mut Self) + } + } + + /// Converts a primitive mutable reference to a non-zero mutable reference + /// if the referenced integer is not zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub fn from_mut(n: &mut $Int) -> Option<&mut Self> { + // SAFETY: Self is repr(transparent), and the value is non-zero. + // As long as the returned reference is alive, + // the user cannot `*n = 0` directly. + (*n != 0).then(|| unsafe { &mut *(n as *mut $Int as *mut Self) }) + } + /// Returns the value as a primitive type. #[$stability] #[inline] diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index ce04a9f40898e..5c4f0bf9b2b49 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -5,6 +5,7 @@ use crate::fmt::{self, Write}; use crate::iter; use crate::mem; use crate::ops; +use core::ascii::EscapeDefault; #[cfg(not(test))] impl [u8] { @@ -253,7 +254,45 @@ impl<'a> iter::FusedIterator for EscapeAscii<'a> {} #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] impl<'a> fmt::Display for EscapeAscii<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.clone().try_for_each(|b| f.write_char(b as char)) + // disassemble iterator, including front/back parts of flatmap in case it has been partially consumed + let (front, slice, back) = self.clone().inner.into_parts(); + let front = front.unwrap_or(EscapeDefault::empty()); + let mut bytes = slice.unwrap_or_default().as_slice(); + let back = back.unwrap_or(EscapeDefault::empty()); + + // usually empty, so the formatter won't have to do any work + for byte in front { + f.write_char(byte as char)?; + } + + fn needs_escape(b: u8) -> bool { + b > 0x7E || b < 0x20 || b == b'\\' || b == b'\'' || b == b'"' + } + + while bytes.len() > 0 { + // fast path for the printable, non-escaped subset of ascii + let prefix = bytes.iter().take_while(|&&b| !needs_escape(b)).count(); + // SAFETY: prefix length was derived by counting bytes in the same splice, so it's in-bounds + let (prefix, remainder) = unsafe { bytes.split_at_unchecked(prefix) }; + // SAFETY: prefix is a valid utf8 sequence, as it's a subset of ASCII + let prefix = unsafe { crate::str::from_utf8_unchecked(prefix) }; + + f.write_str(prefix)?; // the fast part + + bytes = remainder; + + if let Some(&b) = bytes.first() { + // guaranteed to be non-empty, better to write it as a str + f.write_str(ascii::escape_default(b).as_str())?; + bytes = &bytes[1..]; + } + } + + // also usually empty + for byte in back { + f.write_char(byte as char)?; + } + Ok(()) } } #[stable(feature = "inherent_ascii_escape", since = "1.60.0")] diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs index f5f2dd0477885..3d3f8ac10c603 100644 --- a/library/core/tests/ascii.rs +++ b/library/core/tests/ascii.rs @@ -479,3 +479,13 @@ fn ascii_ctype_const() { is_ascii_control => [false, false, false, false, false]; } } + +#[test] +fn test_ascii_display() { + assert_eq!(b"foo'bar".escape_ascii().to_string(), r#"foo\'bar"#); + assert_eq!(b"\0\xff".escape_ascii().to_string(), r#"\x00\xff"#); + let mut it = b"\0fastpath\xffremainder\xff".escape_ascii(); + let _ = it.advance_by(4); + let _ = it.advance_back_by(4); + assert_eq!(it.to_string(), r#"fastpath\xffremainder"#); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 8604d41eb6860..13fb97fdc7f3e 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -59,6 +59,7 @@ #![feature(noop_waker)] #![feature(numfmt)] #![feature(num_midpoint)] +#![cfg_attr(not(bootstrap), feature(offset_of_nested))] #![feature(isqrt)] #![feature(step_trait)] #![feature(str_internals)] @@ -115,7 +116,6 @@ #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] -#![feature(offset_of)] #![feature(iter_map_windows)] #![allow(internal_features)] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index c3506175715fe..1b38ba721147c 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -102,8 +102,6 @@ impl f32 { /// # Examples /// /// ``` - /// #![feature(round_ties_even)] - /// /// let f = 3.3_f32; /// let g = -3.3_f32; /// let h = 3.5_f32; @@ -116,7 +114,7 @@ impl f32 { /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] - #[unstable(feature = "round_ties_even", issue = "96710")] + #[stable(feature = "round_ties_even", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn round_ties_even(self) -> f32 { unsafe { intrinsics::rintf32(self) } diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index e4b7bfeeb84af..f8fc84440ae5c 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -102,8 +102,6 @@ impl f64 { /// # Examples /// /// ``` - /// #![feature(round_ties_even)] - /// /// let f = 3.3_f64; /// let g = -3.3_f64; /// let h = 3.5_f64; @@ -116,7 +114,7 @@ impl f64 { /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] - #[unstable(feature = "round_ties_even", issue = "96710")] + #[stable(feature = "round_ties_even", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn round_ties_even(self) -> f64 { unsafe { intrinsics::rintf64(self) } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 7a8d9d0ceeca6..568645ddf7311 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -329,7 +329,6 @@ #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_write_slice)] -#![feature(offset_of)] #![feature(panic_can_unwind)] #![feature(panic_info_message)] #![feature(panic_internals)] @@ -338,7 +337,6 @@ #![feature(prelude_2024)] #![feature(ptr_as_uninit)] #![feature(raw_os_nonzero)] -#![feature(round_ties_even)] #![feature(slice_internals)] #![feature(slice_ptr_get)] #![feature(slice_range)] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index cacd02bbfaee1..80a47c852692c 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -8,7 +8,6 @@ #![feature(variant_count)] #![feature(yeet_expr)] #![feature(nonzero_ops)] -#![feature(round_ties_even)] #![feature(let_chains)] #![feature(lint_reasons)] #![feature(int_roundings)] diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index 5f2d4489f4ac1..1bb44d56bf6b5 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -1,5 +1,4 @@ #![feature(stmt_expr_attributes)] -#![feature(round_ties_even)] #![feature(float_gamma)] #![allow(arithmetic_overflow)] diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 8e791a7dc69cb..d673ce7a736d9 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -15,7 +15,7 @@ use std::ffi::OsStr; use std::fmt; use std::fs; use std::num::NonZeroU32; -use std::path::Path; +use std::path::{Path, PathBuf}; use regex::Regex; @@ -52,6 +52,8 @@ pub struct Feature { pub since: Option, pub has_gate_test: bool, pub tracking_issue: Option, + pub file: PathBuf, + pub line: usize, } impl Feature { fn tracking_issue_display(&self) -> impl fmt::Display { @@ -184,23 +186,25 @@ pub fn check( .chain(lib_features.iter().map(|feat| (feat, "lib"))); for ((feature_name, feature), kind) in all_features_iter { let since = if let Some(since) = feature.since { since } else { continue }; + let file = feature.file.display(); + let line = feature.line; if since > version && since != Version::CurrentPlaceholder { tidy_error!( bad, - "The stabilization version {since} of {kind} feature `{feature_name}` is newer than the current {version}" + "{file}:{line}: The stabilization version {since} of {kind} feature `{feature_name}` is newer than the current {version}" ); } if channel == "nightly" && since == version { tidy_error!( bad, - "The stabilization version {since} of {kind} feature `{feature_name}` is written out but should be {}", + "{file}:{line}: The stabilization version {since} of {kind} feature `{feature_name}` is written out but should be {}", version::VERSION_PLACEHOLDER ); } if channel != "nightly" && since == Version::CurrentPlaceholder { tidy_error!( bad, - "The placeholder use of {kind} feature `{feature_name}` is not allowed on the {channel} channel", + "{file}:{line}: The placeholder use of {kind} feature `{feature_name}` is not allowed on the {channel} channel", ); } } @@ -433,7 +437,14 @@ fn collect_lang_features_in(features: &mut Features, base: &Path, file: &str, ba ); } Entry::Vacant(e) => { - e.insert(Feature { level, since, has_gate_test: false, tracking_issue }); + e.insert(Feature { + level, + since, + has_gate_test: false, + tracking_issue, + file: path.to_path_buf(), + line: line_number, + }); } } } @@ -559,6 +570,8 @@ fn map_lib_features( since: None, has_gate_test: false, tracking_issue: find_attr_val(line, "issue").and_then(handle_issue_none), + file: file.to_path_buf(), + line: i + 1, }; mf(Ok((feature_name, feature)), file, i + 1); continue; @@ -588,7 +601,14 @@ fn map_lib_features( }; let tracking_issue = find_attr_val(line, "issue").and_then(handle_issue_none); - let feature = Feature { level, since, has_gate_test: false, tracking_issue }; + let feature = Feature { + level, + since, + has_gate_test: false, + tracking_issue, + file: file.to_path_buf(), + line: i + 1, + }; if line.contains(']') { mf(Ok((feature_name, feature)), file, i + 1); } else { diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs index 43ecbbed186f6..f15d15bfcb268 100644 --- a/tests/mir-opt/const_prop/offset_of.rs +++ b/tests/mir-opt/const_prop/offset_of.rs @@ -2,7 +2,7 @@ // unit-test: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] use std::marker::PhantomData; use std::mem::offset_of; diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs index e71b3f59ecab3..c1be691025805 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.rs +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -2,7 +2,7 @@ // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::marker::PhantomData; use std::mem::offset_of; diff --git a/tests/pretty/offset_of.rs b/tests/pretty/offset_of.rs index e1783432857e2..1307c335ad322 100644 --- a/tests/pretty/offset_of.rs +++ b/tests/pretty/offset_of.rs @@ -1,4 +1,3 @@ // pp-exact -#![feature(offset_of)] fn main() { std::mem::offset_of!(std :: ops :: Range < usize >, end); } diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs index e19dcf9f6a54c..1f2f7ee1e1919 100644 --- a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr index 02ee54e8607ac..fc7dd7923f7a8 100644 --- a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr @@ -13,7 +13,7 @@ error[E0658]: using enums in offset_of is experimental LL | offset_of!(Alpha, One); | ^^^ | - = note: see issue #106655 for more information + = note: see issue #120141 for more information = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -29,7 +29,7 @@ error[E0658]: using enums in offset_of is experimental LL | offset_of!(Alpha, Two.0); | ^^^ | - = note: see issue #106655 for more information + = note: see issue #120141 for more information = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.rs b/tests/ui/feature-gates/feature-gate-offset-of-nested.rs new file mode 100644 index 0000000000000..c4eb4720fde5e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-offset-of-nested.rs @@ -0,0 +1,28 @@ +#![feature(offset_of_enum)] + +use std::mem::offset_of; + +struct S { + a: u8, + b: (u8, u8), + c: T, +} + +struct T { + t: &'static str, +} + +enum Alpha { + One(u8), + Two(u8), +} + +fn main() { + offset_of!(Alpha, Two.0); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!(S, a); + offset_of!((u8, S), 1); + offset_of!((u32, (S, T)), 1.1); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!(S, b.0); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!((S, ()), 0.c); //~ ERROR only a single ident or integer is stable as the field in offset_of + offset_of!(S, c.t); //~ ERROR only a single ident or integer is stable as the field in offset_of +} diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr new file mode 100644 index 0000000000000..f367fc9fa0dd4 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr @@ -0,0 +1,60 @@ +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:21:27 + | +LL | offset_of!(Alpha, Two.0); + | ^ + | + = note: see issue #120140 for more information + = help: add `#![feature(offset_of_nested)]` 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]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:24:33 + | +LL | offset_of!((u32, (S, T)), 1.1); + | _____----------------------------^- + | | | + | | in this macro invocation +LL | | offset_of!(S, b.0); +LL | | offset_of!((S, ()), 0.c); +LL | | offset_of!(S, c.t); +... | + | + = note: see issue #120140 for more information + = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:25:21 + | +LL | offset_of!(S, b.0); + | ^ + | + = note: see issue #120140 for more information + = help: add `#![feature(offset_of_nested)]` 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]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:26:27 + | +LL | offset_of!((S, ()), 0.c); + | ^ + | + = note: see issue #120140 for more information + = help: add `#![feature(offset_of_nested)]` 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]: only a single ident or integer is stable as the field in offset_of + --> $DIR/feature-gate-offset-of-nested.rs:27:21 + | +LL | offset_of!(S, c.t); + | ^ + | + = note: see issue #120140 for more information + = help: add `#![feature(offset_of_nested)]` 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 + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/layout/issue-112048-unsizing-niche.rs b/tests/ui/layout/issue-112048-unsizing-niche.rs index 23588ba36ee59..e59e063df99be 100644 --- a/tests/ui/layout/issue-112048-unsizing-niche.rs +++ b/tests/ui/layout/issue-112048-unsizing-niche.rs @@ -2,7 +2,6 @@ // Check that unsizing does not change which field is considered for niche layout. -#![feature(offset_of)] #![allow(dead_code)] #[derive(Clone)] diff --git a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs index 2c6fcef250049..ae81a2524396c 100644 --- a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs +++ b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs @@ -1,6 +1,6 @@ // check-pass -#![feature(offset_of)] +#![feature(offset_of_nested)] #![deny(dead_code)] // This struct contains a projection that can only be normalized after getting the field type. diff --git a/tests/ui/lint/dead-code/offset-of.rs b/tests/ui/lint/dead-code/offset-of.rs index da91de3862fc8..5269426d2ff3a 100644 --- a/tests/ui/lint/dead-code/offset-of.rs +++ b/tests/ui/lint/dead-code/offset-of.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] #![deny(dead_code)] use std::mem::offset_of; diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.rs b/tests/ui/object-safety/avoid-ice-on-warning-2.rs new file mode 100644 index 0000000000000..cd34362d3dd52 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.rs @@ -0,0 +1,9 @@ +fn id(f: Copy) -> usize { +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +//~| ERROR the trait `Copy` cannot be made into an object + f() +} +fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.stderr new file mode 100644 index 0000000000000..2755eee6f3529 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.stderr @@ -0,0 +1,50 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-2.rs:1:13 + | +LL | fn id(f: Copy) -> usize { + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `Copy` it is not object safe, so it can't be `dyn` + = note: `#[warn(bare_trait_objects)]` on by default +help: use a new generic type parameter, constrained by `Copy` + | +LL | fn id(f: T) -> usize { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn id(f: impl Copy) -> usize { + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-2.rs:1:13 + | +LL | fn id(f: Copy) -> usize { + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `Copy` it is not object safe, so it can't be `dyn` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use a new generic type parameter, constrained by `Copy` + | +LL | fn id(f: T) -> usize { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn id(f: impl Copy) -> usize { + | ++++ + +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/avoid-ice-on-warning-2.rs:1:13 + | +LL | fn id(f: Copy) -> usize { + | ^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = 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 + +error: aborting due to 1 previous error; 2 warnings emitted + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.rs b/tests/ui/object-safety/avoid-ice-on-warning-3.rs new file mode 100644 index 0000000000000..caaf4d0fd99aa --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.rs @@ -0,0 +1,17 @@ +trait B { fn f(a: A) -> A; } +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| ERROR the trait `A` cannot be made into an object +trait A { fn g(b: B) -> B; } +//~^ WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| WARN this is accepted in the current edition +//~| ERROR the trait `B` cannot be made into an object +fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.stderr new file mode 100644 index 0000000000000..0fc67770b96dd --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.stderr @@ -0,0 +1,148 @@ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:9:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `B` it is not object safe, so it can't be `dyn` + = note: `#[warn(bare_trait_objects)]` on by default +help: use a new generic type parameter, constrained by `B` + | +LL | trait A { fn g(b: T) -> B; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait A { fn g(b: impl B) -> B; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:9:25 + | +LL | trait A { fn g(b: B) -> B; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | trait A { fn g(b: B) -> impl B; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:1:19 + | +LL | trait B { fn f(a: A) -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `A` it is not object safe, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` + | +LL | trait B { fn f(a: T) -> A; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait B { fn f(a: impl A) -> A; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:1:25 + | +LL | trait B { fn f(a: A) -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: `A` is not object safe, use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | trait B { fn f(a: A) -> impl A; } + | ++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:1:19 + | +LL | trait B { fn f(a: A) -> A; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `A` it is not object safe, so it can't be `dyn` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use a new generic type parameter, constrained by `A` + | +LL | trait B { fn f(a: T) -> A; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait B { fn f(a: impl A) -> A; } + | ++++ + +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/avoid-ice-on-warning-3.rs:1:19 + | +LL | trait B { fn f(a: A) -> A; } + | ^ `A` 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/avoid-ice-on-warning-3.rs:9:14 + | +LL | trait A { fn g(b: B) -> B; } + | - ^ ...because associated function `g` has no `self` parameter + | | + | this trait cannot be made into an object... +help: consider turning `g` into a method by giving it a `&self` argument + | +LL | trait A { fn g(&self, b: B) -> B; } + | ++++++ +help: alternatively, consider constraining `g` so it does not apply to trait objects + | +LL | trait A { fn g(b: B) -> B where Self: Sized; } + | +++++++++++++++++ + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning-3.rs:9:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `B` it is not object safe, so it can't be `dyn` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use a new generic type parameter, constrained by `B` + | +LL | trait A { fn g(b: T) -> B; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait A { fn g(b: impl B) -> B; } + | ++++ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/avoid-ice-on-warning-3.rs:9:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ `B` 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/avoid-ice-on-warning-3.rs:1:14 + | +LL | trait B { fn f(a: A) -> A; } + | - ^ ...because associated function `f` has no `self` parameter + | | + | this trait cannot be made into an object... +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | trait B { fn f(&self, a: A) -> A; } + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | trait B { fn f(a: A) -> A where Self: Sized; } + | +++++++++++++++++ + +error: aborting due to 2 previous errors; 6 warnings emitted + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning.rs b/tests/ui/object-safety/avoid-ice-on-warning.rs new file mode 100644 index 0000000000000..d2a1eeb5286b0 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning.rs @@ -0,0 +1,6 @@ +fn call_this(f: F) : Fn(&str) + call_that {} +//~^ ERROR return types are denoted using `->` +//~| ERROR cannot find trait `call_that` in this scope +//~| WARN trait objects without an explicit `dyn` are deprecated +//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning.stderr b/tests/ui/object-safety/avoid-ice-on-warning.stderr new file mode 100644 index 0000000000000..1046f177e8296 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning.stderr @@ -0,0 +1,29 @@ +error: return types are denoted using `->` + --> $DIR/avoid-ice-on-warning.rs:1:23 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^ help: use `->` instead + +error[E0405]: cannot find trait `call_that` in this scope + --> $DIR/avoid-ice-on-warning.rs:1:36 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^ not found in this scope + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/avoid-ice-on-warning.rs:1:25 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` on by default +help: `Fn(&str) + call_that` is not object safe, use `impl Fn(&str) + call_that` to return an opaque type, as long as you return a single underlying type + | +LL | fn call_this(f: F) : impl Fn(&str) + call_that {} + | ++++ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs index 7b92698c25e8a..c86e61a61a725 100644 --- a/tests/ui/offset-of/offset-of-arg-count.rs +++ b/tests/ui/offset-of/offset-of-arg-count.rs @@ -1,5 +1,3 @@ -#![feature(offset_of)] - use std::mem::offset_of; fn main() { diff --git a/tests/ui/offset-of/offset-of-arg-count.stderr b/tests/ui/offset-of/offset-of-arg-count.stderr index af0d42de30d60..4cb24b3d034b6 100644 --- a/tests/ui/offset-of/offset-of-arg-count.stderr +++ b/tests/ui/offset-of/offset-of-arg-count.stderr @@ -1,5 +1,5 @@ error: unexpected end of macro invocation - --> $DIR/offset-of-arg-count.rs:6:34 + --> $DIR/offset-of-arg-count.rs:4:34 | LL | offset_of!(NotEnoughArguments); | ^ missing tokens in macro arguments @@ -8,7 +8,7 @@ note: while trying to match `,` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error: unexpected end of macro invocation - --> $DIR/offset-of-arg-count.rs:7:45 + --> $DIR/offset-of-arg-count.rs:5:45 | LL | offset_of!(NotEnoughArgumentsWithAComma, ); | ^ missing tokens in macro arguments @@ -17,7 +17,7 @@ note: while trying to match meta-variable `$fields:expr` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error: no rules expected the token `too` - --> $DIR/offset-of-arg-count.rs:8:34 + --> $DIR/offset-of-arg-count.rs:6:34 | LL | offset_of!(Container, field, too many arguments); | ^^^ no rules expected this token in macro call @@ -25,25 +25,25 @@ LL | offset_of!(Container, field, too many arguments); = note: while trying to match sequence end error: unexpected token: `)` - --> $DIR/offset-of-arg-count.rs:11:21 + --> $DIR/offset-of-arg-count.rs:9:21 | LL | offset_of!(S, f.); | ^ error: unexpected token: `,` - --> $DIR/offset-of-arg-count.rs:12:21 + --> $DIR/offset-of-arg-count.rs:10:21 | LL | offset_of!(S, f.,); | ^ error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-arg-count.rs:13:19 + --> $DIR/offset-of-arg-count.rs:11:19 | LL | offset_of!(S, f..); | ^^^ error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-arg-count.rs:14:19 + --> $DIR/offset-of-arg-count.rs:12:19 | LL | offset_of!(S, f..,); | ^^^ diff --git a/tests/ui/offset-of/offset-of-dst-field.rs b/tests/ui/offset-of/offset-of-dst-field.rs index e393b159e64d5..016ebfadd1420 100644 --- a/tests/ui/offset-of/offset-of-dst-field.rs +++ b/tests/ui/offset-of/offset-of-dst-field.rs @@ -1,4 +1,4 @@ -#![feature(offset_of, extern_types)] +#![feature(extern_types)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs index a2d6aace47da1..cb2f04786ac5c 100644 --- a/tests/ui/offset-of/offset-of-enum.rs +++ b/tests/ui/offset-of/offset-of-enum.rs @@ -1,4 +1,4 @@ -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-inference.rs b/tests/ui/offset-of/offset-of-inference.rs index ba87574eae047..1b1ae25e1ee65 100644 --- a/tests/ui/offset-of/offset-of-inference.rs +++ b/tests/ui/offset-of/offset-of-inference.rs @@ -1,7 +1,5 @@ // Test that inference types in `offset_of!` don't ICE. -#![feature(offset_of)] - struct Foo { x: T, } diff --git a/tests/ui/offset-of/offset-of-inference.stderr b/tests/ui/offset-of/offset-of-inference.stderr index 1845822f11db1..8bd104ed7e277 100644 --- a/tests/ui/offset-of/offset-of-inference.stderr +++ b/tests/ui/offset-of/offset-of-inference.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/offset-of-inference.rs:10:35 + --> $DIR/offset-of-inference.rs:8:35 | LL | let _ = core::mem::offset_of!(Foo<_>, x); | ^^^^^^ cannot infer type diff --git a/tests/ui/offset-of/offset-of-must-use.rs b/tests/ui/offset-of/offset-of-must-use.rs index e30145d7a2fe3..e4b092fcedf3b 100644 --- a/tests/ui/offset-of/offset-of-must-use.rs +++ b/tests/ui/offset-of/offset-of-must-use.rs @@ -1,6 +1,5 @@ // check-pass -#![feature(offset_of)] #![warn(unused)] fn main() { diff --git a/tests/ui/offset-of/offset-of-must-use.stderr b/tests/ui/offset-of/offset-of-must-use.stderr index 5fe387a72553c..b6d88e098d00c 100644 --- a/tests/ui/offset-of/offset-of-must-use.stderr +++ b/tests/ui/offset-of/offset-of-must-use.stderr @@ -1,11 +1,11 @@ warning: unused return value of `must_use` that must be used - --> $DIR/offset-of-must-use.rs:7:5 + --> $DIR/offset-of-must-use.rs:6:5 | LL | core::mem::offset_of!((String,), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/offset-of-must-use.rs:4:9 + --> $DIR/offset-of-must-use.rs:3:9 | LL | #![warn(unused)] | ^^^^^^ diff --git a/tests/ui/offset-of/offset-of-output-type.rs b/tests/ui/offset-of/offset-of-output-type.rs index 50c2e93841f9f..76a33154ba3d1 100644 --- a/tests/ui/offset-of/offset-of-output-type.rs +++ b/tests/ui/offset-of/offset-of-output-type.rs @@ -1,5 +1,3 @@ -#![feature(offset_of)] - use std::mem::offset_of; struct S { diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr index 233d49876436a..34ad931d0caac 100644 --- a/tests/ui/offset-of/offset-of-output-type.stderr +++ b/tests/ui/offset-of/offset-of-output-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:12:17 + --> $DIR/offset-of-output-type.rs:10:17 | LL | let _: u8 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u8`, found `usize` @@ -7,7 +7,7 @@ LL | let _: u8 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:13:18 + --> $DIR/offset-of-output-type.rs:11:18 | LL | let _: u16 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u16`, found `usize` @@ -15,7 +15,7 @@ LL | let _: u16 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:14:18 + --> $DIR/offset-of-output-type.rs:12:18 | LL | let _: u32 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u32`, found `usize` @@ -23,7 +23,7 @@ LL | let _: u32 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:15:18 + --> $DIR/offset-of-output-type.rs:13:18 | LL | let _: u64 = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `u64`, found `usize` @@ -31,7 +31,7 @@ LL | let _: u64 = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:16:20 + --> $DIR/offset-of-output-type.rs:14:20 | LL | let _: isize = offset_of!(S, v); | ^^^^^^^^^^^^^^^^ expected `isize`, found `usize` @@ -39,7 +39,7 @@ LL | let _: isize = offset_of!(S, v); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/offset-of-output-type.rs:19:5 + --> $DIR/offset-of-output-type.rs:17:5 | LL | fn main() { | - expected `()` because of default return type diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs index b7affdb794395..1c326b5c79a5e 100644 --- a/tests/ui/offset-of/offset-of-private.rs +++ b/tests/ui/offset-of/offset-of-private.rs @@ -1,4 +1,4 @@ -#![feature(offset_of, offset_of_enum)] +#![feature(offset_of_enum, offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs index 04dcaf7c0a6b6..1558e13b53095 100644 --- a/tests/ui/offset-of/offset-of-self.rs +++ b/tests/ui/offset-of/offset-of-self.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-tuple-nested.rs b/tests/ui/offset-of/offset-of-tuple-nested.rs index 59b02e3c5c433..212176b24271a 100644 --- a/tests/ui/offset-of/offset-of-tuple-nested.rs +++ b/tests/ui/offset-of/offset-of-tuple-nested.rs @@ -2,7 +2,7 @@ // Test for issue #112204 -- make sure this goes through the entire compilation pipeline, // similar to why `offset-of-unsized.rs` is also build-pass -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs index b6fc1e32229a1..75ba8d77f2fbd 100644 --- a/tests/ui/offset-of/offset-of-tuple.rs +++ b/tests/ui/offset-of/offset-of-tuple.rs @@ -1,4 +1,4 @@ -#![feature(offset_of)] +#![feature(offset_of_nested)] #![feature(builtin_syntax)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-unsized.rs b/tests/ui/offset-of/offset-of-unsized.rs index 49c8328da5c55..b70529ed7b85e 100644 --- a/tests/ui/offset-of/offset-of-unsized.rs +++ b/tests/ui/offset-of/offset-of-unsized.rs @@ -2,8 +2,6 @@ // regression test for #112051, not in `offset-of-dst` as the issue is in codegen, // and isn't triggered in the presence of typeck errors -#![feature(offset_of)] - struct S { a: u64, b: T, diff --git a/tests/ui/offset-of/offset-of-unstable-with-feature.rs b/tests/ui/offset-of/offset-of-unstable-with-feature.rs index 7d2eb46c056eb..be275564a0a4f 100644 --- a/tests/ui/offset-of/offset-of-unstable-with-feature.rs +++ b/tests/ui/offset-of/offset-of-unstable-with-feature.rs @@ -1,7 +1,7 @@ // check-pass // aux-build:offset-of-staged-api.rs -#![feature(offset_of, unstable_test_feature)] +#![feature(offset_of_nested, unstable_test_feature)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-unstable.rs b/tests/ui/offset-of/offset-of-unstable.rs index 1e19f2091f29f..da0882abd2286 100644 --- a/tests/ui/offset-of/offset-of-unstable.rs +++ b/tests/ui/offset-of/offset-of-unstable.rs @@ -1,6 +1,6 @@ // aux-build:offset-of-staged-api.rs -#![feature(offset_of)] +#![feature(offset_of_nested)] use std::mem::offset_of; diff --git a/tests/ui/single-use-lifetime/issue-117965.rs b/tests/ui/single-use-lifetime/issue-117965.rs new file mode 100644 index 0000000000000..5eb2a03e13da4 --- /dev/null +++ b/tests/ui/single-use-lifetime/issue-117965.rs @@ -0,0 +1,18 @@ +#![deny(single_use_lifetimes)] + +pub enum Data<'a> { + Borrowed(&'a str), + Owned(String), +} + +impl<'a> Data<'a> { + pub fn get<'b: 'a>(&'b self) -> &'a str { + //~^ ERROR lifetime parameter `'b` only used once + match &self { + Self::Borrowed(val) => val, + Self::Owned(val) => &val, + } + } +} + +fn main() {} diff --git a/tests/ui/single-use-lifetime/issue-117965.stderr b/tests/ui/single-use-lifetime/issue-117965.stderr new file mode 100644 index 0000000000000..ed14ab92f4d16 --- /dev/null +++ b/tests/ui/single-use-lifetime/issue-117965.stderr @@ -0,0 +1,16 @@ +error: lifetime parameter `'b` only used once + --> $DIR/issue-117965.rs:9:16 + | +LL | pub fn get<'b: 'a>(&'b self) -> &'a str { + | ^^ -- ...is used only here + | | + | this lifetime... + | +note: the lint level is defined here + --> $DIR/issue-117965.rs:1:9 + | +LL | #![deny(single_use_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs new file mode 100644 index 0000000000000..f48c3d124ddac --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs @@ -0,0 +1,23 @@ +// edition:2021 +#![allow(bare_trait_objects)] +trait A: Sized { + fn f(a: A) -> A; + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword + //~| ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `A` cannot be made into an object +} +trait B { + fn f(a: B) -> B; + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword + //~| ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `B` cannot be made into an object +} +trait C { + fn f(&self, a: C) -> C; + //~^ ERROR trait objects must include the `dyn` keyword + //~| ERROR trait objects must include the `dyn` keyword +} + +fn main() {} diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr new file mode 100644 index 0000000000000..73d5a24f83137 --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr @@ -0,0 +1,168 @@ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + | +LL | trait A: Sized { + | - in this trait +LL | fn f(a: A) -> A; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + | +LL | fn f(a: A) -> A; + | ^ `A` 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/object-unsafe-trait-should-use-self-2021-without-dyn.rs:3:10 + | +LL | trait A: Sized { + | - ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + | +LL | trait B { + | - in this trait +LL | fn f(a: B) -> B; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + | +LL | fn f(a: B) -> B; + | ^ `B` 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/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:8 + | +LL | trait B { + | - this trait cannot be made into an object... +LL | fn f(a: B) -> B; + | ^ ...because associated function `f` has no `self` parameter +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | fn f(&self, a: B) -> B; + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | fn f(a: B) -> B where Self: Sized; + | +++++++++++++++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + | +LL | fn f(a: A) -> A; + | ^ + | +help: use a new generic type parameter, constrained by `A` + | +LL | fn f(a: T) -> A; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl A) -> A; + | ++++ +help: alternatively, use a trait object to accept any type that implements `A`, accessing its methods at runtime using dynamic dispatch + | +LL | fn f(a: &dyn A) -> A; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:19 + | +LL | fn f(a: A) -> A; + | ^ + | +help: use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: A) -> impl A; + | ++++ +help: alternatively, you can return an owned trait object + | +LL | fn f(a: A) -> Box; + | +++++++ + + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + | +LL | fn f(a: B) -> B; + | ^ + | +help: use a new generic type parameter, constrained by `B` + | +LL | fn f(a: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl B) -> B; + | ++++ +help: alternatively, use a trait object to accept any type that implements `B`, accessing its methods at runtime using dynamic dispatch + | +LL | fn f(a: &dyn B) -> B; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19 + | +LL | fn f(a: B) -> B; + | ^ + | +help: use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: B) -> impl B; + | ++++ +help: alternatively, you can return an owned trait object + | +LL | fn f(a: B) -> Box; + | +++++++ + + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 + | +LL | fn f(&self, a: C) -> C; + | ^ + | +help: use a new generic type parameter, constrained by `C` + | +LL | fn f(&self, a: T) -> C; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(&self, a: impl C) -> C; + | ++++ +help: alternatively, use a trait object to accept any type that implements `C`, accessing its methods at runtime using dynamic dispatch + | +LL | fn f(&self, a: &dyn C) -> C; + | ++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26 + | +LL | fn f(&self, a: C) -> C; + | ^ + | +help: use `impl C` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(&self, a: C) -> impl C; + | ++++ +help: alternatively, you can return an owned trait object + | +LL | fn f(&self, a: C) -> Box; + | +++++++ + + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0038, E0782. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs new file mode 100644 index 0000000000000..a598e883f3fdd --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs @@ -0,0 +1,17 @@ +// edition:2021 +#![allow(bare_trait_objects)] +trait A: Sized { + fn f(a: dyn A) -> dyn A; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `A` cannot be made into an object +} +trait B { + fn f(a: dyn B) -> dyn B; + //~^ ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `B` cannot be made into an object +} +trait C { + fn f(&self, a: dyn C) -> dyn C; +} + +fn main() {} diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr new file mode 100644 index 0000000000000..d6376be9c046c --- /dev/null +++ b/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr @@ -0,0 +1,65 @@ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13 + | +LL | trait A: Sized { + | - in this trait +LL | fn f(a: dyn A) -> dyn A; + | ^^^^^ ^^^^^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13 + | +LL | fn f(a: dyn A) -> dyn A; + | ^^^^^ `A` 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/object-unsafe-trait-should-use-self-2021.rs:3:10 + | +LL | trait A: Sized { + | - ^^^^^ ...because it requires `Self: Sized` + | | + | this trait cannot be made into an object... + +error: associated item referring to unboxed trait object for its own trait + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13 + | +LL | trait B { + | - in this trait +LL | fn f(a: dyn B) -> dyn B; + | ^^^^^ ^^^^^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL | fn f(a: Self) -> Self; + | ~~~~ ~~~~ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13 + | +LL | fn f(a: dyn B) -> dyn B; + | ^^^^^ `B` 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/object-unsafe-trait-should-use-self-2021.rs:9:8 + | +LL | trait B { + | - this trait cannot be made into an object... +LL | fn f(a: dyn B) -> dyn B; + | ^ ...because associated function `f` has no `self` parameter +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | fn f(&self, a: dyn B) -> dyn B; + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | fn f(a: dyn B) -> dyn B where Self: Sized; + | +++++++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0038`.