diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 946f2cafa15f2..efc1fa05c5f92 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -190,14 +190,19 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::FnSig<'hir> { let header = if let Some(local_sig_id) = sig_id.as_local() { match self.resolver.delegation_fn_sigs.get(&local_sig_id) { - Some(sig) => self.lower_fn_header( - sig.header, + Some(sig) => { + let parent = self.tcx.parent(sig_id); // HACK: we override the default safety instead of generating attributes from the ether. // We are not forwarding the attributes, as the delegation fn sigs are collected on the ast, // and here we need the hir attributes. - if sig.target_feature { hir::Safety::Unsafe } else { hir::Safety::Safe }, - &[], - ), + let default_safety = + if sig.target_feature || self.tcx.def_kind(parent) == DefKind::ForeignMod { + hir::Safety::Unsafe + } else { + hir::Safety::Safe + }; + self.lower_fn_header(sig.header, default_safety, &[]) + } None => self.generate_header_error(), } } else { diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 1a799f5dea5b5..a21bf018d01fa 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -8,7 +8,6 @@ use std::hash::Hash; use rustc_abi::{Align, Size}; use rustc_apfloat::{Float, FloatConvert}; -use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::TyAndLayout; @@ -21,7 +20,6 @@ use super::{ AllocBytes, AllocId, AllocKind, AllocRange, Allocation, CTFE_ALLOC_SALT, ConstAllocation, CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, interp_ok, throw_unsup, - throw_unsup_format, }; /// Data returned by [`Machine::after_stack_pop`], and consumed by @@ -361,6 +359,19 @@ pub trait Machine<'tcx>: Sized { size: i64, ) -> Option<(AllocId, Size, Self::ProvenanceExtra)>; + /// Return a "root" pointer for the given allocation: the one that is used for direct + /// accesses to this static/const/fn allocation, or the one returned from the heap allocator. + /// + /// Not called on `extern` or thread-local statics (those use the methods above). + /// + /// `kind` is the kind of the allocation the pointer points to; it can be `None` when + /// it's a global and `GLOBAL_KIND` is `None`. + fn adjust_alloc_root_pointer( + ecx: &InterpCx<'tcx, Self>, + ptr: Pointer, + kind: Option>, + ) -> InterpResult<'tcx, Pointer>; + /// Called to adjust global allocations to the Provenance and AllocExtra of this machine. /// /// If `alloc` contains pointers, then they are all pointing to globals. @@ -375,11 +386,12 @@ pub trait Machine<'tcx>: Sized { alloc: &'b Allocation, ) -> InterpResult<'tcx, Cow<'b, Allocation>>; - /// Initialize the extra state of an allocation. + /// Initialize the extra state of an allocation local to this machine. /// - /// This is guaranteed to be called exactly once on all allocations that are accessed by the - /// program. - fn init_alloc_extra( + /// This is guaranteed to be called exactly once on all allocations local to this machine. + /// It will not be called automatically for global allocations; `adjust_global_allocation` + /// has to do that itself if that is desired. + fn init_local_allocation( ecx: &InterpCx<'tcx, Self>, id: AllocId, kind: MemoryKind, @@ -387,34 +399,6 @@ pub trait Machine<'tcx>: Sized { align: Align, ) -> InterpResult<'tcx, Self::AllocExtra>; - /// Return a "root" pointer for the given allocation: the one that is used for direct - /// accesses to this static/const/fn allocation, or the one returned from the heap allocator. - /// - /// Not called on `extern` or thread-local statics (those use the methods above). - /// - /// `kind` is the kind of the allocation the pointer points to; it can be `None` when - /// it's a global and `GLOBAL_KIND` is `None`. - fn adjust_alloc_root_pointer( - ecx: &InterpCx<'tcx, Self>, - ptr: Pointer, - kind: Option>, - ) -> InterpResult<'tcx, Pointer>; - - /// Evaluate the inline assembly. - /// - /// This should take care of jumping to the next block (one of `targets`) when asm goto - /// is triggered, `targets[0]` when the assembly falls through, or diverge in case of - /// naked_asm! or `InlineAsmOptions::NORETURN` being set. - fn eval_inline_asm( - _ecx: &mut InterpCx<'tcx, Self>, - _template: &'tcx [InlineAsmTemplatePiece], - _operands: &[mir::InlineAsmOperand<'tcx>], - _options: InlineAsmOptions, - _targets: &[mir::BasicBlock], - ) -> InterpResult<'tcx> { - throw_unsup_format!("inline assembly is not supported") - } - /// Hook for performing extra checks on a memory read access. /// /// This will *not* be called during validation! @@ -699,7 +683,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) { interp_ok(Cow::Borrowed(alloc)) } - fn init_alloc_extra( + fn init_local_allocation( _ecx: &InterpCx<$tcx, Self>, _id: AllocId, _kind: MemoryKind, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index e5af067362919..75726269a865d 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -263,9 +263,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { M::GLOBAL_KIND.map(MemoryKind::Machine), "dynamically allocating global memory" ); - // We have set things up so we don't need to call `adjust_from_tcx` here, - // so we avoid copying the entire allocation contents. - let extra = M::init_alloc_extra(self, id, kind, alloc.size(), alloc.align)?; + // This cannot be merged with the `adjust_global_allocation` code path + // since here we have an allocation that already uses `M::Bytes`. + let extra = M::init_local_allocation(self, id, kind, alloc.size(), alloc.align)?; let alloc = alloc.with_extra(extra); self.memory.alloc_map.insert(id, (kind, alloc)); M::adjust_alloc_root_pointer(self, Pointer::from(id), Some(kind)) diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 6a17da61c8b7b..ddf2d65914f6c 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -14,7 +14,7 @@ use tracing::{info, instrument, trace}; use super::{ FnArg, FnVal, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemPlaceMeta, PlaceTy, - Projectable, Scalar, interp_ok, throw_ub, + Projectable, Scalar, interp_ok, throw_ub, throw_unsup_format, }; use crate::util; @@ -590,8 +590,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { terminator.kind ), - InlineAsm { template, ref operands, options, ref targets, .. } => { - M::eval_inline_asm(self, template, operands, options, targets)?; + InlineAsm { .. } => { + throw_unsup_format!("inline assembly is not supported"); } } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 9c28fac809da7..b4a16b2b8054c 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -84,6 +84,7 @@ use rustc_infer::infer::{self, TyCtxtInferExt as _}; use rustc_infer::traits::ObligationCause; use rustc_middle::query::Providers; use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::print::with_types_for_signature; use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_session::parse::feature_err; @@ -240,11 +241,11 @@ fn missing_items_err( (Vec::new(), Vec::new(), Vec::new()); for &trait_item in missing_items { - let snippet = suggestion_signature( + let snippet = with_types_for_signature!(suggestion_signature( tcx, trait_item, tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(), - ); + )); let code = format!("{padding}{snippet}\n{padding}"); if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) { missing_trait_item_label diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 70b49fea34f1c..5270c8ed3566f 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -32,6 +32,7 @@ use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, ErrorGuaranteed}; +use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, ExprKind}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_macros::{TypeFoldable, TypeVisitable}; @@ -155,7 +156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -#[derive(Copy, Clone, Debug)] +#[derive(Debug)] enum CastError<'tcx> { ErrorGuaranteed(ErrorGuaranteed), @@ -182,6 +183,7 @@ enum CastError<'tcx> { /// when we're typechecking a type parameter with a ?Sized bound. IntToWideCast(Option<&'static str>), ForeignNonExhaustiveAdt, + PtrPtrAddingAutoTrait(Vec), } impl From for CastError<'_> { @@ -596,6 +598,21 @@ impl<'a, 'tcx> CastCheck<'tcx> { .with_note("cannot cast an enum with a non-exhaustive variant when it's defined in another crate") .emit(); } + CastError::PtrPtrAddingAutoTrait(added) => { + fcx.dcx().emit_err(errors::PtrCastAddAutoToObject { + span: self.span, + traits_len: added.len(), + traits: { + let mut traits: Vec<_> = added + .into_iter() + .map(|trait_did| fcx.tcx.def_path_str(trait_did)) + .collect(); + + traits.sort(); + traits.into() + }, + }); + } } } @@ -940,19 +957,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { .collect::>(); if !added.is_empty() { - tcx.dcx().emit_err(errors::PtrCastAddAutoToObject { - span: self.span, - traits_len: added.len(), - traits: { - let mut traits: Vec<_> = added - .into_iter() - .map(|trait_did| tcx.def_path_str(trait_did)) - .collect(); - - traits.sort(); - traits.into() - }, - }); + return Err(CastError::PtrPtrAddingAutoTrait(added)); } Ok(CastKind::PtrPtrCast) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index bc3d4d6f83ad3..86f1bcc46eea1 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1682,12 +1682,21 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, #endif // Based on the 'InProcessThinBackend' constructor in LLVM +#if LLVM_VERSION_GE(21, 0) + for (auto &Name : Data->Index.cfiFunctionDefs().symbols()) + CfiFunctionDefs.insert( + GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name))); + for (auto &Name : Data->Index.cfiFunctionDecls().symbols()) + CfiFunctionDecls.insert( + GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name))); +#else for (auto &Name : Data->Index.cfiFunctionDefs()) CfiFunctionDefs.insert( GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name))); for (auto &Name : Data->Index.cfiFunctionDecls()) CfiFunctionDecls.insert( GlobalValue::getGUID(GlobalValue::dropLLVMManglingEscape(Name))); +#endif #if LLVM_VERSION_GE(20, 0) Key = llvm::computeLTOCacheKey(conf, Data->Index, ModId, ImportList, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 2a3a7705b7b60..72924c0dd4b27 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -63,6 +63,18 @@ thread_local! { static FORCE_TRIMMED_PATH: Cell = const { Cell::new(false) }; static REDUCED_QUERIES: Cell = const { Cell::new(false) }; static NO_VISIBLE_PATH: Cell = const { Cell::new(false) }; + static RTN_MODE: Cell = const { Cell::new(RtnMode::ForDiagnostic) }; +} + +/// Rendering style for RTN types. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum RtnMode { + /// Print the RTN type as an impl trait with its path, i.e.e `impl Sized { T::method(..) }`. + ForDiagnostic, + /// Print the RTN type as an impl trait, i.e. `impl Sized`. + ForSignature, + /// Print the RTN type as a value path, i.e. `T::method(..): ...`. + ForSuggestion, } macro_rules! define_helper { @@ -124,6 +136,38 @@ define_helper!( fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH); ); +#[must_use] +pub struct RtnModeHelper(RtnMode); + +impl RtnModeHelper { + pub fn with(mode: RtnMode) -> RtnModeHelper { + RtnModeHelper(RTN_MODE.with(|c| c.replace(mode))) + } +} + +impl Drop for RtnModeHelper { + fn drop(&mut self) { + RTN_MODE.with(|c| c.set(self.0)) + } +} + +/// Print types for the purposes of a suggestion. +/// +/// Specifically, this will render RPITITs as `T::method(..)` which is suitable for +/// things like where-clauses. +pub macro with_types_for_suggestion($e:expr) {{ + let _guard = $crate::ty::print::pretty::RtnModeHelper::with(RtnMode::ForSuggestion); + $e +}} + +/// Print types for the purposes of a signature suggestion. +/// +/// Specifically, this will render RPITITs as `impl Trait` rather than `T::method(..)`. +pub macro with_types_for_signature($e:expr) {{ + let _guard = $crate::ty::print::pretty::RtnModeHelper::with(RtnMode::ForSignature); + $e +}} + /// Avoids running any queries during prints. pub macro with_no_queries($e:expr) {{ $crate::ty::print::with_reduced_queries!($crate::ty::print::with_forced_impl_filename_line!( @@ -1223,22 +1267,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } } - if self.tcx().features().return_type_notation() - && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) = - self.tcx().opt_rpitit_info(def_id) - && let ty::Alias(_, alias_ty) = - self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind() - && alias_ty.def_id == def_id - && let generics = self.tcx().generics_of(fn_def_id) - // FIXME(return_type_notation): We only support lifetime params for now. - && generics.own_params.iter().all(|param| matches!(param.kind, ty::GenericParamDefKind::Lifetime)) - { - let num_args = generics.count(); - write!(self, " {{ ")?; - self.print_def_path(fn_def_id, &args[..num_args])?; - write!(self, "(..) }}")?; - } - Ok(()) } @@ -1306,6 +1334,46 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ) } + fn pretty_print_rpitit( + &mut self, + def_id: DefId, + args: ty::GenericArgsRef<'tcx>, + ) -> Result<(), PrintError> { + let fn_args = if self.tcx().features().return_type_notation() + && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) = + self.tcx().opt_rpitit_info(def_id) + && let ty::Alias(_, alias_ty) = + self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind() + && alias_ty.def_id == def_id + && let generics = self.tcx().generics_of(fn_def_id) + // FIXME(return_type_notation): We only support lifetime params for now. + && generics.own_params.iter().all(|param| matches!(param.kind, ty::GenericParamDefKind::Lifetime)) + { + let num_args = generics.count(); + Some((fn_def_id, &args[..num_args])) + } else { + None + }; + + match (fn_args, RTN_MODE.with(|c| c.get())) { + (Some((fn_def_id, fn_args)), RtnMode::ForDiagnostic) => { + self.pretty_print_opaque_impl_type(def_id, args)?; + write!(self, " {{ ")?; + self.print_def_path(fn_def_id, fn_args)?; + write!(self, "(..) }}")?; + } + (Some((fn_def_id, fn_args)), RtnMode::ForSuggestion) => { + self.print_def_path(fn_def_id, fn_args)?; + write!(self, "(..)")?; + } + _ => { + self.pretty_print_opaque_impl_type(def_id, args)?; + } + } + + Ok(()) + } + fn ty_infer_name(&self, _: ty::TyVid) -> Option { None } @@ -3123,22 +3191,21 @@ define_print! { ty::AliasTerm<'tcx> { match self.kind(cx.tcx()) { ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)), - ty::AliasTermKind::ProjectionTy - | ty::AliasTermKind::WeakTy - | ty::AliasTermKind::OpaqueTy - | ty::AliasTermKind::UnevaluatedConst - | ty::AliasTermKind::ProjectionConst => { - // If we're printing verbosely, or don't want to invoke queries - // (`is_impl_trait_in_trait`), then fall back to printing the def path. - // This is likely what you want if you're debugging the compiler anyways. + ty::AliasTermKind::ProjectionTy => { if !(cx.should_print_verbose() || with_reduced_queries()) && cx.tcx().is_impl_trait_in_trait(self.def_id) { - return cx.pretty_print_opaque_impl_type(self.def_id, self.args); + p!(pretty_print_rpitit(self.def_id, self.args)) } else { p!(print_def_path(self.def_id, self.args)); } } + | ty::AliasTermKind::WeakTy + | ty::AliasTermKind::OpaqueTy + | ty::AliasTermKind::UnevaluatedConst + | ty::AliasTermKind::ProjectionConst => { + p!(print_def_path(self.def_id, self.args)); + } } } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index d78c874c76607..7f2e7d5ca8385 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -753,6 +753,11 @@ impl UnsafeOpKind { span: Span, suggest_unsafe_block: bool, ) { + if tcx.hir_opt_delegation_sig_id(hir_id.owner.def_id).is_some() { + // The body of the delegation item is synthesized, so it makes no sense + // to emit this lint. + return; + } let parent_id = tcx.hir_get_parent_item(hir_id); let parent_owner = tcx.hir_owner_node(parent_id); let should_suggest = parent_owner.fn_sig().is_some_and(|sig| { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d28988cd74f10..f3f6c55158068 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5117,12 +5117,18 @@ struct ItemInfoCollector<'a, 'ra, 'tcx> { } impl ItemInfoCollector<'_, '_, '_> { - fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId, attrs: &[Attribute]) { + fn collect_fn_info( + &mut self, + header: FnHeader, + decl: &FnDecl, + id: NodeId, + attrs: &[Attribute], + ) { let sig = DelegationFnSig { - header: sig.header, - param_count: sig.decl.inputs.len(), - has_self: sig.decl.has_self(), - c_variadic: sig.decl.c_variadic(), + header, + param_count: decl.inputs.len(), + has_self: decl.has_self(), + c_variadic: decl.c_variadic(), target_feature: attrs.iter().any(|attr| attr.has_name(sym::target_feature)), }; self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig); @@ -5142,7 +5148,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { | ItemKind::Trait(box Trait { generics, .. }) | ItemKind::TraitAlias(generics, _) => { if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind { - self.collect_fn_info(sig, item.id, &item.attrs); + self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs); } let def_id = self.r.local_def_id(item.id); @@ -5154,8 +5160,17 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { self.r.item_generics_num_lifetimes.insert(def_id, count); } + ItemKind::ForeignMod(ForeignMod { extern_span, safety: _, abi, items }) => { + for foreign_item in items { + if let ForeignItemKind::Fn(box Fn { sig, .. }) = &foreign_item.kind { + let new_header = + FnHeader { ext: Extern::from_abi(*abi, *extern_span), ..sig.header }; + self.collect_fn_info(new_header, &sig.decl, foreign_item.id, &item.attrs); + } + } + } + ItemKind::Mod(..) - | ItemKind::ForeignMod(..) | ItemKind::Static(..) | ItemKind::Use(..) | ItemKind::ExternCrate(..) @@ -5175,7 +5190,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) { if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { - self.collect_fn_info(sig, item.id, &item.attrs); + self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs); } visit::walk_assoc_item(self, item, ctxt); } diff --git a/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs index 55dc6a70627c9..8a4bc58e546e8 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32_wrs_vxworks.rs @@ -2,7 +2,7 @@ use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { - llvm_target: "riscv32".into(), + llvm_target: "riscv32-unknown-linux-gnu".into(), metadata: TargetMetadata { description: None, tier: Some(3), diff --git a/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs index 58ded24b9c599..39aa70035e4a7 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64_wrs_vxworks.rs @@ -2,7 +2,7 @@ use crate::spec::{StackProbeType, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { - llvm_target: "riscv64".into(), + llvm_target: "riscv64-unknown-linux-gnu".into(), metadata: TargetMetadata { description: None, tier: Some(3), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 4f89f3c2b4992..dce85b43df19e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -26,7 +26,7 @@ use rustc_middle::traits::IsConstable; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::print::{ PrintPolyTraitPredicateExt as _, PrintPolyTraitRefExt, PrintTraitPredicateExt as _, - with_forced_trimmed_paths, with_no_trimmed_paths, + with_forced_trimmed_paths, with_no_trimmed_paths, with_types_for_suggestion, }; use rustc_middle::ty::{ self, AdtKind, GenericArgs, InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder, @@ -110,7 +110,7 @@ impl<'a, 'tcx> CoroutineData<'a, 'tcx> { fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) { ( generics.tail_span_for_predicate_suggestion(), - format!("{} {}", generics.add_where_or_trailing_comma(), pred), + with_types_for_suggestion!(format!("{} {}", generics.add_where_or_trailing_comma(), pred)), ) } @@ -136,7 +136,8 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( if hir_generics.where_clause_span.from_expansion() || hir_generics.where_clause_span.desugaring_kind().is_some() || projection.is_some_and(|projection| { - tcx.is_impl_trait_in_trait(projection.def_id) + (tcx.is_impl_trait_in_trait(projection.def_id) + && !tcx.features().return_type_notation()) || tcx.lookup_stability(projection.def_id).is_some_and(|stab| stab.is_unstable()) }) { diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index ff4a4b35ce450..daba918af82c4 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1278,69 +1278,6 @@ where } } -impl HashMap -where - S: BuildHasher, -{ - /// Creates a raw entry builder for the `HashMap`. - /// - /// Raw entries provide the lowest level of control for searching and - /// manipulating a map. They must be manually initialized with a hash and - /// then manually searched. After this, insertions into a vacant entry - /// still require an owned key to be provided. - /// - /// Raw entries are useful for such exotic situations as: - /// - /// * Hash memoization - /// * Deferring the creation of an owned key until it is known to be required - /// * Using a search key that doesn't work with the Borrow trait - /// * Using custom comparison logic without newtype wrappers - /// - /// Because raw entries provide much more low-level control, it's much easier - /// to put the `HashMap` into an inconsistent state which, while memory-safe, - /// will cause the map to produce seemingly random results. Higher-level and - /// more foolproof APIs like `entry` should be preferred when possible. - /// - /// In particular, the hash used to initialize the raw entry must still be - /// consistent with the hash of the key that is ultimately stored in the entry. - /// This is because implementations of `HashMap` may need to recompute hashes - /// when resizing, at which point only the keys are available. - /// - /// Raw entries give mutable access to the keys. This must not be used - /// to modify how the key would compare or hash, as the map will not re-evaluate - /// where the key should go, meaning the keys may become "lost" if their - /// location does not reflect their state. For instance, if you change a key - /// so that the map now contains keys which compare equal, search may start - /// acting erratically, with two keys randomly masking each other. Implementations - /// are free to assume this doesn't happen (within the limits of memory-safety). - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> { - RawEntryBuilderMut { map: self } - } - - /// Creates a raw immutable entry builder for the `HashMap`. - /// - /// Raw entries provide the lowest level of control for searching and - /// manipulating a map. They must be manually initialized with a hash and - /// then manually searched. - /// - /// This is useful for - /// * Hash memoization - /// * Using a search key that doesn't work with the Borrow trait - /// * Using custom comparison logic without newtype wrappers - /// - /// Unless you are in such a situation, higher-level and more foolproof APIs like - /// `get` should be preferred. - /// - /// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> { - RawEntryBuilder { map: self } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Clone for HashMap where @@ -1828,404 +1765,6 @@ impl Default for IntoValues { } } -/// A builder for computing where in a HashMap a key-value pair would be stored. -/// -/// See the [`HashMap::raw_entry_mut`] docs for usage examples. -#[unstable(feature = "hash_raw_entry", issue = "56167")] -pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> { - map: &'a mut HashMap, -} - -/// A view into a single entry in a map, which may either be vacant or occupied. -/// -/// This is a lower-level version of [`Entry`]. -/// -/// This `enum` is constructed through the [`raw_entry_mut`] method on [`HashMap`], -/// then calling one of the methods of that [`RawEntryBuilderMut`]. -/// -/// [`raw_entry_mut`]: HashMap::raw_entry_mut -#[unstable(feature = "hash_raw_entry", issue = "56167")] -pub enum RawEntryMut<'a, K: 'a, V: 'a, S: 'a> { - /// An occupied entry. - Occupied(RawOccupiedEntryMut<'a, K, V, S>), - /// A vacant entry. - Vacant(RawVacantEntryMut<'a, K, V, S>), -} - -/// A view into an occupied entry in a `HashMap`. -/// It is part of the [`RawEntryMut`] enum. -#[unstable(feature = "hash_raw_entry", issue = "56167")] -pub struct RawOccupiedEntryMut<'a, K: 'a, V: 'a, S: 'a> { - base: base::RawOccupiedEntryMut<'a, K, V, S>, -} - -/// A view into a vacant entry in a `HashMap`. -/// It is part of the [`RawEntryMut`] enum. -#[unstable(feature = "hash_raw_entry", issue = "56167")] -pub struct RawVacantEntryMut<'a, K: 'a, V: 'a, S: 'a> { - base: base::RawVacantEntryMut<'a, K, V, S>, -} - -/// A builder for computing where in a HashMap a key-value pair would be stored. -/// -/// See the [`HashMap::raw_entry`] docs for usage examples. -#[unstable(feature = "hash_raw_entry", issue = "56167")] -pub struct RawEntryBuilder<'a, K: 'a, V: 'a, S: 'a> { - map: &'a HashMap, -} - -impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> -where - S: BuildHasher, -{ - /// Creates a `RawEntryMut` from the given key. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn from_key(self, k: &Q) -> RawEntryMut<'a, K, V, S> - where - K: Borrow, - Q: Hash + Eq, - { - map_raw_entry(self.map.base.raw_entry_mut().from_key(k)) - } - - /// Creates a `RawEntryMut` from the given key and its hash. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S> - where - K: Borrow, - Q: Eq, - { - map_raw_entry(self.map.base.raw_entry_mut().from_key_hashed_nocheck(hash, k)) - } - - /// Creates a `RawEntryMut` from the given hash. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn from_hash(self, hash: u64, is_match: F) -> RawEntryMut<'a, K, V, S> - where - for<'b> F: FnMut(&'b K) -> bool, - { - map_raw_entry(self.map.base.raw_entry_mut().from_hash(hash, is_match)) - } -} - -impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> -where - S: BuildHasher, -{ - /// Access an entry by key. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn from_key(self, k: &Q) -> Option<(&'a K, &'a V)> - where - K: Borrow, - Q: Hash + Eq, - { - self.map.base.raw_entry().from_key(k) - } - - /// Access an entry by a key and its hash. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)> - where - K: Borrow, - Q: Hash + Eq, - { - self.map.base.raw_entry().from_key_hashed_nocheck(hash, k) - } - - /// Access an entry by hash. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn from_hash(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> - where - F: FnMut(&K) -> bool, - { - self.map.base.raw_entry().from_hash(hash, is_match) - } -} - -impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { - /// Ensures a value is in the entry by inserting the default if empty, and returns - /// mutable references to the key and value in the entry. - /// - /// # Examples - /// - /// ``` - /// #![feature(hash_raw_entry)] - /// use std::collections::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 3); - /// assert_eq!(map["poneyland"], 3); - /// - /// *map.raw_entry_mut().from_key("poneyland").or_insert("poneyland", 10).1 *= 2; - /// assert_eq!(map["poneyland"], 6); - /// ``` - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V) - where - K: Hash, - S: BuildHasher, - { - match self { - RawEntryMut::Occupied(entry) => entry.into_key_value(), - RawEntryMut::Vacant(entry) => entry.insert(default_key, default_val), - } - } - - /// Ensures a value is in the entry by inserting the result of the default function if empty, - /// and returns mutable references to the key and value in the entry. - /// - /// # Examples - /// - /// ``` - /// #![feature(hash_raw_entry)] - /// use std::collections::HashMap; - /// - /// let mut map: HashMap<&str, String> = HashMap::new(); - /// - /// map.raw_entry_mut().from_key("poneyland").or_insert_with(|| { - /// ("poneyland", "hoho".to_string()) - /// }); - /// - /// assert_eq!(map["poneyland"], "hoho".to_string()); - /// ``` - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn or_insert_with(self, default: F) -> (&'a mut K, &'a mut V) - where - F: FnOnce() -> (K, V), - K: Hash, - S: BuildHasher, - { - match self { - RawEntryMut::Occupied(entry) => entry.into_key_value(), - RawEntryMut::Vacant(entry) => { - let (k, v) = default(); - entry.insert(k, v) - } - } - } - - /// Provides in-place mutable access to an occupied entry before any - /// potential inserts into the map. - /// - /// # Examples - /// - /// ``` - /// #![feature(hash_raw_entry)] - /// use std::collections::HashMap; - /// - /// let mut map: HashMap<&str, u32> = HashMap::new(); - /// - /// map.raw_entry_mut() - /// .from_key("poneyland") - /// .and_modify(|_k, v| { *v += 1 }) - /// .or_insert("poneyland", 42); - /// assert_eq!(map["poneyland"], 42); - /// - /// map.raw_entry_mut() - /// .from_key("poneyland") - /// .and_modify(|_k, v| { *v += 1 }) - /// .or_insert("poneyland", 0); - /// assert_eq!(map["poneyland"], 43); - /// ``` - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn and_modify(self, f: F) -> Self - where - F: FnOnce(&mut K, &mut V), - { - match self { - RawEntryMut::Occupied(mut entry) => { - { - let (k, v) = entry.get_key_value_mut(); - f(k, v); - } - RawEntryMut::Occupied(entry) - } - RawEntryMut::Vacant(entry) => RawEntryMut::Vacant(entry), - } - } -} - -impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { - /// Gets a reference to the key in the entry. - #[inline] - #[must_use] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn key(&self) -> &K { - self.base.key() - } - - /// Gets a mutable reference to the key in the entry. - #[inline] - #[must_use] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn key_mut(&mut self) -> &mut K { - self.base.key_mut() - } - - /// Converts the entry into a mutable reference to the key in the entry - /// with a lifetime bound to the map itself. - #[inline] - #[must_use = "`self` will be dropped if the result is not used"] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn into_key(self) -> &'a mut K { - self.base.into_key() - } - - /// Gets a reference to the value in the entry. - #[inline] - #[must_use] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn get(&self) -> &V { - self.base.get() - } - - /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry - /// with a lifetime bound to the map itself. - #[inline] - #[must_use = "`self` will be dropped if the result is not used"] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn into_mut(self) -> &'a mut V { - self.base.into_mut() - } - - /// Gets a mutable reference to the value in the entry. - #[inline] - #[must_use] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn get_mut(&mut self) -> &mut V { - self.base.get_mut() - } - - /// Gets a reference to the key and value in the entry. - #[inline] - #[must_use] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn get_key_value(&mut self) -> (&K, &V) { - self.base.get_key_value() - } - - /// Gets a mutable reference to the key and value in the entry. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) { - self.base.get_key_value_mut() - } - - /// Converts the `OccupiedEntry` into a mutable reference to the key and value in the entry - /// with a lifetime bound to the map itself. - #[inline] - #[must_use = "`self` will be dropped if the result is not used"] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn into_key_value(self) -> (&'a mut K, &'a mut V) { - self.base.into_key_value() - } - - /// Sets the value of the entry, and returns the entry's old value. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn insert(&mut self, value: V) -> V { - self.base.insert(value) - } - - /// Sets the value of the entry, and returns the entry's old value. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn insert_key(&mut self, key: K) -> K { - self.base.insert_key(key) - } - - /// Takes the value out of the entry, and returns it. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn remove(self) -> V { - self.base.remove() - } - - /// Take the ownership of the key and value from the map. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn remove_entry(self) -> (K, V) { - self.base.remove_entry() - } -} - -impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { - /// Sets the value of the entry with the `VacantEntry`'s key, - /// and returns a mutable reference to it. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) - where - K: Hash, - S: BuildHasher, - { - self.base.insert(key, value) - } - - /// Sets the value of the entry with the VacantEntry's key, - /// and returns a mutable reference to it. - #[inline] - #[unstable(feature = "hash_raw_entry", issue = "56167")] - pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) - where - K: Hash, - S: BuildHasher, - { - self.base.insert_hashed_nocheck(hash, key, value) - } -} - -#[unstable(feature = "hash_raw_entry", issue = "56167")] -impl Debug for RawEntryBuilderMut<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawEntryBuilder").finish_non_exhaustive() - } -} - -#[unstable(feature = "hash_raw_entry", issue = "56167")] -impl Debug for RawEntryMut<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(), - RawEntryMut::Occupied(ref o) => f.debug_tuple("RawEntry").field(o).finish(), - } - } -} - -#[unstable(feature = "hash_raw_entry", issue = "56167")] -impl Debug for RawOccupiedEntryMut<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawOccupiedEntryMut") - .field("key", self.key()) - .field("value", self.get()) - .finish_non_exhaustive() - } -} - -#[unstable(feature = "hash_raw_entry", issue = "56167")] -impl Debug for RawVacantEntryMut<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawVacantEntryMut").finish_non_exhaustive() - } -} - -#[unstable(feature = "hash_raw_entry", issue = "56167")] -impl Debug for RawEntryBuilder<'_, K, V, S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RawEntryBuilder").finish_non_exhaustive() - } -} - /// A view into a single entry in a map, which may either be vacant or occupied. /// /// This `enum` is constructed from the [`entry`] method on [`HashMap`]. @@ -3298,16 +2837,6 @@ pub(super) fn map_try_reserve_error(err: hashbrown::TryReserveError) -> TryReser } } -#[inline] -fn map_raw_entry<'a, K: 'a, V: 'a, S: 'a>( - raw: base::RawEntryMut<'a, K, V, S>, -) -> RawEntryMut<'a, K, V, S> { - match raw { - base::RawEntryMut::Occupied(base) => RawEntryMut::Occupied(RawOccupiedEntryMut { base }), - base::RawEntryMut::Vacant(base) => RawEntryMut::Vacant(RawVacantEntryMut { base }), - } -} - #[allow(dead_code)] fn assert_covariance() { fn map_key<'new>(v: HashMap<&'static str, u8>) -> HashMap<&'new str, u8> { diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs index a275488a55602..9f7df20a1d7e4 100644 --- a/library/std/src/collections/hash/map/tests.rs +++ b/library/std/src/collections/hash/map/tests.rs @@ -852,99 +852,6 @@ fn test_try_reserve() { } } -#[test] -fn test_raw_entry() { - use super::RawEntryMut::{Occupied, Vacant}; - - let xs = [(1i32, 10i32), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)]; - - let mut map: HashMap<_, _> = xs.iter().cloned().collect(); - - let compute_hash = |map: &HashMap, k: i32| -> u64 { - use core::hash::{BuildHasher, Hash, Hasher}; - - let mut hasher = map.hasher().build_hasher(); - k.hash(&mut hasher); - hasher.finish() - }; - - // Existing key (insert) - match map.raw_entry_mut().from_key(&1) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - assert_eq!(view.get(), &10); - assert_eq!(view.insert(100), 10); - } - } - let hash1 = compute_hash(&map, 1); - assert_eq!(map.raw_entry().from_key(&1).unwrap(), (&1, &100)); - assert_eq!(map.raw_entry().from_hash(hash1, |k| *k == 1).unwrap(), (&1, &100)); - assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash1, &1).unwrap(), (&1, &100)); - assert_eq!(map.len(), 6); - - // Existing key (update) - match map.raw_entry_mut().from_key(&2) { - Vacant(_) => unreachable!(), - Occupied(mut view) => { - let v = view.get_mut(); - let new_v = (*v) * 10; - *v = new_v; - } - } - let hash2 = compute_hash(&map, 2); - assert_eq!(map.raw_entry().from_key(&2).unwrap(), (&2, &200)); - assert_eq!(map.raw_entry().from_hash(hash2, |k| *k == 2).unwrap(), (&2, &200)); - assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash2, &2).unwrap(), (&2, &200)); - assert_eq!(map.len(), 6); - - // Existing key (take) - let hash3 = compute_hash(&map, 3); - match map.raw_entry_mut().from_key_hashed_nocheck(hash3, &3) { - Vacant(_) => unreachable!(), - Occupied(view) => { - assert_eq!(view.remove_entry(), (3, 30)); - } - } - assert_eq!(map.raw_entry().from_key(&3), None); - assert_eq!(map.raw_entry().from_hash(hash3, |k| *k == 3), None); - assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash3, &3), None); - assert_eq!(map.len(), 5); - - // Nonexistent key (insert) - match map.raw_entry_mut().from_key(&10) { - Occupied(_) => unreachable!(), - Vacant(view) => { - assert_eq!(view.insert(10, 1000), (&mut 10, &mut 1000)); - } - } - assert_eq!(map.raw_entry().from_key(&10).unwrap(), (&10, &1000)); - assert_eq!(map.len(), 6); - - // Ensure all lookup methods produce equivalent results. - for k in 0..12 { - let hash = compute_hash(&map, k); - let v = map.get(&k).cloned(); - let kv = v.as_ref().map(|v| (&k, v)); - - assert_eq!(map.raw_entry().from_key(&k), kv); - assert_eq!(map.raw_entry().from_hash(hash, |q| *q == k), kv); - assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &k), kv); - - match map.raw_entry_mut().from_key(&k) { - Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv), - Vacant(_) => assert_eq!(v, None), - } - match map.raw_entry_mut().from_key_hashed_nocheck(hash, &k) { - Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv), - Vacant(_) => assert_eq!(v, None), - } - match map.raw_entry_mut().from_hash(hash, |q| *q == k) { - Occupied(mut o) => assert_eq!(Some(o.get_key_value()), kv), - Vacant(_) => assert_eq!(v, None), - } - } -} - mod test_extract_if { use super::*; use crate::panic::{AssertUnwindSafe, catch_unwind}; diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index 5d257029a46e5..0a2d3ac63a7ad 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -377,7 +377,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn get_global_alloc_bytes( &self, id: AllocId, - kind: MemoryKind, bytes: &[u8], align: Align, ) -> InterpResult<'tcx, MiriAllocBytes> { @@ -386,7 +385,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`. // This additional call ensures that some `MiriAllocBytes` are always prepared, just in case // this function gets called before the first time `addr_from_alloc_id` gets called. - this.addr_from_alloc_id(id, kind)?; + this.addr_from_alloc_id(id, MiriMemoryKind::Global.into())?; // The memory we need here will have already been allocated during an earlier call to // `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead // fetch the previously prepared bytes from `prepared_alloc_bytes`. diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index dbb092f67286a..90beffbf83092 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -814,6 +814,59 @@ impl<'tcx> MiriMachine<'tcx> { .and_then(|(_allocated, deallocated)| *deallocated) .map(Span::data) } + + fn init_allocation( + ecx: &MiriInterpCx<'tcx>, + id: AllocId, + kind: MemoryKind, + size: Size, + align: Align, + ) -> InterpResult<'tcx, AllocExtra<'tcx>> { + if ecx.machine.tracked_alloc_ids.contains(&id) { + ecx.emit_diagnostic(NonHaltingDiagnostic::CreatedAlloc(id, size, align, kind)); + } + + let borrow_tracker = ecx + .machine + .borrow_tracker + .as_ref() + .map(|bt| bt.borrow_mut().new_allocation(id, size, kind, &ecx.machine)); + + let data_race = ecx.machine.data_race.as_ref().map(|data_race| { + data_race::AllocState::new_allocation( + data_race, + &ecx.machine.threads, + size, + kind, + ecx.machine.current_span(), + ) + }); + let weak_memory = ecx.machine.weak_memory.then(weak_memory::AllocState::new_allocation); + + // If an allocation is leaked, we want to report a backtrace to indicate where it was + // allocated. We don't need to record a backtrace for allocations which are allowed to + // leak. + let backtrace = if kind.may_leak() || !ecx.machine.collect_leak_backtraces { + None + } else { + Some(ecx.generate_stacktrace()) + }; + + if matches!(kind, MemoryKind::Machine(kind) if kind.should_save_allocation_span()) { + ecx.machine + .allocation_spans + .borrow_mut() + .insert(id, (ecx.machine.current_span(), None)); + } + + interp_ok(AllocExtra { + borrow_tracker, + data_race, + weak_memory, + backtrace, + sync: FxHashMap::default(), + }) + } } impl VisitProvenance for MiriMachine<'_> { @@ -1200,57 +1253,15 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } } - fn init_alloc_extra( + fn init_local_allocation( ecx: &MiriInterpCx<'tcx>, id: AllocId, kind: MemoryKind, size: Size, align: Align, ) -> InterpResult<'tcx, Self::AllocExtra> { - if ecx.machine.tracked_alloc_ids.contains(&id) { - ecx.emit_diagnostic(NonHaltingDiagnostic::CreatedAlloc(id, size, align, kind)); - } - - let borrow_tracker = ecx - .machine - .borrow_tracker - .as_ref() - .map(|bt| bt.borrow_mut().new_allocation(id, size, kind, &ecx.machine)); - - let data_race = ecx.machine.data_race.as_ref().map(|data_race| { - data_race::AllocState::new_allocation( - data_race, - &ecx.machine.threads, - size, - kind, - ecx.machine.current_span(), - ) - }); - let weak_memory = ecx.machine.weak_memory.then(weak_memory::AllocState::new_allocation); - - // If an allocation is leaked, we want to report a backtrace to indicate where it was - // allocated. We don't need to record a backtrace for allocations which are allowed to - // leak. - let backtrace = if kind.may_leak() || !ecx.machine.collect_leak_backtraces { - None - } else { - Some(ecx.generate_stacktrace()) - }; - - if matches!(kind, MemoryKind::Machine(kind) if kind.should_save_allocation_span()) { - ecx.machine - .allocation_spans - .borrow_mut() - .insert(id, (ecx.machine.current_span(), None)); - } - - interp_ok(AllocExtra { - borrow_tracker, - data_race, - weak_memory, - backtrace, - sync: FxHashMap::default(), - }) + assert!(kind != MiriMemoryKind::Global.into()); + MiriMachine::init_allocation(ecx, id, kind, size, align) } fn adjust_alloc_root_pointer( @@ -1340,13 +1351,13 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { alloc: &'b Allocation, ) -> InterpResult<'tcx, Cow<'b, Allocation>> { - let kind = Self::GLOBAL_KIND.unwrap().into(); let alloc = alloc.adjust_from_tcx( &ecx.tcx, - |bytes, align| ecx.get_global_alloc_bytes(id, kind, bytes, align), + |bytes, align| ecx.get_global_alloc_bytes(id, bytes, align), |ptr| ecx.global_root_pointer(ptr), )?; - let extra = Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?; + let kind = MiriMemoryKind::Global.into(); + let extra = MiriMachine::init_allocation(ecx, id, kind, alloc.size(), alloc.align)?; interp_ok(Cow::Owned(alloc.with_extra(extra))) } diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index ddcf315a2672d..e54747c129a0c 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -552,6 +552,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "html5ever" version = "0.27.0" @@ -874,9 +880,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.45" +version = "0.4.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07d36d96ffe1b5b16ddf2bc80b3b26bb7a498b2a6591061250bf0af8e8095ad" +checksum = "7e1a8fe3a4a01f28dab245c474cb7b95ccb4d3d2f17a5419a3d949f474c45e84" dependencies = [ "ammonia", "anyhow", @@ -886,6 +892,7 @@ dependencies = [ "elasticlunr-rs", "env_logger", "handlebars", + "hex", "log", "memchr", "once_cell", @@ -894,6 +901,7 @@ dependencies = [ "regex", "serde", "serde_json", + "sha2", "shlex", "tempfile", "toml 0.5.11", diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 6aec0bec0fa09..831233e3065d3 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -15,6 +15,6 @@ mdbook-i18n-helpers = "0.3.3" mdbook-spec = { path = "../../doc/reference/mdbook-spec" } [dependencies.mdbook] -version = "0.4.45" +version = "0.4.47" default-features = false features = ["search"] diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 33f2a51215dfe..4b510e308c977 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -151,6 +151,7 @@ fn get_book_dir(args: &ArgMatches) -> PathBuf { fn load_book(book_dir: &Path) -> Result3 { let mut book = MDBook::load(book_dir)?; book.config.set("output.html.input-404", "").unwrap(); + book.config.set("output.html.hash-files", true).unwrap(); Ok(book) } diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr index 0a31cc6753340..459f3ea164202 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr @@ -15,6 +15,10 @@ note: required by a bound in `is_send` | LL | fn is_send(_: impl Send) {} | ^^^^ required by this bound in `is_send` +help: consider further restricting the associated type + | +LL | >() where ::method(..): Send { + | ++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/return-type-notation/display.stderr b/tests/ui/associated-type-bounds/return-type-notation/display.stderr index b895d79695272..a614089ce407a 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/display.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/display.stderr @@ -11,6 +11,10 @@ note: required by a bound in `needs_trait` | LL | fn needs_trait(_: impl Trait) {} | ^^^^^ required by this bound in `needs_trait` +help: consider further restricting the associated type + | +LL | fn foo(t: T) where ::method(..): Trait { + | +++++++++++++++++++++++++++++++++++++ error[E0277]: the trait bound `impl Sized { ::method_with_lt(..) }: Trait` is not satisfied --> $DIR/display.rs:16:17 @@ -25,6 +29,10 @@ note: required by a bound in `needs_trait` | LL | fn needs_trait(_: impl Trait) {} | ^^^^^ required by this bound in `needs_trait` +help: consider further restricting the associated type + | +LL | fn foo(t: T) where ::method_with_lt(..): Trait { + | +++++++++++++++++++++++++++++++++++++++++++++ error[E0277]: the trait bound `impl Sized: Trait` is not satisfied --> $DIR/display.rs:18:17 diff --git a/tests/ui/associated-type-bounds/return-type-notation/rendering.fixed b/tests/ui/associated-type-bounds/return-type-notation/rendering.fixed new file mode 100644 index 0000000000000..72c174a0ca020 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/rendering.fixed @@ -0,0 +1,15 @@ +//@ run-rustfix + +#![allow(unused)] +#![feature(return_type_notation)] + +trait Foo { + fn missing() -> impl Sized; +} + +impl Foo for () { + //~^ ERROR not all trait items implemented, missing: `missing` +fn missing() -> impl Sized { todo!() } +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/rendering.rs b/tests/ui/associated-type-bounds/return-type-notation/rendering.rs new file mode 100644 index 0000000000000..4c9948d4c0604 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/rendering.rs @@ -0,0 +1,14 @@ +//@ run-rustfix + +#![allow(unused)] +#![feature(return_type_notation)] + +trait Foo { + fn missing() -> impl Sized; +} + +impl Foo for () { + //~^ ERROR not all trait items implemented, missing: `missing` +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/rendering.stderr b/tests/ui/associated-type-bounds/return-type-notation/rendering.stderr new file mode 100644 index 0000000000000..62fdeb059dd84 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/rendering.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `missing` + --> $DIR/rendering.rs:10:1 + | +LL | fn missing() -> impl Sized; + | --------------------------- `missing` from trait +... +LL | impl Foo for () { + | ^^^^^^^^^^^^^^^ missing `missing` in implementation + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/delegation/foreign-fn.rs b/tests/ui/delegation/foreign-fn.rs new file mode 100644 index 0000000000000..1d221da29ceb2 --- /dev/null +++ b/tests/ui/delegation/foreign-fn.rs @@ -0,0 +1,22 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![deny(unsafe_op_in_unsafe_fn)] +#![deny(unused_unsafe)] + +mod to_reuse { + unsafe extern "C" { + pub fn default_unsafe_foo(); + pub unsafe fn unsafe_foo(); + pub safe fn safe_foo(); + } +} + +reuse to_reuse::{default_unsafe_foo, unsafe_foo, safe_foo}; + +fn main() { + let _: extern "C" fn() = default_unsafe_foo; + //~^ ERROR mismatched types + let _: extern "C" fn() = unsafe_foo; + //~^ ERROR mismatched types + let _: extern "C" fn() = safe_foo; +} diff --git a/tests/ui/delegation/foreign-fn.stderr b/tests/ui/delegation/foreign-fn.stderr new file mode 100644 index 0000000000000..f7d3dba4bb1c0 --- /dev/null +++ b/tests/ui/delegation/foreign-fn.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/foreign-fn.rs:17:30 + | +LL | let _: extern "C" fn() = default_unsafe_foo; + | --------------- ^^^^^^^^^^^^^^^^^^ expected safe fn, found unsafe fn + | | + | expected due to this + | + = note: expected fn pointer `extern "C" fn()` + found fn item `unsafe extern "C" fn() {default_unsafe_foo}` + = note: unsafe functions cannot be coerced into safe function pointers + +error[E0308]: mismatched types + --> $DIR/foreign-fn.rs:19:30 + | +LL | let _: extern "C" fn() = unsafe_foo; + | --------------- ^^^^^^^^^^ expected safe fn, found unsafe fn + | | + | expected due to this + | + = note: expected fn pointer `extern "C" fn()` + found fn item `unsafe extern "C" fn() {unsafe_foo}` + = note: unsafe functions cannot be coerced into safe function pointers + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`.