diff --git a/Cargo.lock b/Cargo.lock index 150a70341f585..844cf99b4688d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4348,6 +4348,7 @@ dependencies = [ "rustc_span", "rustc_target", "smallvec", + "termize", "tracing", "winapi", ] diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 07558ca075d3c..4fa18907fcd46 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -259,6 +259,8 @@ enum ImplTraitContext { }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, + /// `impl Trait` is unstably accepted in this position. + FeatureGated(ImplTraitPosition, Symbol), /// `impl Trait` is not accepted in this position. Disallowed(ImplTraitPosition), } @@ -1372,17 +1374,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } path } - ImplTraitContext::Disallowed( - position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn), - ) => { + ImplTraitContext::FeatureGated(position, feature) => { self.tcx .sess .create_feature_err( MisplacedImplTrait { span: t.span, - position: DiagnosticArgFromDisplay(&position), + position: DiagnosticArgFromDisplay(position), }, - sym::return_position_impl_trait_in_trait, + *feature, ) .emit(); hir::TyKind::Err @@ -1390,7 +1390,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed(position) => { self.tcx.sess.emit_err(MisplacedImplTrait { span: t.span, - position: DiagnosticArgFromDisplay(&position), + position: DiagnosticArgFromDisplay(position), }); hir::TyKind::Err } @@ -1739,14 +1739,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { match &decl.output { FnRetTy::Ty(ty) => { - let mut context = if kind.return_impl_trait_allowed(self.tcx) { + let context = if kind.return_impl_trait_allowed(self.tcx) { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), in_trait: matches!(kind, FnDeclKind::Trait), } } else { - ImplTraitContext::Disallowed(match kind { + let position = match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { unreachable!("fn should allow in-band lifetimes") } @@ -1755,9 +1755,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnDeclKind::Pointer => ImplTraitPosition::PointerReturn, FnDeclKind::Trait => ImplTraitPosition::TraitReturn, FnDeclKind::Impl => ImplTraitPosition::ImplReturn, - }) + }; + match kind { + FnDeclKind::Trait | FnDeclKind::Impl => ImplTraitContext::FeatureGated( + position, + sym::return_position_impl_trait_in_trait, + ), + _ => ImplTraitContext::Disallowed(position), + } }; - hir::FnRetTy::Return(self.lower_ty(ty, &mut context)) + hir::FnRetTy::Return(self.lower_ty(ty, &context)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)), } @@ -1938,7 +1945,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { output, span, if in_trait && !this.tcx.features().return_position_impl_trait_in_trait { - ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn) + ImplTraitContext::FeatureGated( + ImplTraitPosition::TraitReturn, + sym::return_position_impl_trait_in_trait, + ) } else { ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 8d23c26e603b7..592fc5aa6456f 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -9,7 +9,7 @@ use rustc_ast::{self as ast, *}; use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::GenericArg; -use rustc_span::symbol::{kw, Ident}; +use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; @@ -352,11 +352,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug // // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^ // ``` - FnRetTy::Ty(ty) - if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) - && self.tcx.features().impl_trait_in_fn_trait_return => - { - self.lower_ty(&ty, itctx) + FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => { + if self.tcx.features().impl_trait_in_fn_trait_return { + self.lower_ty(&ty, itctx) + } else { + self.lower_ty( + &ty, + &ImplTraitContext::FeatureGated( + ImplTraitPosition::FnTraitReturn, + sym::impl_trait_in_fn_trait_return, + ), + ) + } } FnRetTy::Ty(ty) => { self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 540f15c89e928..882430694e16d 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -102,7 +102,7 @@ pub fn link_binary<'a>( sess, crate_type, outputs, - codegen_results.crate_info.local_crate_name.as_str(), + codegen_results.crate_info.local_crate_name, ); match crate_type { CrateType::Rlib => { diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 88d25be6bd861..0604d5ee6fa4c 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -373,9 +373,21 @@ pub trait Machine<'mir, 'tcx>: Sized { Ok(()) } - /// Executes a retagging operation. + /// Executes a retagging operation for a single pointer. + /// Returns the possibly adjusted pointer. #[inline] - fn retag( + fn retag_ptr_value( + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _kind: mir::RetagKind, + val: &ImmTy<'tcx, Self::Provenance>, + ) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> { + Ok(val.clone()) + } + + /// Executes a retagging operation on a compound value. + /// Replaces all pointers stored in the given place. + #[inline] + fn retag_place_contents( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _kind: mir::RetagKind, _place: &PlaceTy<'tcx, Self::Provenance>, diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 60578246eedcc..81b44a49484d0 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -8,7 +8,7 @@ use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::ty::layout::LayoutOf; -use super::{InterpCx, Machine}; +use super::{ImmTy, InterpCx, Machine}; /// Classify whether an operator is "left-homogeneous", i.e., the LHS has the /// same type as the result. @@ -108,7 +108,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Stacked Borrows. Retag(kind, place) => { let dest = self.eval_place(**place)?; - M::retag(self, *kind, &dest)?; + M::retag_place_contents(self, *kind, &dest)?; } Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?, @@ -247,10 +247,41 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?; } - AddressOf(_, place) | Ref(_, _, place) => { + Ref(_, borrow_kind, place) => { let src = self.eval_place(place)?; let place = self.force_allocation(&src)?; - self.write_immediate(place.to_ref(self), &dest)?; + let val = ImmTy::from_immediate(place.to_ref(self), dest.layout); + // A fresh reference was created, make sure it gets retagged. + let val = M::retag_ptr_value( + self, + if borrow_kind.allows_two_phase_borrow() { + mir::RetagKind::TwoPhase + } else { + mir::RetagKind::Default + }, + &val, + )?; + self.write_immediate(*val, &dest)?; + } + + AddressOf(_, place) => { + // Figure out whether this is an addr_of of an already raw place. + let place_base_raw = if place.has_deref() { + let ty = self.frame().body.local_decls[place.local].ty; + ty.is_unsafe_ptr() + } else { + // Not a deref, and thus not raw. + false + }; + + let src = self.eval_place(place)?; + let place = self.force_allocation(&src)?; + let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout); + if !place_base_raw { + // If this was not already raw, it needs retagging. + val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?; + } + self.write_immediate(*val, &dest)?; } NullaryOp(null_op, ty) => { diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 22f87514dd8fa..f06ca5a0733a5 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -25,6 +25,7 @@ use rustc_data_structures::sync::SeqCst; use rustc_errors::registry::{InvalidErrorCode, Registry}; use rustc_errors::{ErrorGuaranteed, PResult}; use rustc_feature::find_gated_cfg; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; @@ -374,14 +375,14 @@ fn run_compiler( queries.global_ctxt()?.peek_mut().enter(|tcx| { let result = tcx.analysis(()); if sess.opts.unstable_opts.save_analysis { - let crate_name = queries.crate_name()?.peek().clone(); + let crate_name = tcx.crate_name(LOCAL_CRATE); sess.time("save_analysis", || { save::process_crate( tcx, - &crate_name, + crate_name, compiler.input(), None, - DumpHandler::new(compiler.output_dir().as_deref(), &crate_name), + DumpHandler::new(compiler.output_dir().as_deref(), crate_name), ) }); } @@ -678,7 +679,7 @@ fn print_crate_info( let crate_types = collect_crate_types(sess, attrs); for &style in &crate_types { let fname = - rustc_session::output::filename_for_input(sess, style, &id, &t_outputs); + rustc_session::output::filename_for_input(sess, style, id, &t_outputs); println!("{}", fname.file_name().unwrap().to_string_lossy()); } } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 13e2d1ebbe786..9d6a4f9a1fd7d 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -960,7 +960,7 @@ pub trait LintStoreExpand { node_id: NodeId, attrs: &[Attribute], items: &[P], - name: &str, + name: Symbol, ); } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e799fa404f6fd..1014ec2209c61 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1122,7 +1122,7 @@ impl InvocationCollectorNode for P { ecx.current_expansion.lint_node_id, &attrs, &items, - ident.name.as_str(), + ident.name, ); } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 636e6e1b48d0e..8bc022e1e178e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -827,7 +827,7 @@ impl<'tcx> AttributeMap<'tcx> { pub struct OwnerNodes<'tcx> { /// Pre-computed hash of the full HIR. pub hash_including_bodies: Fingerprint, - /// Pre-computed hash of the item signature, sithout recursing into the body. + /// Pre-computed hash of the item signature, without recursing into the body. pub hash_without_bodies: Fingerprint, /// Full HIR for the current owner. // The zeroth node's parent should never be accessed: the owner's parent is computed by the diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs index 4636d515249d9..d4791150947fb 100644 --- a/compiler/rustc_hir/src/tests.rs +++ b/compiler/rustc_hir/src/tests.rs @@ -1,5 +1,7 @@ use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData}; use rustc_span::def_id::{DefPathHash, StableCrateId}; +use rustc_span::edition::Edition; +use rustc_span::{create_session_if_not_set_then, Symbol}; #[test] fn def_path_hash_depends_on_crate_id() { @@ -11,26 +13,28 @@ fn def_path_hash_depends_on_crate_id() { // the crate by changing the crate disambiguator (e.g. via bumping the // crate's version number). - let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]); - let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]); + create_session_if_not_set_then(Edition::Edition2024, |_| { + let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]); + let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]); - let h0 = mk_test_hash(id0); - let h1 = mk_test_hash(id1); + let h0 = mk_test_hash(id0); + let h1 = mk_test_hash(id1); - assert_ne!(h0.stable_crate_id(), h1.stable_crate_id()); - assert_ne!(h0.local_hash(), h1.local_hash()); + assert_ne!(h0.stable_crate_id(), h1.stable_crate_id()); + assert_ne!(h0.local_hash(), h1.local_hash()); - fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash { - let parent_hash = DefPathHash::new(stable_crate_id, 0); + fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash { + let parent_hash = DefPathHash::new(stable_crate_id, 0); - let key = DefKey { - parent: None, - disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::CrateRoot, - disambiguator: 0, - }, - }; + let key = DefKey { + parent: None, + disambiguated_data: DisambiguatedDefPathData { + data: DefPathData::CrateRoot, + disambiguator: 0, + }, + }; - key.compute_stable_hash(parent_hash) - } + key.compute_stable_hash(parent_hash) + } + }) } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 639f81f20bfb9..0a7e25300cba8 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -4,7 +4,6 @@ use hir::{ GenericParamKind, HirId, Node, }; use rustc_hir as hir; -use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint; @@ -143,20 +142,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Some(tcx.typeck_root_def_id(def_id)) } Node::Item(item) => match item.kind { - ItemKind::OpaqueTy(hir::OpaqueTy { - origin: - hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id), - in_trait, - .. - }) => { - if in_trait { - assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn)) - } else { - assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn)) - } - Some(fn_def_id.to_def_id()) - } - ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { + ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => { let parent_id = tcx.hir().get_parent_item(hir_id); assert_ne!(parent_id, hir::CRATE_OWNER_ID); debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 0c9a350c295f4..32f86b8042c11 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -1,7 +1,7 @@ use crate::coercion::CoerceMany; use crate::gather_locals::GatherLocalsVisitor; use crate::FnCtxt; -use crate::{GeneratorTypes, UnsafetyState}; +use crate::GeneratorTypes; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::intravisit::Visitor; @@ -30,7 +30,6 @@ pub(super) fn check_fn<'a, 'tcx>( can_be_generator: Option, ) -> Option> { let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id); - fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id)); let tcx = fcx.tcx; let hir = tcx.hir(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 8a875e05b19b7..60fec05d36d6d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1393,8 +1393,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { blk: &'tcx hir::Block<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - let prev = self.ps.replace(self.ps.get().recurse(blk)); - // In some cases, blocks have just one exit, but other blocks // can be targeted by multiple breaks. This can happen both // with labeled blocks as well as when we desugar @@ -1558,7 +1556,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.write_ty(blk.hir_id, ty); - self.ps.set(prev); ty } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 1e9b575213085..30b59da7852d4 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -8,7 +8,7 @@ use rustc_errors::ErrorGuaranteed; pub use suggestions::*; use crate::coercion::DynamicCoerceMany; -use crate::{Diverges, EnclosingBreakables, Inherited, UnsafetyState}; +use crate::{Diverges, EnclosingBreakables, Inherited}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir_analysis::astconv::AstConv; @@ -74,8 +74,6 @@ pub struct FnCtxt<'a, 'tcx> { pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>, - pub(super) ps: Cell, - /// Whether the last checked node generates a divergence (e.g., /// `return` will set this to `Always`). In general, when entering /// an expression or other node in the tree, the initial value @@ -129,7 +127,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ret_coercion: None, ret_coercion_span: Cell::new(None), resume_yield_tys: None, - ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)), diverges: Cell::new(Diverges::Maybe), enclosing_breakables: RefCell::new(EnclosingBreakables { stack: Vec::new(), diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 09bd123350dfd..5b2352cda34b3 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -89,38 +89,6 @@ pub struct LocalTy<'tcx> { revealed_ty: Ty<'tcx>, } -#[derive(Copy, Clone)] -pub struct UnsafetyState { - pub def: hir::HirId, - pub unsafety: hir::Unsafety, - from_fn: bool, -} - -impl UnsafetyState { - pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState { - UnsafetyState { def, unsafety, from_fn: true } - } - - pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState { - use hir::BlockCheckMode; - match self.unsafety { - // If this unsafe, then if the outer function was already marked as - // unsafe we shouldn't attribute the unsafe'ness to the block. This - // way the block can be warned about instead of ignoring this - // extraneous block (functions are never warned about). - hir::Unsafety::Unsafe if self.from_fn => self, - - unsafety => { - let (unsafety, def) = match blk.rules { - BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id), - BlockCheckMode::DefaultBlock => (unsafety, self.def), - }; - UnsafetyState { def, unsafety, from_fn: false } - } - } - } -} - /// If this `DefId` is a "primary tables entry", returns /// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`. /// diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 58d6e6d7efd69..97ebed0585579 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -109,6 +109,7 @@ use rustc_data_structures::{base_n, flock}; use rustc_errors::ErrorGuaranteed; use rustc_fs_util::{link_or_copy, LinkOrCopy}; use rustc_session::{Session, StableCrateId}; +use rustc_span::Symbol; use std::fs as std_fs; use std::io::{self, ErrorKind}; @@ -202,7 +203,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu /// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph pub fn prepare_session_directory( sess: &Session, - crate_name: &str, + crate_name: Symbol, stable_crate_id: StableCrateId, ) -> Result<(), ErrorGuaranteed> { if sess.opts.incremental.is_none() { @@ -657,7 +658,7 @@ fn string_to_timestamp(s: &str) -> Result { Ok(UNIX_EPOCH + duration) } -fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf { +fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf { let incr_dir = sess.opts.incremental.as_ref().unwrap().clone(); let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 3256ca1fb20fb..980a17e41e13f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -80,6 +80,7 @@ use rustc_middle::ty::{ use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; use std::ops::{ControlFlow, Deref}; +use std::path::PathBuf; use std::{cmp, fmt, iter}; mod note; @@ -1352,10 +1353,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .map(|(mod_str, _)| mod_str.len() + separator_len) .sum(); - debug!( - "cmp: separator_len={}, split_idx={}, min_len={}", - separator_len, split_idx, min_len - ); + debug!(?separator_len, ?split_idx, ?min_len, "cmp"); if split_idx >= min_len { // paths are identical, highlight everything @@ -1366,7 +1364,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } else { let (common, uniq1) = t1_str.split_at(split_idx); let (_, uniq2) = t2_str.split_at(split_idx); - debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2); + debug!(?common, ?uniq1, ?uniq2, "cmp"); values.0.push_normal(common); values.0.push_highlighted(uniq1); @@ -1659,17 +1657,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")), }; - let vals = match self.values_str(values) { - Some((expected, found)) => Some((expected, found)), - None => { - // Derived error. Cancel the emitter. - // NOTE(eddyb) this was `.cancel()`, but `diag` - // is borrowed, so we can't fully defuse it. - diag.downgrade_to_delayed_bug(); - return; - } + let Some(vals) = self.values_str(values) else { + // Derived error. Cancel the emitter. + // NOTE(eddyb) this was `.cancel()`, but `diag` + // is borrowed, so we can't fully defuse it. + diag.downgrade_to_delayed_bug(); + return; }; - (vals, exp_found, is_simple_error, Some(values)) + (Some(vals), exp_found, is_simple_error, Some(values)) } }; @@ -1701,7 +1696,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { label_or_note(span, &terr.to_string()); } - if let Some((expected, found)) = expected_found { + if let Some((expected, found, exp_p, found_p)) = expected_found { let (expected_label, found_label, exp_found) = match exp_found { Mismatch::Variable(ef) => ( ef.expected.prefix_string(self.tcx), @@ -1818,32 +1813,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } TypeError::Sorts(values) => { let extra = expected == found; - let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) { - (true, ty::Opaque(def_id, _)) => { - let sm = self.tcx.sess.source_map(); - let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo()); - format!( - " (opaque type at <{}:{}:{}>)", - sm.filename_for_diagnostics(&pos.file.name), - pos.line, - pos.col.to_usize() + 1, - ) - } - (true, ty::Projection(proj)) - if self.tcx.def_kind(proj.item_def_id) - == DefKind::ImplTraitPlaceholder => - { - let sm = self.tcx.sess.source_map(); - let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo()); - format!( - " (trait associated opaque type at <{}:{}:{}>)", - sm.filename_for_diagnostics(&pos.file.name), - pos.line, - pos.col.to_usize() + 1, - ) + let sort_string = |ty: Ty<'tcx>, path: Option| { + let mut s = match (extra, ty.kind()) { + (true, ty::Opaque(def_id, _)) => { + let sm = self.tcx.sess.source_map(); + let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo()); + format!( + " (opaque type at <{}:{}:{}>)", + sm.filename_for_diagnostics(&pos.file.name), + pos.line, + pos.col.to_usize() + 1, + ) + } + (true, ty::Projection(proj)) + if self.tcx.def_kind(proj.item_def_id) + == DefKind::ImplTraitPlaceholder => + { + let sm = self.tcx.sess.source_map(); + let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo()); + format!( + " (trait associated opaque type at <{}:{}:{}>)", + sm.filename_for_diagnostics(&pos.file.name), + pos.line, + pos.col.to_usize() + 1, + ) + } + (true, _) => format!(" ({})", ty.sort_string(self.tcx)), + (false, _) => "".to_string(), + }; + if let Some(path) = path { + s.push_str(&format!( + "\nthe full type name has been written to '{}'", + path.display(), + )); } - (true, _) => format!(" ({})", ty.sort_string(self.tcx)), - (false, _) => "".to_string(), + s }; if !(values.expected.is_simple_text() && values.found.is_simple_text()) || (exp_found.map_or(false, |ef| { @@ -1865,8 +1869,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { expected, &found_label, found, - &sort_string(values.expected), - &sort_string(values.found), + &sort_string(values.expected, exp_p), + &sort_string(values.found, found_p), ); } } @@ -2339,7 +2343,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let code = trace.cause.code(); if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code && let hir::MatchSource::TryDesugar = source - && let Some((expected_ty, found_ty)) = self.values_str(trace.values) + && let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values) { err.note(&format!( "`?` operator cannot convert from `{}` to `{}`", @@ -2455,7 +2459,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn values_str( &self, values: ValuePairs<'tcx>, - ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { + ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option, Option)> + { match values { infer::Regions(exp_found) => self.expected_found_str(exp_found), infer::Terms(exp_found) => self.expected_found_str_term(exp_found), @@ -2465,7 +2470,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { found: exp_found.found.print_only_trait_path(), }; match self.expected_found_str(pretty_exp_found) { - Some((expected, found)) if expected == found => { + Some((expected, found, _, _)) if expected == found => { self.expected_found_str(exp_found) } ret => ret, @@ -2477,7 +2482,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { found: exp_found.found.print_only_trait_path(), }; match self.expected_found_str(pretty_exp_found) { - Some((expected, found)) if expected == found => { + Some((expected, found, _, _)) if expected == found => { self.expected_found_str(exp_found) } ret => ret, @@ -2489,17 +2494,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn expected_found_str_term( &self, exp_found: ty::error::ExpectedFound>, - ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { + ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option, Option)> + { let exp_found = self.resolve_vars_if_possible(exp_found); if exp_found.references_error() { return None; } Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) { - (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => self.cmp(expected, found), + (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => { + let (mut exp, mut fnd) = self.cmp(expected, found); + // Use the terminal width as the basis to determine when to compress the printed + // out type, but give ourselves some leeway to avoid ending up creating a file for + // a type that is somewhat shorter than the path we'd write to. + let len = self.tcx.sess().diagnostic_width() + 40; + let exp_s = exp.content(); + let fnd_s = fnd.content(); + let mut exp_p = None; + let mut fnd_p = None; + if exp_s.len() > len { + let (exp_s, exp_path) = self.tcx.short_ty_string(expected); + exp = DiagnosticStyledString::highlighted(exp_s); + exp_p = exp_path; + } + if fnd_s.len() > len { + let (fnd_s, fnd_path) = self.tcx.short_ty_string(found); + fnd = DiagnosticStyledString::highlighted(fnd_s); + fnd_p = fnd_path; + } + (exp, fnd, exp_p, fnd_p) + } _ => ( DiagnosticStyledString::highlighted(exp_found.expected.to_string()), DiagnosticStyledString::highlighted(exp_found.found.to_string()), + None, + None, ), }) } @@ -2508,7 +2537,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn expected_found_str>( &self, exp_found: ty::error::ExpectedFound, - ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { + ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option, Option)> + { let exp_found = self.resolve_vars_if_possible(exp_found); if exp_found.references_error() { return None; @@ -2517,6 +2547,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { Some(( DiagnosticStyledString::highlighted(exp_found.expected.to_string()), DiagnosticStyledString::highlighted(exp_found.found.to_string()), + None, + None, )) } @@ -2850,36 +2882,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { debug!("report_sub_sup_conflict: sup_region={:?}", sup_region); debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin); - if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) = - (&sup_origin, &sub_origin) + if let infer::Subtype(ref sup_trace) = sup_origin + && let infer::Subtype(ref sub_trace) = sub_origin + && let Some((sup_expected, sup_found, _, _)) = self.values_str(sup_trace.values) + && let Some((sub_expected, sub_found, _, _)) = self.values_str(sub_trace.values) + && sub_expected == sup_expected + && sub_found == sup_found { - debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace); - debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace); - debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values); - debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values); - - if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) = - (self.values_str(sup_trace.values), self.values_str(sub_trace.values)) - { - if sub_expected == sup_expected && sub_found == sup_found { - note_and_explain_region( - self.tcx, - &mut err, - "...but the lifetime must also be valid for ", - sub_region, - "...", - None, - ); - err.span_note( - sup_trace.cause.span, - &format!("...so that the {}", sup_trace.cause.as_requirement_str()), - ); + note_and_explain_region( + self.tcx, + &mut err, + "...but the lifetime must also be valid for ", + sub_region, + "...", + None, + ); + err.span_note( + sup_trace.cause.span, + &format!("...so that the {}", sup_trace.cause.as_requirement_str()), + ); - err.note_expected_found(&"", sup_expected, &"", sup_found); - err.emit(); - return; - } - } + err.note_expected_found(&"", sup_expected, &"", sup_found); + err.emit(); + return; } self.note_region_origin(&mut err, &sup_origin); diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 41b115f3377ac..d2dffa4a0b78e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -16,7 +16,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { span: trace.cause.span, requirement: ObligationCauseAsDiagArg(trace.cause.clone()), - expected_found: self.values_str(trace.values), + expected_found: self.values_str(trace.values).map(|(e, f, _, _)| (e, f)), } .add_to_diagnostic(err), infer::Reborrow(span) => { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f75c8669fa1e1..f808c1438bfc5 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -158,7 +158,7 @@ pub fn create_resolver( sess: Lrc, metadata_loader: Box, krate: &ast::Crate, - crate_name: &str, + crate_name: Symbol, ) -> BoxedResolver { trace!("create_resolver"); BoxedResolver::new(sess, move |sess, resolver_arenas| { @@ -171,7 +171,7 @@ pub fn register_plugins<'a>( metadata_loader: &'a dyn MetadataLoader, register_lints: impl Fn(&Session, &mut LintStore), mut krate: ast::Crate, - crate_name: &str, + crate_name: Symbol, ) -> Result<(ast::Crate, LintStore)> { krate = sess.time("attributes_injection", || { rustc_builtin_macros::cmdline_attrs::inject( @@ -228,19 +228,21 @@ fn pre_expansion_lint<'a>( lint_store: &LintStore, registered_tools: &RegisteredTools, check_node: impl EarlyCheckNode<'a>, - node_name: &str, + node_name: Symbol, ) { - sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name).run(|| { - rustc_lint::check_ast_node( - sess, - true, - lint_store, - registered_tools, - None, - rustc_lint::BuiltinCombinedPreExpansionLintPass::new(), - check_node, - ); - }); + sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run( + || { + rustc_lint::check_ast_node( + sess, + true, + lint_store, + registered_tools, + None, + rustc_lint::BuiltinCombinedPreExpansionLintPass::new(), + check_node, + ); + }, + ); } // Cannot implement directly for `LintStore` due to trait coherence. @@ -254,7 +256,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { node_id: ast::NodeId, attrs: &[ast::Attribute], items: &[rustc_ast::ptr::P], - name: &str, + name: Symbol, ) { pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name); } @@ -268,7 +270,7 @@ pub fn configure_and_expand( sess: &Session, lint_store: &LintStore, mut krate: ast::Crate, - crate_name: &str, + crate_name: Symbol, resolver: &mut Resolver<'_>, ) -> Result { trace!("configure_and_expand"); @@ -462,7 +464,7 @@ fn generated_output_paths( sess: &Session, outputs: &OutputFilenames, exact_name: bool, - crate_name: &str, + crate_name: Symbol, ) -> Vec { let mut out_filenames = Vec::new(); for output_type in sess.opts.output_types.keys() { @@ -661,7 +663,7 @@ pub fn prepare_outputs( compiler: &Compiler, krate: &ast::Crate, boxed_resolver: &RefCell, - crate_name: &str, + crate_name: Symbol, ) -> Result { let _timer = sess.timer("prepare_outputs"); @@ -771,7 +773,7 @@ pub fn create_global_ctxt<'tcx>( dep_graph: DepGraph, resolver: Rc>, outputs: OutputFilenames, - crate_name: &str, + crate_name: Symbol, queries: &'tcx OnceCell>, global_ctxt: &'tcx OnceCell>, arena: &'tcx WorkerLocal>, diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index f5ddd647b2435..39e1f2204b002 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -17,6 +17,7 @@ use rustc_query_impl::Queries as TcxQueries; use rustc_session::config::{self, OutputFilenames, OutputType}; use rustc_session::{output::find_crate_name, Session}; use rustc_span::symbol::sym; +use rustc_span::Symbol; use std::any::Any; use std::cell::{Ref, RefCell, RefMut}; use std::rc::Rc; @@ -74,7 +75,7 @@ pub struct Queries<'tcx> { dep_graph_future: Query>, parse: Query, - crate_name: Query, + crate_name: Query, register_plugins: Query<(ast::Crate, Lrc)>, expansion: Query<(Lrc, Rc>, Lrc)>, dep_graph: Query, @@ -135,7 +136,7 @@ impl<'tcx> Queries<'tcx> { &*self.codegen_backend().metadata_loader(), self.compiler.register_lints.as_deref().unwrap_or_else(|| empty), krate, - &crate_name, + crate_name, )?; // Compute the dependency graph (in the background). We want to do @@ -149,7 +150,7 @@ impl<'tcx> Queries<'tcx> { }) } - pub fn crate_name(&self) -> Result<&Query> { + pub fn crate_name(&self) -> Result<&Query> { self.crate_name.compute(|| { Ok({ let parse_result = self.parse()?; @@ -165,7 +166,7 @@ impl<'tcx> Queries<'tcx> { ) -> Result<&Query<(Lrc, Rc>, Lrc)>> { trace!("expansion"); self.expansion.compute(|| { - let crate_name = self.crate_name()?.peek().clone(); + let crate_name = *self.crate_name()?.peek(); let (krate, lint_store) = self.register_plugins()?.take(); let _timer = self.session().timer("configure_and_expand"); let sess = self.session(); @@ -173,10 +174,10 @@ impl<'tcx> Queries<'tcx> { sess.clone(), self.codegen_backend().metadata_loader(), &krate, - &crate_name, + crate_name, ); let krate = resolver.access(|resolver| { - passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver) + passes::configure_and_expand(sess, &lint_store, krate, crate_name, resolver) })?; Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store)) }) @@ -201,20 +202,20 @@ impl<'tcx> Queries<'tcx> { pub fn prepare_outputs(&self) -> Result<&Query> { self.prepare_outputs.compute(|| { let (krate, boxed_resolver, _) = &*self.expansion()?.peek(); - let crate_name = self.crate_name()?.peek(); + let crate_name = *self.crate_name()?.peek(); passes::prepare_outputs( self.session(), self.compiler, krate, &*boxed_resolver, - &crate_name, + crate_name, ) }) } pub fn global_ctxt(&'tcx self) -> Result<&Query>> { self.global_ctxt.compute(|| { - let crate_name = self.crate_name()?.peek().clone(); + let crate_name = *self.crate_name()?.peek(); let outputs = self.prepare_outputs()?.take(); let dep_graph = self.dep_graph()?.peek().clone(); let (krate, resolver, lint_store) = self.expansion()?.take(); @@ -225,7 +226,7 @@ impl<'tcx> Queries<'tcx> { dep_graph, resolver, outputs, - &crate_name, + crate_name, &self.queries, &self.gcx, &self.arena, diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 1a2389c7a8448..efeaac8fe9a0f 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -245,7 +245,7 @@ impl<'a> CrateLoader<'a> { pub fn new( sess: &'a Session, metadata_loader: Box, - local_crate_name: &str, + local_crate_name: Symbol, ) -> Self { let mut stable_crate_ids = FxHashMap::default(); stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE); @@ -253,7 +253,7 @@ impl<'a> CrateLoader<'a> { CrateLoader { sess, metadata_loader, - local_crate_name: Symbol::intern(local_crate_name), + local_crate_name, cstore: CStore { // We add an empty entry for LOCAL_CRATE (which maps to zero) in // order to make array indices in `metas` match with the @@ -1000,7 +1000,7 @@ impl<'a> CrateLoader<'a> { ); let name = match orig_name { Some(orig_name) => { - validate_crate_name(self.sess, orig_name.as_str(), Some(item.span)); + validate_crate_name(self.sess, orig_name, Some(item.span)); orig_name } None => item.ident.name, diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 4fa440c7ca691..7601f6bd3221e 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -61,8 +61,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { .unwrap_or(MetadataKind::None); let crate_name = tcx.crate_name(LOCAL_CRATE); - let out_filename = - filename_for_metadata(tcx.sess, crate_name.as_str(), tcx.output_filenames(())); + let out_filename = filename_for_metadata(tcx.sess, crate_name, tcx.output_filenames(())); // To avoid races with another rustc process scanning the output directory, // we need to write the file somewhere else and atomically move it to its // final destination, with an `fs::rename` call. In order for the rename to diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 7d2a6bda56926..614e0d012b35a 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -400,7 +400,7 @@ impl std::fmt::Display for NonDivergingIntrinsic<'_> { #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] pub enum RetagKind { - /// The initial retag when entering a function. + /// The initial retag of arguments when entering a function. FnEntry, /// Retag preparing for a two-phase borrow. TwoPhase, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index af573376a26bc..b44bc14ec26c8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1285,7 +1285,7 @@ impl<'tcx> TyCtxt<'tcx> { on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, query_kinds: &'tcx [DepKindStruct<'tcx>], - crate_name: &str, + crate_name: Symbol, output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| { @@ -1325,7 +1325,7 @@ impl<'tcx> TyCtxt<'tcx> { pred_rcache: Default::default(), selection_cache: Default::default(), evaluation_cache: Default::default(), - crate_name: Symbol::intern(crate_name), + crate_name, data_layout, alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames), diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index d83e17574a094..aa61c39b8d819 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -986,23 +986,32 @@ fn foo(&self) -> Self::T { String::new() } } pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option) { - let length_limit = 50; - let type_limit = 4; + let width = self.sess.diagnostic_width(); + let length_limit = width.saturating_sub(30); + let mut type_limit = 50; let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS) .pretty_print_type(ty) .expect("could not write to `String`") .into_buffer(); - if regular.len() <= length_limit { + if regular.len() <= width { return (regular, None); } - let short = FmtPrinter::new_with_limit( - self, - hir::def::Namespace::TypeNS, - rustc_session::Limit(type_limit), - ) - .pretty_print_type(ty) - .expect("could not write to `String`") - .into_buffer(); + let mut short; + loop { + // Look for the longest properly trimmed path that still fits in lenght_limit. + short = FmtPrinter::new_with_limit( + self, + hir::def::Namespace::TypeNS, + rustc_session::Limit(type_limit), + ) + .pretty_print_type(ty) + .expect("could not write to `String`") + .into_buffer(); + if short.len() <= length_limit || type_limit == 0 { + break; + } + type_limit -= 1; + } if regular == short { return (regular, None); } diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 036b5589849a2..3d22035f0785e 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -10,16 +10,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct AddRetag; -/// Determines whether this place is "stable": Whether, if we evaluate it again -/// after the assignment, we can be sure to obtain the same place value. -/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic -/// copies. Data races are UB.) -fn is_stable(place: PlaceRef<'_>) -> bool { - // Which place this evaluates to can change with any memory write, - // so cannot assume deref to be stable. - !place.has_deref() -} - /// Determine whether this type may contain a reference (or box), and thus needs retagging. /// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this. fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool { @@ -69,22 +59,10 @@ impl<'tcx> MirPass<'tcx> for AddRetag { let basic_blocks = body.basic_blocks.as_mut(); let local_decls = &body.local_decls; let needs_retag = |place: &Place<'tcx>| { - // FIXME: Instead of giving up for unstable places, we should introduce - // a temporary and retag on that. - is_stable(place.as_ref()) + !place.has_deref() // we're not eally interested in stores to "outside" locations, they are hard to keep track of anyway && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx) && !local_decls[place.local].is_deref_temp() }; - let place_base_raw = |place: &Place<'tcx>| { - // If this is a `Deref`, get the type of what we are deref'ing. - if place.has_deref() { - let ty = &local_decls[place.local].ty; - ty.is_unsafe_ptr() - } else { - // Not a deref, and thus not raw. - false - } - }; // PART 1 // Retag arguments at the beginning of the start block. @@ -108,7 +86,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag { } // PART 2 - // Retag return values of functions. Also escape-to-raw the argument of `drop`. + // Retag return values of functions. // We collect the return destinations because we cannot mutate while iterating. let returns = basic_blocks .iter_mut() @@ -140,30 +118,25 @@ impl<'tcx> MirPass<'tcx> for AddRetag { } // PART 3 - // Add retag after assignment. + // Add retag after assignments where data "enters" this function: the RHS is behind a deref and the LHS is not. for block_data in basic_blocks { // We want to insert statements as we iterate. To this end, we // iterate backwards using indices. for i in (0..block_data.statements.len()).rev() { let (retag_kind, place) = match block_data.statements[i].kind { - // Retag-as-raw after escaping to a raw pointer, if the referent - // is not already a raw pointer. - StatementKind::Assign(box (lplace, Rvalue::AddressOf(_, ref rplace))) - if !place_base_raw(rplace) => - { - (RetagKind::Raw, lplace) - } // Retag after assignments of reference type. StatementKind::Assign(box (ref place, ref rvalue)) if needs_retag(place) => { - let kind = match rvalue { - Rvalue::Ref(_, borrow_kind, _) - if borrow_kind.allows_two_phase_borrow() => - { - RetagKind::TwoPhase - } - _ => RetagKind::Default, + let add_retag = match rvalue { + // Ptr-creating operations already do their own internal retagging, no + // need to also add a retag statement. + Rvalue::Ref(..) | Rvalue::AddressOf(..) => false, + _ => true, }; - (kind, *place) + if add_retag { + (RetagKind::Default, *place) + } else { + continue; + } } // Do nothing for the rest _ => continue, diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 8922298ecafcb..69f96fe48ea2f 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -985,16 +985,6 @@ fn create_generator_drop_shim<'tcx>( tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }), source_info, ); - if tcx.sess.opts.unstable_opts.mir_emit_retag { - // Alias tracking must know we changed the type - body.basic_blocks_mut()[START_BLOCK].statements.insert( - 0, - Statement { - source_info, - kind: StatementKind::Retag(RetagKind::Raw, Box::new(Place::from(SELF_ARG))), - }, - ) - } // Make sure we remove dead blocks to remove // unrelated code from the resume part of the function diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index a115bb2831a4b..16b7dcad17e77 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -177,16 +177,6 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) if ty.is_some() { // The first argument (index 0), but add 1 for the return value. let dropee_ptr = Place::from(Local::new(1 + 0)); - if tcx.sess.opts.unstable_opts.mir_emit_retag { - // Function arguments should be retagged, and we make this one raw. - body.basic_blocks_mut()[START_BLOCK].statements.insert( - 0, - Statement { - source_info, - kind: StatementKind::Retag(RetagKind::Raw, Box::new(dropee_ptr)), - }, - ); - } let patch = { let param_env = tcx.param_env_reveal_all_normalized(def_id); let mut elaborator = diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 4ef89cfb2554f..82f5d0f534a4b 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1196,7 +1196,7 @@ impl<'a> Resolver<'a> { pub fn new( session: &'a Session, krate: &Crate, - crate_name: &str, + crate_name: Symbol, metadata_loader: Box, arenas: &'a ResolverArenas<'a>, ) -> Resolver<'a> { diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index b45288538256f..9ae07cb005bd4 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -111,7 +111,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.save_ctxt.lookup_def_id(ref_id) } - pub fn dump_crate_info(&mut self, name: &str) { + pub fn dump_crate_info(&mut self, name: Symbol) { let source_file = self.tcx.sess.local_crate_source_file.as_ref(); let crate_root = source_file.map(|source_file| { let source_file = Path::new(source_file); @@ -124,7 +124,7 @@ impl<'tcx> DumpVisitor<'tcx> { let data = CratePreludeData { crate_id: GlobalCrateId { - name: name.into(), + name: name.to_string(), disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0), }, crate_root: crate_root.unwrap_or_else(|| "".to_owned()), @@ -135,7 +135,7 @@ impl<'tcx> DumpVisitor<'tcx> { self.dumper.crate_prelude(data); } - pub fn dump_compilation_options(&mut self, input: &Input, crate_name: &str) { + pub fn dump_compilation_options(&mut self, input: &Input, crate_name: Symbol) { // Apply possible `remap-path-prefix` remapping to the input source file // (and don't include remapping args anymore) let (program, arguments) = { diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index f05eb2b7432b5..7735c571310dd 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -95,7 +95,7 @@ impl<'tcx> SaveContext<'tcx> { } /// Returns path to the compilation output (e.g., libfoo-12345678.rmeta) - pub fn compilation_output(&self, crate_name: &str) -> PathBuf { + pub fn compilation_output(&self, crate_name: Symbol) -> PathBuf { let sess = &self.tcx.sess; // Save-analysis is emitted per whole session, not per each crate type let crate_type = sess.crate_types()[0]; @@ -894,8 +894,8 @@ pub struct DumpHandler<'a> { } impl<'a> DumpHandler<'a> { - pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> { - DumpHandler { odir, cratename: cratename.to_owned() } + pub fn new(odir: Option<&'a Path>, cratename: Symbol) -> DumpHandler<'a> { + DumpHandler { odir, cratename: cratename.to_string() } } fn output_file(&self, ctx: &SaveContext<'_>) -> (BufWriter, PathBuf) { @@ -960,7 +960,7 @@ impl SaveHandler for CallbackHandler<'_> { pub fn process_crate<'l, 'tcx, H: SaveHandler>( tcx: TyCtxt<'tcx>, - cratename: &str, + cratename: Symbol, input: &'l Input, config: Option, mut handler: H, diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index a052f29334169..cbbba2252bf60 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -18,6 +18,7 @@ rustc_fs_util = { path = "../rustc_fs_util" } rustc_ast = { path = "../rustc_ast" } rustc_lint_defs = { path = "../rustc_lint_defs" } smallvec = "1.8.1" +termize = "0.1.1" [target.'cfg(unix)'.dependencies] libc = "0.2" diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 8cb9e1a6f1ae8..ee492f802a70c 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -129,10 +129,10 @@ pub struct FileIsNotWriteable<'a> { #[derive(Diagnostic)] #[diag(session_crate_name_does_not_match)] -pub struct CrateNameDoesNotMatch<'a> { +pub struct CrateNameDoesNotMatch { #[primary_span] pub span: Span, - pub s: &'a str, + pub s: Symbol, pub name: Symbol, } @@ -151,11 +151,11 @@ pub struct CrateNameEmpty { #[derive(Diagnostic)] #[diag(session_invalid_character_in_create_name)] -pub struct InvalidCharacterInCrateName<'a> { +pub struct InvalidCharacterInCrateName { #[primary_span] pub span: Option, pub character: char, - pub crate_name: &'a str, + pub crate_name: Symbol, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 2511bee46afeb..8ee3057de625e 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -7,14 +7,14 @@ use crate::errors::{ use crate::Session; use rustc_ast as ast; use rustc_span::symbol::sym; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; use std::path::{Path, PathBuf}; pub fn out_filename( sess: &Session, crate_type: CrateType, outputs: &OutputFilenames, - crate_name: &str, + crate_name: Symbol, ) -> PathBuf { let default_filename = filename_for_input(sess, crate_type, crate_name, outputs); let out_filename = outputs @@ -45,9 +45,9 @@ fn is_writeable(p: &Path) -> bool { } } -pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> String { - let validate = |s: String, span: Option| { - validate_crate_name(sess, &s, span); +pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> Symbol { + let validate = |s: Symbol, span: Option| { + validate_crate_name(sess, s, span); s }; @@ -59,38 +59,39 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s))); if let Some(ref s) = sess.opts.crate_name { + let s = Symbol::intern(s); if let Some((attr, name)) = attr_crate_name { - if name.as_str() != s { + if name != s { sess.emit_err(CrateNameDoesNotMatch { span: attr.span, s, name }); } } - return validate(s.clone(), None); + return validate(s, None); } if let Some((attr, s)) = attr_crate_name { - return validate(s.to_string(), Some(attr.span)); + return validate(s, Some(attr.span)); } if let Input::File(ref path) = *input { if let Some(s) = path.file_stem().and_then(|s| s.to_str()) { if s.starts_with('-') { sess.emit_err(CrateNameInvalid { s }); } else { - return validate(s.replace('-', "_"), None); + return validate(Symbol::intern(&s.replace('-', "_")), None); } } } - "rust_out".to_string() + Symbol::intern("rust_out") } -pub fn validate_crate_name(sess: &Session, s: &str, sp: Option) { +pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option) { let mut err_count = 0; { if s.is_empty() { err_count += 1; sess.emit_err(CrateNameEmpty { span: sp }); } - for c in s.chars() { + for c in s.as_str().chars() { if c.is_alphanumeric() { continue; } @@ -109,7 +110,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option) { pub fn filename_for_metadata( sess: &Session, - crate_name: &str, + crate_name: Symbol, outputs: &OutputFilenames, ) -> PathBuf { // If the command-line specified the path, use that directly. @@ -132,7 +133,7 @@ pub fn filename_for_metadata( pub fn filename_for_input( sess: &Session, crate_type: CrateType, - crate_name: &str, + crate_name: Symbol, outputs: &OutputFilenames, ) -> PathBuf { let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index e99e460913ef0..4c049a8d628ef 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -952,6 +952,17 @@ impl Session { ) -> Option { attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str()) } + + pub fn diagnostic_width(&self) -> usize { + let default_column_width = 140; + if let Some(width) = self.opts.diagnostic_width { + width + } else if self.opts.unstable_opts.ui_testing { + default_column_width + } else { + termize::dimensions().map_or(default_column_width, |(w, _)| w) + } + } } // JUSTIFICATION: defn of the suggested wrapper fns diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 0ad1f1a0da72f..e62ce2c266aa0 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -1,4 +1,4 @@ -use crate::HashStableContext; +use crate::{HashStableContext, Symbol}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_data_structures::AtomicRef; @@ -149,9 +149,11 @@ impl StableCrateId { /// Computes the stable ID for a crate with the given name and /// `-Cmetadata` arguments. - pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec) -> StableCrateId { + pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec) -> StableCrateId { let mut hasher = StableHasher::new(); - crate_name.hash(&mut hasher); + // We must hash the string text of the crate name, not the id, as the id is not stable + // across builds. + crate_name.as_str().hash(&mut hasher); // We don't want the stable crate ID to depend on the order of // -C metadata arguments, so sort them: diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs index 8dad941b534b6..06529c2e4039d 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs @@ -33,12 +33,6 @@ pub fn target() -> Target { // For now this target just never has an entry symbol no matter the output // type, so unconditionally pass this. "--no-entry", - // Rust really needs a way for users to specify exports and imports in - // the source code. --export-dynamic isn't the right tool for this job, - // however it does have the side effect of automatically exporting a lot - // of symbols, which approximates what people want when compiling for - // wasm32-unknown-unknown expect, so use it for now. - "--export-dynamic", ], ); options.add_pre_link_args( @@ -48,7 +42,6 @@ pub fn target() -> Target { // otherwise "--target=wasm32-unknown-unknown", "-Wl,--no-entry", - "-Wl,--export-dynamic", ], ); diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index b2328b001de90..ac7f579ebb5aa 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -4,12 +4,14 @@ use crate::ascii; use crate::convert::TryInto; -use crate::error::Error; use crate::intrinsics; use crate::mem; use crate::ops::{Add, Mul, Sub}; use crate::str::FromStr; +#[cfg(not(no_fp_fmt_parse))] +use crate::error::Error; + // Used because the `?` operator is not allowed in a const context. macro_rules! try_opt { ($e:expr) => { diff --git a/library/std/src/sys/itron/condvar.rs b/library/std/src/sys/itron/condvar.rs index f70aa434e4834..7a47cc6696a34 100644 --- a/library/std/src/sys/itron/condvar.rs +++ b/library/std/src/sys/itron/condvar.rs @@ -71,7 +71,7 @@ impl Condvar { } } - unsafe { mutex.lock() }; + mutex.lock(); } pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { @@ -109,7 +109,7 @@ impl Condvar { // we woke up because of `notify_*`. let success = self.waiters.with_locked(|waiters| unsafe { !waiters.remove(waiter) }); - unsafe { mutex.lock() }; + mutex.lock(); success } } diff --git a/library/std/src/sys/itron/mutex.rs b/library/std/src/sys/itron/mutex.rs index f2eed8e771c40..1f6cc41947602 100644 --- a/library/std/src/sys/itron/mutex.rs +++ b/library/std/src/sys/itron/mutex.rs @@ -72,7 +72,7 @@ pub(super) struct MutexGuard<'a>(&'a Mutex); impl<'a> MutexGuard<'a> { #[inline] pub(super) fn lock(x: &'a Mutex) -> Self { - unsafe { x.lock() }; + x.lock(); Self(x) } } diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs index d28f57f33be20..c2b3668087225 100644 --- a/library/std/src/sys/itron/thread.rs +++ b/library/std/src/sys/itron/thread.rs @@ -11,18 +11,25 @@ use crate::{ ffi::CStr, hint, io, mem::ManuallyDrop, + ptr::NonNull, sync::atomic::{AtomicUsize, Ordering}, sys::thread_local_dtor::run_dtors, time::Duration, }; pub struct Thread { - inner: ManuallyDrop>, + p_inner: NonNull, /// The ID of the underlying task. task: abi::ID, } +// Safety: There's nothing in `Thread` that ties it to the original creator. It +// can be dropped by any threads. +unsafe impl Send for Thread {} +// Safety: `Thread` provides no methods that take `&self`. +unsafe impl Sync for Thread {} + /// State data shared between a parent thread and child thread. It's dropped on /// a transition to one of the final states. struct ThreadInner { @@ -90,8 +97,9 @@ impl Thread { }); unsafe extern "C" fn trampoline(exinf: isize) { + let p_inner: *mut ThreadInner = crate::ptr::from_exposed_addr_mut(exinf as usize); // Safety: `ThreadInner` is alive at this point - let inner = unsafe { &*(exinf as *const ThreadInner) }; + let inner = unsafe { &*p_inner }; // Safety: Since `trampoline` is called only once for each // `ThreadInner` and only `trampoline` touches `start`, @@ -119,13 +127,13 @@ impl Thread { // No one will ever join, so we'll ask the collector task to // delete the task. - // In this case, `inner`'s ownership has been moved to us, - // And we are responsible for dropping it. The acquire + // In this case, `*p_inner`'s ownership has been moved to + // us, and we are responsible for dropping it. The acquire // ordering is not necessary because the parent thread made // no memory access needing synchronization since the call // to `acre_tsk`. // Safety: See above. - let _ = unsafe { Box::from_raw(inner as *const _ as *mut ThreadInner) }; + let _ = unsafe { Box::from_raw(p_inner) }; // Safety: There are no pinned references to the stack unsafe { terminate_and_delete_current_task() }; @@ -162,13 +170,14 @@ impl Thread { } } - let inner_ptr = (&*inner) as *const ThreadInner; + // Safety: `Box::into_raw` returns a non-null pointer + let p_inner = unsafe { NonNull::new_unchecked(Box::into_raw(inner)) }; let new_task = ItronError::err_if_negative(unsafe { abi::acre_tsk(&abi::T_CTSK { // Activate this task immediately tskatr: abi::TA_ACT, - exinf: inner_ptr as abi::EXINF, + exinf: p_inner.as_ptr().expose_addr() as abi::EXINF, // The entry point task: Some(trampoline), // Inherit the calling task's base priority @@ -180,7 +189,7 @@ impl Thread { }) .map_err(|e| e.as_io_error())?; - Ok(Self { inner: ManuallyDrop::new(inner), task: new_task }) + Ok(Self { p_inner, task: new_task }) } pub fn yield_now() { @@ -197,8 +206,9 @@ impl Thread { } } - pub fn join(mut self) { - let inner = &*self.inner; + pub fn join(self) { + // Safety: `ThreadInner` is alive at this point + let inner = unsafe { self.p_inner.as_ref() }; // Get the current task ID. Panicking here would cause a resource leak, // so just abort on failure. let current_task = task::current_task_id_aborting(); @@ -243,8 +253,8 @@ impl Thread { unsafe { terminate_and_delete_task(self.task) }; // In either case, we are responsible for dropping `inner`. - // Safety: The contents of `self.inner` will not be accessed hereafter - let _inner = unsafe { ManuallyDrop::take(&mut self.inner) }; + // Safety: The contents of `*p_inner` will not be accessed hereafter + let _inner = unsafe { Box::from_raw(self.p_inner.as_ptr()) }; // Skip the destructor (because it would attempt to detach the thread) crate::mem::forget(self); @@ -253,13 +263,16 @@ impl Thread { impl Drop for Thread { fn drop(&mut self) { + // Safety: `ThreadInner` is alive at this point + let inner = unsafe { self.p_inner.as_ref() }; + // Detach the thread. - match self.inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) { + match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) { LIFECYCLE_INIT => { // [INIT → DETACHED] // When the time comes, the child will figure out that no // one will ever join it. - // The ownership of `self.inner` is moved to the child thread. + // The ownership of `*p_inner` is moved to the child thread. // However, the release ordering is not necessary because we // made no memory access needing synchronization since the call // to `acre_tsk`. @@ -278,10 +291,9 @@ impl Drop for Thread { // delete by entering the `FINISHED` state. unsafe { terminate_and_delete_task(self.task) }; - // Wwe are responsible for dropping `inner`. - // Safety: The contents of `self.inner` will not be accessed - // hereafter - unsafe { ManuallyDrop::drop(&mut self.inner) }; + // Wwe are responsible for dropping `*p_inner`. + // Safety: The contents of `*p_inner` will not be accessed hereafter + let _ = unsafe { Box::from_raw(self.p_inner.as_ptr()) }; } _ => unsafe { hint::unreachable_unchecked() }, } diff --git a/library/std/src/sys/solid/io.rs b/library/std/src/sys/solid/io.rs index 9eb17a10daa28..a862bb7870264 100644 --- a/library/std/src/sys/solid/io.rs +++ b/library/std/src/sys/solid/io.rs @@ -75,3 +75,7 @@ impl<'a> IoSliceMut<'a> { unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) } } } + +pub fn is_terminal(_: &T) -> bool { + false +} diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs index 4906c62689d4c..6135921f0b5a8 100644 --- a/library/std/src/sys/solid/os.rs +++ b/library/std/src/sys/solid/os.rs @@ -1,7 +1,6 @@ use super::unsupported; -use crate::convert::TryFrom; use crate::error::Error as StdError; -use crate::ffi::{CStr, CString, OsStr, OsString}; +use crate::ffi::{CStr, OsStr, OsString}; use crate::fmt; use crate::io; use crate::os::{ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile index c3b47c3510d46..06f15bd121174 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile @@ -25,7 +25,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ zlib1g-dev \ xz-utils \ nodejs \ - + \ # Install powershell so we can test x.ps1 on Linux apt-transport-https software-properties-common && \ curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 501d27816462a..58c0c5db1a5d6 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -15,7 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ sudo \ xz-utils \ tidy \ - + \ # Install dependencies for chromium browser gconf-service \ libasound2 \ diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir index 75af20d482ddd..60149ff36064e 100644 --- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir @@ -38,9 +38,7 @@ fn bar() -> bool { // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) } Retag(_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 _4 = &(*_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 - Retag(_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 _3 = &(*_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 - Retag(_3); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 StorageLive(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 StorageLive(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 _9 = const _; // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 @@ -49,9 +47,7 @@ fn bar() -> bool { // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) } Retag(_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 _7 = &(*_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 - Retag(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 _6 = &(*_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 - Retag(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 Retag(_3); // scope 2 at $DIR/inline_retag.rs:16:8: 16:9 Retag(_6); // scope 2 at $DIR/inline_retag.rs:16:17: 16:18 StorageLive(_11); // scope 2 at $DIR/inline_retag.rs:17:5: 17:7 diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index fe57e32a7acc2..7b69b3e07d6c5 100644 --- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -68,9 +68,7 @@ fn array_casts() -> () { StorageLive(_3); // scope 1 at $DIR/retag.rs:+2:13: +2:19 StorageLive(_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19 _4 = &mut _1; // scope 1 at $DIR/retag.rs:+2:13: +2:19 - Retag(_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19 _3 = &raw mut (*_4); // scope 1 at $DIR/retag.rs:+2:13: +2:19 - Retag([raw] _3); // scope 1 at $DIR/retag.rs:+2:13: +2:19 _2 = move _3 as *mut usize (Pointer(ArrayToPointer)); // scope 1 at $DIR/retag.rs:+2:13: +2:33 StorageDead(_3); // scope 1 at $DIR/retag.rs:+2:32: +2:33 StorageDead(_4); // scope 1 at $DIR/retag.rs:+2:33: +2:34 @@ -96,9 +94,7 @@ fn array_casts() -> () { StorageLive(_10); // scope 4 at $DIR/retag.rs:+6:13: +6:15 StorageLive(_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15 _11 = &_8; // scope 4 at $DIR/retag.rs:+6:13: +6:15 - Retag(_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15 _10 = &raw const (*_11); // scope 4 at $DIR/retag.rs:+6:13: +6:15 - Retag([raw] _10); // scope 4 at $DIR/retag.rs:+6:13: +6:15 _9 = move _10 as *const usize (Pointer(ArrayToPointer)); // scope 4 at $DIR/retag.rs:+6:13: +6:31 StorageDead(_10); // scope 4 at $DIR/retag.rs:+6:30: +6:31 StorageDead(_11); // scope 4 at $DIR/retag.rs:+6:31: +6:32 @@ -119,7 +115,6 @@ fn array_casts() -> () { StorageDead(_17); // scope 6 at $DIR/retag.rs:+7:33: +7:34 _15 = (*_16); // scope 6 at $DIR/retag.rs:+7:25: +7:34 _14 = &_15; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _35 = const _; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant @@ -127,7 +122,6 @@ fn array_casts() -> () { // + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) } Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Deinit(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_13.0: &usize) = move _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_13.1: &usize) = move _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -164,15 +158,11 @@ fn array_casts() -> () { StorageLive(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _31 = &(*_20); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _30 = &(*_31); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_30); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _33 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _32 = &(*_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Retag(_32); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Deinit(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL discriminant(_34) = 0; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir index cdc413c568f18..14f297e948bec 100644 --- a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir +++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir @@ -6,7 +6,6 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () { let mut _3: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 bb0: { - Retag([raw] _1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 _2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 _3 = ::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 // mir::Constant diff --git a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir index 96fc7e6493ab9..9e5c119a2b24e 100644 --- a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir @@ -15,7 +15,6 @@ fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 { _3 = _2; // scope 0 at $DIR/retag.rs:+1:18: +1:19 Retag(_3); // scope 0 at $DIR/retag.rs:+1:18: +1:19 _0 = &(*_2); // scope 1 at $DIR/retag.rs:+2:9: +2:10 - Retag(_0); // scope 1 at $DIR/retag.rs:+2:9: +2:10 StorageDead(_3); // scope 0 at $DIR/retag.rs:+3:5: +3:6 return; // scope 0 at $DIR/retag.rs:+3:6: +3:6 } diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index 81225b44ebf9f..b853e45054172 100644 --- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -65,13 +65,10 @@ fn main() -> () { Deinit(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24 (_5.0: i32) = const 0_i32; // scope 1 at $DIR/retag.rs:+3:17: +3:24 _4 = &_5; // scope 1 at $DIR/retag.rs:+3:17: +3:36 - Retag(_4); // scope 1 at $DIR/retag.rs:+3:17: +3:36 StorageLive(_6); // scope 1 at $DIR/retag.rs:+3:29: +3:35 StorageLive(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35 _7 = &mut _1; // scope 1 at $DIR/retag.rs:+3:29: +3:35 - Retag(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35 _6 = &mut (*_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35 - Retag([2phase] _6); // scope 1 at $DIR/retag.rs:+3:29: +3:35 _3 = Test::foo(move _4, move _6) -> [return: bb1, unwind: bb8]; // scope 1 at $DIR/retag.rs:+3:17: +3:36 // mir::Constant // + span: $DIR/retag.rs:33:25: 33:28 @@ -93,7 +90,6 @@ fn main() -> () { _9 = move _3; // scope 2 at $DIR/retag.rs:+4:19: +4:20 Retag(_9); // scope 2 at $DIR/retag.rs:+4:19: +4:20 _8 = &mut (*_9); // scope 2 at $DIR/retag.rs:+4:19: +4:20 - Retag(_8); // scope 2 at $DIR/retag.rs:+4:19: +4:20 StorageDead(_9); // scope 2 at $DIR/retag.rs:+4:22: +4:23 StorageLive(_10); // scope 3 at $DIR/retag.rs:+5:13: +5:14 _10 = move _8; // scope 3 at $DIR/retag.rs:+5:17: +5:18 @@ -101,7 +97,6 @@ fn main() -> () { StorageLive(_11); // scope 4 at $DIR/retag.rs:+7:13: +7:15 StorageLive(_12); // scope 4 at $DIR/retag.rs:+7:18: +7:29 _12 = &raw mut (*_10); // scope 4 at $DIR/retag.rs:+7:18: +7:19 - Retag([raw] _12); // scope 4 at $DIR/retag.rs:+7:18: +7:19 _11 = _12; // scope 4 at $DIR/retag.rs:+7:18: +7:29 StorageDead(_12); // scope 4 at $DIR/retag.rs:+7:29: +7:30 _2 = const (); // scope 1 at $DIR/retag.rs:+2:5: +8:6 @@ -122,9 +117,7 @@ fn main() -> () { StorageLive(_17); // scope 6 at $DIR/retag.rs:+15:16: +15:18 StorageLive(_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18 _18 = &_1; // scope 6 at $DIR/retag.rs:+15:16: +15:18 - Retag(_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18 _17 = &(*_18); // scope 6 at $DIR/retag.rs:+15:16: +15:18 - Retag(_17); // scope 6 at $DIR/retag.rs:+15:16: +15:18 _15 = move _16(move _17) -> bb3; // scope 6 at $DIR/retag.rs:+15:14: +15:19 } @@ -139,7 +132,6 @@ fn main() -> () { Deinit(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12 (_21.0: i32) = const 0_i32; // scope 7 at $DIR/retag.rs:+18:5: +18:12 _20 = &_21; // scope 7 at $DIR/retag.rs:+18:5: +18:24 - Retag(_20); // scope 7 at $DIR/retag.rs:+18:5: +18:24 StorageLive(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23 StorageLive(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23 _28 = const _; // scope 7 at $DIR/retag.rs:+18:21: +18:23 @@ -148,9 +140,7 @@ fn main() -> () { // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } Retag(_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23 _23 = &(*_28); // scope 7 at $DIR/retag.rs:+18:21: +18:23 - Retag(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23 _22 = &(*_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23 - Retag(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23 _19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind: bb7]; // scope 7 at $DIR/retag.rs:+18:5: +18:24 // mir::Constant // + span: $DIR/retag.rs:48:13: 48:20 @@ -171,7 +161,6 @@ fn main() -> () { StorageLive(_25); // scope 7 at $DIR/retag.rs:+21:9: +21:11 StorageLive(_26); // scope 7 at $DIR/retag.rs:+21:14: +21:28 _26 = &raw const (*_15); // scope 7 at $DIR/retag.rs:+21:14: +21:16 - Retag([raw] _26); // scope 7 at $DIR/retag.rs:+21:14: +21:16 _25 = _26; // scope 7 at $DIR/retag.rs:+21:14: +21:28 StorageDead(_26); // scope 7 at $DIR/retag.rs:+21:28: +21:29 StorageLive(_27); // scope 8 at $DIR/retag.rs:+23:5: +23:18 diff --git a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir index 08fd655ae29bb..4b50205fa8081 100644 --- a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir @@ -11,9 +11,7 @@ fn ::foo(_1: &Test, _2: &mut i32) -> &mut i32 Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:+0:23: +0:24 StorageLive(_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10 _3 = &mut (*_2); // scope 0 at $DIR/retag.rs:+1:9: +1:10 - Retag(_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10 _0 = &mut (*_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10 - Retag(_0); // scope 0 at $DIR/retag.rs:+1:9: +1:10 StorageDead(_3); // scope 0 at $DIR/retag.rs:+2:5: +2:6 return; // scope 0 at $DIR/retag.rs:+2:6: +2:6 } diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 2c4309fbe66f9..3aa57d58908bb 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -67,7 +67,7 @@ impl CodegenBackend for TheBackend { if crate_type != CrateType::Rlib { sess.fatal(&format!("Crate type is {:?}", crate_type)); } - let output_name = out_filename(sess, crate_type, &outputs, &*crate_name.as_str()); + let output_name = out_filename(sess, crate_type, &outputs, crate_name); let mut out_file = ::std::fs::File::create(output_name).unwrap(); write!(out_file, "This has been \"compiled\" successfully.").unwrap(); } diff --git a/src/test/ui/async-await/in-trait/nested-rpit.rs b/src/test/ui/async-await/in-trait/nested-rpit.rs new file mode 100644 index 0000000000000..ae8e0aed0cc53 --- /dev/null +++ b/src/test/ui/async-await/in-trait/nested-rpit.rs @@ -0,0 +1,17 @@ +// check-pass +// edition: 2021 + +#![feature(async_fn_in_trait)] +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +use std::future::Future; +use std::marker::PhantomData; + +trait Lockable { + async fn lock_all_entries(&self) -> impl Future>; +} + +struct Guard<'a>(PhantomData<&'a ()>); + +fn main() {} diff --git a/src/test/ui/diagnostic-width/long-E0308.rs b/src/test/ui/diagnostic-width/long-E0308.rs new file mode 100644 index 0000000000000..3fd7a7110fd97 --- /dev/null +++ b/src/test/ui/diagnostic-width/long-E0308.rs @@ -0,0 +1,86 @@ +// compile-flags: --diagnostic-width=60 +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" + +struct Atype(T, K); +struct Btype(T, K); +struct Ctype(T, K); + +fn main() { + let x: Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok("") + )))))))))))))))))))))))))))))) + )))))))))))))))))))))))))))))); + //~^^^^^ ERROR E0308 + + let _ = Some(Ok(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( + Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( + Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some( + Some(Some(Some(Some(Some(Some(Some(Some(Some(""))))))))) + ))))))))))))))))) + )))))))))))))))))) + ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) + )))))))))))))))))))))))))))))) + )))))))))))))))))))))))); + //~^^^^^ ERROR E0308 + + let x: Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype< + Atype< + Btype< + Ctype, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + >, + i32 + > = (); + //~^ ERROR E0308 + + let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok( + Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) + )))))))))))))))))))))))))))))) + )))))))))))))))))))))))); + //~^^^^^ ERROR E0308 +} diff --git a/src/test/ui/diagnostic-width/long-E0308.stderr b/src/test/ui/diagnostic-width/long-E0308.stderr new file mode 100644 index 0000000000000..487ab23a1c100 --- /dev/null +++ b/src/test/ui/diagnostic-width/long-E0308.stderr @@ -0,0 +1,80 @@ +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:33:9 + | +LL | let x: Atype< + | _____________- +LL | | Btype< +LL | | Ctype< +LL | | Atype< +... | +LL | | i32 +LL | | > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... + | | _____-___^ + | ||_____| + | | expected due to this +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... +LL | | Ok("") +LL | | )))))))))))))))))))))))))))))) +LL | | )))))))))))))))))))))))))))))); + | |__________________________________^ expected struct `Atype`, found enum `Result` + | + = note: expected struct `Atype, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + found enum `Result, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:46:26 + | +LL | ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... + | __________________________^ +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) +LL | | )))))))))))))))))))))))))))))) +LL | | )))))))))))))))))))))))); + | |____________________________^ expected enum `Option`, found enum `Result` + | + = note: expected enum `Option>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + found enum `Result, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:77:9 + | +LL | let x: Atype< + | ____________- +LL | | Btype< +LL | | Ctype< +LL | | Atype< +... | +LL | | i32 +LL | | > = (); + | | - ^^ expected struct `Atype`, found `()` + | |_____| + | expected due to this + | + = note: expected struct `Atype, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/long-E0308.rs:80:17 + | +LL | let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... + | ____________--___^ + | | | + | | expected due to this +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... +LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) +LL | | )))))))))))))))))))))))))))))) +LL | | )))))))))))))))))))))))); + | |____________________________^ expected `()`, found enum `Result` + | + = note: expected unit type `()` + found enum `Result, ...>` + the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr index 49a4d984af9eb..451a683ac8a6e 100644 --- a/src/test/ui/error-codes/E0275.stderr +++ b/src/test/ui/error-codes/E0275.stderr @@ -5,7 +5,7 @@ LL | impl Foo for T where Bar: Foo {} | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`) -note: required for `Bar>>>>>` to implement `Foo` +note: required for `Bar>>>>>>>>>>>>>>>>>>>>` to implement `Foo` --> $DIR/E0275.rs:6:9 | LL | impl Foo for T where Bar: Foo {} diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr index c485bc5c3ab90..760dcb615c879 100644 --- a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr +++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr @@ -3,12 +3,18 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t | LL | fn f() -> impl Fn() -> impl Sized { || () } | ^^^^^^^^^^ + | + = note: see issue #99697 for more information + = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32 | LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () } | ^^^^^^^^^^ + | + = note: see issue #99697 for more information + = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr index 91509ceace8cb..78df445972c94 100644 --- a/src/test/ui/issues/issue-20413.stderr +++ b/src/test/ui/issues/issue-20413.stderr @@ -14,7 +14,7 @@ LL | impl Foo for T where NoData: Foo { | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `NoData>>>>>` to implement `Foo` +note: required for `NoData>>>>>>>>>>>>` to implement `Foo` --> $DIR/issue-20413.rs:9:9 | LL | impl Foo for T where NoData: Foo { @@ -30,13 +30,13 @@ LL | impl Bar for T where EvenLessData: Baz { | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `AlmostNoData>>>>>` to implement `Bar` +note: required for `AlmostNoData>>>>>>` to implement `Bar` --> $DIR/issue-20413.rs:28:9 | LL | impl Bar for T where EvenLessData: Baz { | ^^^ ^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt' -note: required for `EvenLessData>>>>>` to implement `Baz` +note: required for `EvenLessData>>>>>>` to implement `Baz` --> $DIR/issue-20413.rs:35:9 | LL | impl Baz for T where AlmostNoData: Bar { @@ -52,13 +52,13 @@ LL | impl Baz for T where AlmostNoData: Bar { | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`) -note: required for `EvenLessData>>>>>` to implement `Baz` +note: required for `EvenLessData>>>>>>` to implement `Baz` --> $DIR/issue-20413.rs:35:9 | LL | impl Baz for T where AlmostNoData: Bar { | ^^^ ^ = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt' -note: required for `AlmostNoData>>>>>` to implement `Bar` +note: required for `AlmostNoData>>>>>>` to implement `Bar` --> $DIR/issue-20413.rs:28:9 | LL | impl Bar for T where EvenLessData: Baz { diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr index 5828e027b5903..1f50b06a0e4c5 100644 --- a/src/test/ui/issues/issue-23122-2.stderr +++ b/src/test/ui/issues/issue-23122-2.stderr @@ -5,7 +5,7 @@ LL | type Next = as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`) -note: required for `GetNext<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next` +note: required for `GetNext<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next` --> $DIR/issue-23122-2.rs:10:15 | LL | impl Next for GetNext { diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr index 4d00a70831377..dde8ad1b6b327 100644 --- a/src/test/ui/recursion/issue-83150.stderr +++ b/src/test/ui/recursion/issue-83150.stderr @@ -12,7 +12,7 @@ LL | func(&mut iter.map(|x| x + 1)) error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) - = note: required for `&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>` to implement `Iterator` + = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator` = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt' error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/regions/issue-102374.rs b/src/test/ui/regions/issue-102374.rs index e0a1164211a2c..fd71248d9cb45 100644 --- a/src/test/ui/regions/issue-102374.rs +++ b/src/test/ui/regions/issue-102374.rs @@ -1,3 +1,4 @@ +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" use std::cell::Cell; #[rustfmt::skip] diff --git a/src/test/ui/regions/issue-102374.stderr b/src/test/ui/regions/issue-102374.stderr index 31b855c36bead..157850693ab50 100644 --- a/src/test/ui/regions/issue-102374.stderr +++ b/src/test/ui/regions/issue-102374.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-102374.rs:16:5 + --> $DIR/issue-102374.rs:17:5 | LL | ) -> i32 { | --- expected `i32` because of return type @@ -7,7 +7,8 @@ LL | f | ^ expected `i32`, found fn pointer | = note: expected type `i32` - found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<(&'z1 i32, &'a i32, &'b i32, &'c i32, &'d i32, &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, &'y i32, &'z i32, &'z0 i32)>)` + found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<...>)` + the full type name has been written to '$TEST_BUILD_DIR/regions/issue-102374/issue-102374.long-type-hash.txt' error: aborting due to previous error diff --git a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr index a74d2524996a1..1f18c5daf66e3 100644 --- a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr +++ b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr @@ -17,7 +17,7 @@ error[E0275]: overflow evaluating the requirement `(): Sized` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`) = note: required for `std::iter::Empty<()>` to implement `Iterator` = note: 171 redundant requirements hidden - = note: required for `IteratorOfWrapped<(), Map>, ...>>` to implement `Iterator` + = note: required for `IteratorOfWrapped<(), Map>, ...>>, ...>>` to implement `Iterator` = note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt' error: aborting due to previous error; 1 warning emitted diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 10e6e252e94b7..f896a337f42ca 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -11,7 +11,6 @@ use rustc_target::abi::Size; use crate::*; pub mod stacked_borrows; -use stacked_borrows::diagnostics::RetagCause; pub type CallId = NonZeroU64; @@ -265,11 +264,19 @@ impl GlobalStateInner { impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn retag(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { + fn retag_ptr_value(&mut self, kind: RetagKind, val: &ImmTy<'tcx, Provenance>) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { let this = self.eval_context_mut(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { - BorrowTrackerMethod::StackedBorrows => this.sb_retag(kind, place), + BorrowTrackerMethod::StackedBorrows => this.sb_retag_ptr_value(kind, val), + } + } + + fn retag_place_contents(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; + match method { + BorrowTrackerMethod::StackedBorrows => this.sb_retag_place_contents(kind, place), } } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index 9a7b38b13a3ad..24b3489e0d1d6 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -459,10 +459,10 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { Operation::Dealloc(_) => format!(" due to deallocation"), Operation::Access(AccessOp { kind, tag, .. }) => format!(" due to {kind:?} access for {tag:?}"), - Operation::Retag(RetagOp { orig_tag, permission, .. }) => { + Operation::Retag(RetagOp { orig_tag, permission, new_tag, .. }) => { let permission = permission .expect("start_grant should set the current permission before popping a tag"); - format!(" due to {permission:?} retag from {orig_tag:?}") + format!(" due to {permission:?} retag from {orig_tag:?} (that retag created {new_tag:?})") } }; diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index bcac873251f58..ffbc00864022f 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -1,9 +1,13 @@ //! Implements "Stacked Borrows". See //! for further information. +pub mod diagnostics; +mod item; +mod stack; + use log::trace; use std::cmp; -use std::fmt::{self, Write}; +use std::fmt::Write; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::{Mutability, RetagKind}; @@ -15,15 +19,13 @@ use rustc_target::abi::{Abi, Size}; use crate::borrow_tracker::{ stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder, TagHistory}, - AccessKind, GlobalStateInner, ProtectorKind, RetagCause, RetagFields, + AccessKind, GlobalStateInner, ProtectorKind, RetagFields, }; use crate::*; -mod item; +use diagnostics::RetagCause; pub use item::{Item, Permission}; -mod stack; pub use stack::Stack; -pub mod diagnostics; pub type AllocState = Stacks; @@ -40,30 +42,104 @@ pub struct Stacks { modified_since_last_gc: bool, } -/// Indicates which kind of reference is being created. -/// Used by high-level `reborrow` to compute which permissions to grant to the -/// new pointer. -#[derive(Copy, Clone, Hash, PartialEq, Eq)] -enum RefKind { - /// `Box`. - Box, - /// `&mut`. - Unique { two_phase: bool }, - /// `&` with or without interior mutability. - Shared, - /// `*mut`/`*const` (raw pointers). - Raw { mutable: bool }, +/// Indicates which permissions to grant to the retagged pointer. +#[derive(Clone, Debug)] +enum NewPermission { + Uniform { + perm: Permission, + access: Option, + protector: Option, + }, + FreezeSensitive { + freeze_perm: Permission, + freeze_access: Option, + freeze_protector: Option, + nonfreeze_perm: Permission, + nonfreeze_access: Option, + // nonfreeze_protector must always be None + }, } -impl fmt::Display for RefKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl NewPermission { + /// A key function: determine the permissions to grant at a retag for the given kind of + /// reference/pointer. + fn from_ref_ty<'tcx>( + ty: ty::Ty<'tcx>, + kind: RetagKind, + cx: &crate::MiriInterpCx<'_, 'tcx>, + ) -> Self { + let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector); + match ty.kind() { + ty::Ref(_, pointee, Mutability::Mut) => { + if kind == RetagKind::TwoPhase { + // We mostly just give up on 2phase-borrows, and treat these exactly like raw pointers. + assert!(protector.is_none()); // RetagKind can't be both FnEntry and TwoPhase. + NewPermission::Uniform { + perm: Permission::SharedReadWrite, + access: None, + protector: None, + } + } else if pointee.is_unpin(*cx.tcx, cx.param_env()) { + // A regular full mutable reference. + NewPermission::Uniform { + perm: Permission::Unique, + access: Some(AccessKind::Write), + protector, + } + } else { + NewPermission::Uniform { + perm: Permission::SharedReadWrite, + // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we + // should do fake accesses here. But then we run into + // , so for now + // we don't do that. + access: None, + protector, + } + } + } + ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Mut, .. }) => { + assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw. + // Mutable raw pointer. No access, not protected. + NewPermission::Uniform { + perm: Permission::SharedReadWrite, + access: None, + protector: None, + } + } + ty::Ref(_, _pointee, Mutability::Not) => { + NewPermission::FreezeSensitive { + freeze_perm: Permission::SharedReadOnly, + freeze_access: Some(AccessKind::Read), + freeze_protector: protector, + nonfreeze_perm: Permission::SharedReadWrite, + // Inside UnsafeCell, this does *not* count as an access, as there + // might actually be mutable references further up the stack that + // we have to keep alive. + nonfreeze_access: None, + // We do not protect inside UnsafeCell. + // This fixes https://github.com/rust-lang/rust/issues/55005. + } + } + ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Not, .. }) => { + assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw. + // `*const T`, when freshly created, are read-only in the frozen part. + NewPermission::FreezeSensitive { + freeze_perm: Permission::SharedReadOnly, + freeze_access: Some(AccessKind::Read), + freeze_protector: None, + nonfreeze_perm: Permission::SharedReadWrite, + nonfreeze_access: None, + } + } + _ => unreachable!(), + } + } + + fn protector(&self) -> Option { match self { - RefKind::Box => write!(f, "Box"), - RefKind::Unique { two_phase: false } => write!(f, "unique reference"), - RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"), - RefKind::Shared => write!(f, "shared reference"), - RefKind::Raw { mutable: true } => write!(f, "raw (mutable) pointer"), - RefKind::Raw { mutable: false } => write!(f, "raw (constant) pointer"), + NewPermission::Uniform { protector, .. } => *protector, + NewPermission::FreezeSensitive { freeze_protector, .. } => *freeze_protector, } } } @@ -518,10 +594,9 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' &mut self, place: &MPlaceTy<'tcx, Provenance>, size: Size, - kind: RefKind, - retag_cause: RetagCause, // What caused this retag, for diagnostics only + new_perm: NewPermission, new_tag: BorTag, - protect: Option, + retag_cause: RetagCause, // What caused this retag, for diagnostics only ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); @@ -532,20 +607,16 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' let global = this.machine.borrow_tracker.as_ref().unwrap().borrow(); let ty = place.layout.ty; if global.tracked_pointer_tags.contains(&new_tag) { - let mut kind_str = format!("{kind}"); - match kind { - RefKind::Unique { two_phase: false } - if !ty.is_unpin(*this.tcx, this.param_env()) => - { - write!(kind_str, " (!Unpin pointee type {ty})").unwrap() - }, - RefKind::Shared - if !ty.is_freeze(*this.tcx, this.param_env()) => - { - write!(kind_str, " (!Freeze pointee type {ty})").unwrap() - }, - _ => write!(kind_str, " (pointee type {ty})").unwrap(), - }; + let mut kind_str = String::new(); + match new_perm { + NewPermission::Uniform { perm, .. } => + write!(kind_str, "{perm:?} permission").unwrap(), + NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.param_env()) => + write!(kind_str, "{freeze_perm:?} permission").unwrap(), + NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. } => + write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(), + } + write!(kind_str, " (pointee type {ty})").unwrap(); this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag( new_tag.inner(), Some(kind_str), @@ -579,7 +650,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' ); let mut dcx = dcx.build(&mut stacked_borrows.history, base_offset); dcx.log_creation(); - if protect.is_some() { + if new_perm.protector().is_some() { dcx.log_protector(); } }, @@ -592,8 +663,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' if size == Size::ZERO { trace!( - "reborrow of size 0: {} reference {:?} derived from {:?} (pointee {})", - kind, + "reborrow of size 0: reference {:?} derived from {:?} (pointee {})", new_tag, place.ptr, place.layout.ty, @@ -630,8 +700,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' } trace!( - "reborrow: {} reference {:?} derived from {:?} (pointee {}): {:?}, size {}", - kind, + "reborrow: reference {:?} derived from {:?} (pointee {}): {:?}, size {}", new_tag, orig_tag, place.layout.ty, @@ -639,7 +708,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' size.bytes() ); - if let Some(protect) = protect { + if let Some(protect) = new_perm.protector() { // See comment in `Stack::item_invalidated` for why we store the tag twice. this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag); this.machine @@ -651,30 +720,45 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' .insert(new_tag, protect); } - // Update the stacks. - // Make sure that raw pointers and mutable shared references are reborrowed "weak": - // There could be existing unique pointers reborrowed from them that should remain valid! - let (perm, access) = match kind { - RefKind::Unique { two_phase } => { - // Permission is Unique only if the type is `Unpin` and this is not twophase - if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) { - (Permission::Unique, Some(AccessKind::Write)) - } else { - // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we - // should do fake accesses here. But then we run into - // , so for now - // we don't do that. - (Permission::SharedReadWrite, None) + // Update the stacks, according to the new permission information we are given. + match new_perm { + NewPermission::Uniform { perm, access, protector } => { + assert!(perm != Permission::SharedReadOnly); + // Here we can avoid `borrow()` calls because we have mutable references. + // Note that this asserts that the allocation is mutable -- but since we are creating a + // mutable pointer, that seems reasonable. + let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?; + let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut(); + let item = Item::new(new_tag, perm, protector.is_some()); + let range = alloc_range(base_offset, size); + let global = machine.borrow_tracker.as_ref().unwrap().borrow(); + let dcx = DiagnosticCxBuilder::retag( + machine, + retag_cause, + new_tag, + orig_tag, + alloc_range(base_offset, size), + ); + stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| { + stack.grant(orig_tag, item, access, &global, dcx, exposed_tags) + })?; + drop(global); + if let Some(access) = access { + assert_eq!(access, AccessKind::Write); + // Make sure the data race model also knows about this. + if let Some(data_race) = alloc_extra.data_race.as_mut() { + data_race.write(alloc_id, range, machine)?; + } } } - RefKind::Box => (Permission::Unique, Some(AccessKind::Write)), - RefKind::Raw { mutable: true } => { - // Creating a raw ptr does not count as an access - (Permission::SharedReadWrite, None) - } - RefKind::Shared | RefKind::Raw { mutable: false } => { - // Shared references and *const are a whole different kind of game, the - // permission is not uniform across the entire range! + NewPermission::FreezeSensitive { + freeze_perm, + freeze_access, + freeze_protector, + nonfreeze_perm, + nonfreeze_access, + } => { + // The permission is not uniform across the entire range! // We need a frozen-sensitive reborrow. // We have to use shared references to alloc/memory_extra here since // `visit_freeze_sensitive` needs to access the global state. @@ -684,22 +768,12 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' // Adjust range. range.start += base_offset; // We are only ever `SharedReadOnly` inside the frozen bits. - let (perm, access) = if frozen { - (Permission::SharedReadOnly, Some(AccessKind::Read)) - } else { - // Inside UnsafeCell, this does *not* count as an access, as there - // might actually be mutable references further up the stack that - // we have to keep alive. - (Permission::SharedReadWrite, None) - }; - let protected = if frozen { - protect.is_some() + let (perm, access, protector) = if frozen { + (freeze_perm, freeze_access, freeze_protector) } else { - // We do not protect inside UnsafeCell. - // This fixes https://github.com/rust-lang/rust/issues/55005. - false + (nonfreeze_perm, nonfreeze_access, None) }; - let item = Item::new(new_tag, perm, protected); + let item = Item::new(new_tag, perm, protector.is_some()); let global = this.machine.borrow_tracker.as_ref().unwrap().borrow(); let dcx = DiagnosticCxBuilder::retag( &this.machine, @@ -721,34 +795,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' } Ok(()) })?; - return Ok(Some(alloc_id)); - } - }; - - // Here we can avoid `borrow()` calls because we have mutable references. - // Note that this asserts that the allocation is mutable -- but since we are creating a - // mutable pointer, that seems reasonable. - let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?; - let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut(); - let item = Item::new(new_tag, perm, protect.is_some()); - let range = alloc_range(base_offset, size); - let global = machine.borrow_tracker.as_ref().unwrap().borrow(); - let dcx = DiagnosticCxBuilder::retag( - machine, - retag_cause, - new_tag, - orig_tag, - alloc_range(base_offset, size), - ); - stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| { - stack.grant(orig_tag, item, access, &global, dcx, exposed_tags) - })?; - drop(global); - if let Some(access) = access { - assert_eq!(access, AccessKind::Write); - // Make sure the data race model also knows about this. - if let Some(data_race) = alloc_extra.data_race.as_mut() { - data_race.write(alloc_id, range, machine)?; } } @@ -760,9 +806,8 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' fn sb_retag_reference( &mut self, val: &ImmTy<'tcx, Provenance>, - kind: RefKind, - retag_cause: RetagCause, // What caused this retag, for diagnostics only - protect: Option, + new_perm: NewPermission, + cause: RetagCause, // What caused this retag, for diagnostics only ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { let this = self.eval_context_mut(); // We want a place for where the ptr *points to*, so we get one. @@ -780,7 +825,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr(); // Reborrow. - let alloc_id = this.sb_reborrow(&place, size, kind, retag_cause, new_tag, protect)?; + let alloc_id = this.sb_reborrow(&place, size, new_perm, new_tag, cause)?; // Adjust pointer. let new_place = place.map_provenance(|p| { @@ -807,7 +852,22 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - fn sb_retag( + fn sb_retag_ptr_value( + &mut self, + kind: RetagKind, + val: &ImmTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + let this = self.eval_context_mut(); + let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this); + let retag_cause = match kind { + RetagKind::TwoPhase { .. } => RetagCause::TwoPhase, + RetagKind::FnEntry => unreachable!(), + RetagKind::Raw | RetagKind::Default => RetagCause::Normal, + }; + this.sb_retag_reference(&val, new_perm, retag_cause) + } + + fn sb_retag_place_contents( &mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>, @@ -815,9 +875,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields; let retag_cause = match kind { - RetagKind::TwoPhase { .. } => RetagCause::TwoPhase, + RetagKind::Raw | RetagKind::TwoPhase { .. } => unreachable!(), // these can only happen in `retag_ptr_value` RetagKind::FnEntry => RetagCause::FnEntry, - RetagKind::Raw | RetagKind::Default => RetagCause::Normal, + RetagKind::Default => RetagCause::Normal, }; let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields }; return visitor.visit_value(place); @@ -831,15 +891,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> { #[inline(always)] // yes this helps in our benchmarks - fn retag_place( + fn retag_ptr_inplace( &mut self, place: &PlaceTy<'tcx, Provenance>, - ref_kind: RefKind, + new_perm: NewPermission, retag_cause: RetagCause, - protector: Option, ) -> InterpResult<'tcx> { let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?; - let val = self.ecx.sb_retag_reference(&val, ref_kind, retag_cause, protector)?; + let val = self.ecx.sb_retag_reference(&val, new_perm, retag_cause)?; self.ecx.write_immediate(*val, place)?; Ok(()) } @@ -856,13 +915,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { // Boxes get a weak protectors, since they may be deallocated. - self.retag_place( - place, - RefKind::Box, - self.retag_cause, - /*protector*/ - (self.kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector), - ) + let new_perm = NewPermission::Uniform { + perm: Permission::Unique, + access: Some(AccessKind::Write), + protector: (self.kind == RetagKind::FnEntry) + .then_some(ProtectorKind::WeakProtector), + }; + self.retag_ptr_inplace(place, new_perm, self.retag_cause) } fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { @@ -876,36 +935,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Check the type of this value to see what to do with it (retag, or recurse). match place.layout.ty.kind() { - ty::Ref(_, _, mutbl) => { - let ref_kind = match mutbl { - Mutability::Mut => - RefKind::Unique { two_phase: self.kind == RetagKind::TwoPhase }, - Mutability::Not => RefKind::Shared, - }; - self.retag_place( - place, - ref_kind, - self.retag_cause, - /*protector*/ - (self.kind == RetagKind::FnEntry) - .then_some(ProtectorKind::StrongProtector), - )?; + ty::Ref(..) => { + let new_perm = + NewPermission::from_ref_ty(place.layout.ty, self.kind, self.ecx); + self.retag_ptr_inplace(place, new_perm, self.retag_cause)?; } - ty::RawPtr(tym) => { - // We definitely do *not* want to recurse into raw pointers -- wide raw - // pointers have fields, and for dyn Trait pointees those can have reference - // type! - if self.kind == RetagKind::Raw { - // Raw pointers need to be enabled. - self.retag_place( - place, - RefKind::Raw { mutable: tym.mutbl == Mutability::Mut }, - self.retag_cause, - /*protector*/ None, - )?; - } + ty::RawPtr(..) => { + // We do *not* want to recurse into raw pointers -- wide raw pointers have + // fields, and for dyn Trait pointees those can have reference type! } - _ if place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box()) => { + ty::Adt(adt, _) if adt.is_box() => { // Recurse for boxes, they require some tricky handling and will end up in `visit_box` above. // (Yes this means we technically also recursively retag the allocator itself // even if field retagging is not enabled. *shrug*) @@ -953,12 +992,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?; let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout); // Reborrow it. With protection! That is part of the point. - let val = this.sb_retag_reference( - &val, - RefKind::Unique { two_phase: false }, - RetagCause::FnReturn, - /*protector*/ Some(ProtectorKind::StrongProtector), - )?; + let new_perm = NewPermission::Uniform { + perm: Permission::Unique, + access: Some(AccessKind::Write), + protector: Some(ProtectorKind::StrongProtector), + }; + let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturn)?; // And use reborrowed pointer for return place. let return_place = this.ref_to_mplace(&val)?; this.frame_mut().return_place = return_place.into(); diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 074fa032dcc42..d0fb9f9b0b5fe 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -63,9 +63,9 @@ impl MachineStopType for TerminationInfo {} /// Miri specific diagnostics pub enum NonHaltingDiagnostic { - /// (new_tag, new_kind, (alloc_id, base_offset, orig_tag)) + /// (new_tag, new_perm, (alloc_id, base_offset, orig_tag)) /// - /// new_kind is `None` for base tags. + /// new_perm is `None` for base tags. CreatedPointerTag(NonZeroU64, Option, Option<(AllocId, AllocRange, ProvenanceExtra)>), /// This `Item` was popped from the borrow stack. The string explains the reason. PoppedPointerTag(Item, String), @@ -393,10 +393,10 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { let msg = match &e { CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"), - CreatedPointerTag(tag, Some(kind), None) => format!("created {tag:?} for {kind}"), - CreatedPointerTag(tag, Some(kind), Some((alloc_id, range, orig_tag))) => + CreatedPointerTag(tag, Some(perm), None) => format!("created {tag:?} with {perm} derived from unknown tag"), + CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) => format!( - "created tag {tag:?} for {kind} at {alloc_id:?}{range:?} derived from {orig_tag:?}" + "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}" ), PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"), CreatedCallId(id) => format!("function call with id {id}"), diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index c110229c985db..e5b1eb2e48706 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -967,8 +967,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ptr: Pointer, ) -> InterpResult<'tcx> { match ptr.provenance { - Provenance::Concrete { alloc_id, tag } => - intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag), + Provenance::Concrete { alloc_id, tag } => { + intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag) + } Provenance::Wildcard => { // No need to do anything for wildcard pointers as // their provenances have already been previously exposed. @@ -1055,13 +1056,26 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { } #[inline(always)] - fn retag( + fn retag_ptr_value( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + kind: mir::RetagKind, + val: &ImmTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> { + if ecx.machine.borrow_tracker.is_some() { + ecx.retag_ptr_value(kind, val) + } else { + Ok(val.clone()) + } + } + + #[inline(always)] + fn retag_place_contents( ecx: &mut InterpCx<'mir, 'tcx, Self>, kind: mir::RetagKind, place: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { if ecx.machine.borrow_tracker.is_some() { - ecx.retag(kind, place)?; + ecx.retag_place_contents(kind, place)?; } Ok(()) }