diff --git a/compiler/rustc_data_structures/src/base_n/tests.rs b/compiler/rustc_data_structures/src/base_n/tests.rs index b68ef1eb7f4c4..2be2f0532c99c 100644 --- a/compiler/rustc_data_structures/src/base_n/tests.rs +++ b/compiler/rustc_data_structures/src/base_n/tests.rs @@ -15,7 +15,9 @@ fn test_encode() { test(u64::MAX as u128, base); test(u128::MAX, base); - for i in 0..1_000 { + const N: u128 = if cfg!(miri) { 10 } else { 1000 }; + + for i in 0..N { test(i * 983, base); } } diff --git a/compiler/rustc_data_structures/src/graph/scc/tests.rs b/compiler/rustc_data_structures/src/graph/scc/tests.rs index 364005e67e63f..9940fee60d7d8 100644 --- a/compiler/rustc_data_structures/src/graph/scc/tests.rs +++ b/compiler/rustc_data_structures/src/graph/scc/tests.rs @@ -156,7 +156,10 @@ fn test_deep_linear() { v … */ + #[cfg(not(miri))] const NR_NODES: usize = 1 << 14; + #[cfg(miri)] + const NR_NODES: usize = 1 << 3; let mut nodes = vec![]; for i in 1..NR_NODES { nodes.push((i - 1, i)); diff --git a/compiler/rustc_data_structures/src/owning_ref/tests.rs b/compiler/rustc_data_structures/src/owning_ref/tests.rs index 7b8179e90bd07..320c03d5139f4 100644 --- a/compiler/rustc_data_structures/src/owning_ref/tests.rs +++ b/compiler/rustc_data_structures/src/owning_ref/tests.rs @@ -1,3 +1,5 @@ +// FIXME: owning_ref is not sound under stacked borrows. Preferably, get rid of it. +#[cfg(not(miri))] mod owning_ref { use super::super::OwningRef; use super::super::{BoxRef, Erased, ErasedBoxRef, RcRef}; @@ -361,6 +363,8 @@ mod owning_handle { } } +// FIXME: owning_ref is not sound under stacked borrows. Preferably, get rid of it. +#[cfg(not(miri))] mod owning_ref_mut { use super::super::BoxRef; use super::super::{BoxRefMut, Erased, ErasedBoxRefMut, OwningRefMut}; diff --git a/compiler/rustc_data_structures/src/sip128.rs b/compiler/rustc_data_structures/src/sip128.rs index abd25f46ad54f..90793a97ed0d8 100644 --- a/compiler/rustc_data_structures/src/sip128.rs +++ b/compiler/rustc_data_structures/src/sip128.rs @@ -255,8 +255,9 @@ impl SipHasher128 { // elements from spill (at most LEN - 1 bytes could have overflowed // into the spill). The memcpy call is optimized away because the size // is known. And the whole copy is optimized away for LEN == 1. + let dst = self.buf.as_mut_ptr() as *mut u8; let src = self.buf.get_unchecked(BUFFER_SPILL_INDEX) as *const _ as *const u8; - ptr::copy_nonoverlapping(src, self.buf.as_mut_ptr() as *mut u8, LEN - 1); + ptr::copy_nonoverlapping(src, dst, LEN - 1); // This function should only be called when the write fills the buffer. // Therefore, when LEN == 1, the new `self.nbuf` must be zero. diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 899d6c7e490a6..24531e461896b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1728,8 +1728,8 @@ rustc_queries! { query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap> { desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) } } - query maybe_unused_trait_import(def_id: LocalDefId) -> bool { - desc { |tcx| "maybe_unused_trait_import for `{}`", tcx.def_path_str(def_id.to_def_id()) } + query maybe_unused_trait_imports(_: ()) -> &'tcx FxIndexSet { + desc { "fetching potentially unused trait imports" } } query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] { desc { "looking up all possibly unused extern crates" } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 72e2beb372d3c..ac71146303ac2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2893,8 +2893,8 @@ pub fn provide(providers: &mut ty::query::Providers) { assert_eq!(id, LOCAL_CRATE); tcx.crate_name }; - providers.maybe_unused_trait_import = - |tcx, id| tcx.resolutions(()).maybe_unused_trait_imports.contains(&id); + providers.maybe_unused_trait_imports = + |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports; providers.maybe_unused_extern_crates = |tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..]; providers.names_imported_by_glob_use = |tcx, id| { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a493aaac276b1..3a2d3408b9d93 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -28,7 +28,7 @@ pub use generics::*; use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; @@ -138,7 +138,7 @@ pub struct ResolverOutputs { pub has_pub_restricted: bool, pub access_levels: AccessLevels, pub extern_crate_map: FxHashMap, - pub maybe_unused_trait_imports: FxHashSet, + pub maybe_unused_trait_imports: FxIndexSet, pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, pub reexport_map: FxHashMap>, pub glob_map: FxHashMap>, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 64c63e3d567d0..08879afa64a0e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2190,34 +2190,40 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { // this is not *quite* right and changes the ordering of some output // anyways. let (new_value, map) = if self.tcx().sess.verbose() { - // anon index + 1 (BrEnv takes 0) -> name - let mut region_map: FxHashMap<_, _> = Default::default(); - let bound_vars = value.bound_vars(); - for var in bound_vars { - let ty::BoundVariableKind::Region(var) = var else { continue }; - match var { - ty::BrAnon(_) | ty::BrEnv => { - start_or_continue(&mut self, "for<", ", "); - let name = next_name(&self); - do_continue(&mut self, name); - region_map.insert(var, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)); - } - ty::BrNamed(def_id, kw::UnderscoreLifetime) => { - start_or_continue(&mut self, "for<", ", "); - let name = next_name(&self); - do_continue(&mut self, name); - region_map.insert(var, ty::BrNamed(def_id, name)); - } - ty::BrNamed(_, name) => { - start_or_continue(&mut self, "for<", ", "); - do_continue(&mut self, name); + let regions: Vec<_> = value + .bound_vars() + .into_iter() + .map(|var| { + let ty::BoundVariableKind::Region(var) = var else { + // This doesn't really matter because it doesn't get used, + // it's just an empty value + return ty::BrAnon(0); + }; + match var { + ty::BrAnon(_) | ty::BrEnv => { + start_or_continue(&mut self, "for<", ", "); + let name = next_name(&self); + do_continue(&mut self, name); + ty::BrNamed(CRATE_DEF_ID.to_def_id(), name) + } + ty::BrNamed(def_id, kw::UnderscoreLifetime) => { + start_or_continue(&mut self, "for<", ", "); + let name = next_name(&self); + do_continue(&mut self, name); + ty::BrNamed(def_id, name) + } + ty::BrNamed(def_id, name) => { + start_or_continue(&mut self, "for<", ", "); + do_continue(&mut self, name); + ty::BrNamed(def_id, name) + } } - } - } + }) + .collect(); start_or_continue(&mut self, "", "> "); self.tcx.replace_late_bound_regions(value.clone(), |br| { - let kind = region_map[&br.kind]; + let kind = regions[br.var.as_usize()]; self.tcx.mk_region(ty::ReLateBound( ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 65f41c5266d17..59794c4d3f0d8 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -37,7 +37,7 @@ use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, T use rustc_ast as ast; use rustc_ast::expand::allocator::AllocatorKind; use rustc_attr as attr; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 73c8a9d28bd5f..49c15d2c9ef1f 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -28,7 +28,7 @@ use rustc_ast::node_id::NodeMap; use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID}; use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path}; use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed}; @@ -941,7 +941,7 @@ pub struct Resolver<'a> { visibilities: FxHashMap, has_pub_restricted: bool, used_imports: FxHashSet, - maybe_unused_trait_imports: FxHashSet, + maybe_unused_trait_imports: FxIndexSet, maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, /// Privacy errors are delayed until the end in order to deduplicate them. diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs index 00f0d1e6f02a9..f28184c74d355 100644 --- a/compiler/rustc_typeck/src/check_unused.rs +++ b/compiler/rustc_typeck/src/check_unused.rs @@ -16,48 +16,32 @@ pub fn check_crate(tcx: TyCtxt<'_>) { used_trait_imports.extend(imports.iter()); } - for id in tcx.hir().items() { - if matches!(tcx.def_kind(id.def_id), DefKind::Use) { - if tcx.visibility(id.def_id).is_public() { - continue; - } - let item = tcx.hir().item(id); - if item.span.is_dummy() { - continue; - } - if let hir::ItemKind::Use(path, _) = item.kind { - check_import(tcx, &mut used_trait_imports, item.item_id(), path.span); - } + for &id in tcx.maybe_unused_trait_imports(()) { + debug_assert_eq!(tcx.def_kind(id), DefKind::Use); + if tcx.visibility(id).is_public() { + continue; + } + if used_trait_imports.contains(&id) { + continue; } + let item = tcx.hir().expect_item(id); + if item.span.is_dummy() { + continue; + } + let hir::ItemKind::Use(path, _) = item.kind else { unreachable!() }; + tcx.struct_span_lint_hir(lint::builtin::UNUSED_IMPORTS, item.hir_id(), path.span, |lint| { + let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) { + format!("unused import: `{}`", snippet) + } else { + "unused import".to_owned() + }; + lint.build(&msg).emit(); + }); } unused_crates_lint(tcx); } -fn check_import<'tcx>( - tcx: TyCtxt<'tcx>, - used_trait_imports: &mut FxHashSet, - item_id: hir::ItemId, - span: Span, -) { - if !tcx.maybe_unused_trait_import(item_id.def_id) { - return; - } - - if used_trait_imports.contains(&item_id.def_id) { - return; - } - - tcx.struct_span_lint_hir(lint::builtin::UNUSED_IMPORTS, item_id.hir_id(), span, |lint| { - let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) { - format!("unused import: `{}`", snippet) - } else { - "unused import".to_owned() - }; - lint.build(&msg).emit(); - }); -} - fn unused_crates_lint(tcx: TyCtxt<'_>) { let lint = lint::builtin::UNUSED_EXTERN_CRATES; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 7e9d7d2710180..9505ec31609f5 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -84,6 +84,7 @@ #![feature(const_option)] #![feature(const_option_ext)] #![feature(const_result)] +#![feature(const_intrinsic_copy)] #![feature(integer_atomics)] #![feature(int_roundings)] #![feature(slice_group_by)] diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index c5242ad04de84..40b2b49bdbd7d 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -1,4 +1,5 @@ use core::cell::RefCell; +use core::mem::{self, MaybeUninit}; use core::num::NonZeroUsize; use core::ptr; use core::ptr::*; @@ -781,3 +782,42 @@ fn nonnull_tagged_pointer_with_provenance() { } } } + +#[test] +fn test_const_copy() { + const { + let ptr1 = &1; + let mut ptr2 = &666; + + // Copy ptr1 to ptr2, bytewise. + unsafe { + ptr::copy( + &ptr1 as *const _ as *const MaybeUninit, + &mut ptr2 as *mut _ as *mut MaybeUninit, + mem::size_of::<&i32>(), + ); + } + + // Make sure they still work. + assert!(*ptr1 == 1); + assert!(*ptr2 == 1); + }; + + const { + let ptr1 = &1; + let mut ptr2 = &666; + + // Copy ptr1 to ptr2, bytewise. + unsafe { + ptr::copy_nonoverlapping( + &ptr1 as *const _ as *const MaybeUninit, + &mut ptr2 as *mut _ as *mut MaybeUninit, + mem::size_of::<&i32>(), + ); + } + + // Make sure they still work. + assert!(*ptr1 == 1); + assert!(*ptr2 == 1); + }; +} diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index 9f26ccc74d182..b236bd7be4f0c 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId; pub(crate) use renderer::{run_format, FormatRenderer}; use crate::clean::{self, ItemId}; -use cache::Cache; +use crate::html::render::Context; /// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// impl. @@ -65,7 +65,8 @@ impl Impl { // Returns true if this is an implementation on a "local" type, meaning: // the type is in the current crate, or the type and the trait are both // re-exported by the current crate. - pub(crate) fn is_on_local_type(&self, cache: &Cache) -> bool { + pub(crate) fn is_on_local_type(&self, cx: &Context<'_>) -> bool { + let cache = cx.cache(); let for_type = &self.inner_impl().for_; if let Some(for_type_did) = for_type.def_id(cache) { // The "for" type is local if it's in the paths for the current crate. @@ -80,6 +81,18 @@ impl Impl { if for_type_did.krate == trait_did.krate { return true; } + // Hack: many traits and types in std are re-exported from + // core or alloc. In general, rustdoc is capable of recognizing + // these implementations as being on local types. However, in at + // least one case (https://github.com/rust-lang/rust/issues/97610), + // rustdoc gets confused and labels an implementation as being on + // a foreign type. To make sure that confusion doesn't pass on to + // the reader, consider all implementations in std, core, and alloc + // to be on local types. + let crate_name = cx.tcx().crate_name(trait_did.krate); + if matches!(crate_name.as_str(), "std" | "core" | "alloc") { + return true; + } } return false; }; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 0b801a20995d3..23ce634cf286b 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2281,11 +2281,10 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean |sym| format!("{0}", sym, ItemType::Method), ); - let cache = cx.cache(); - if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) { + if let Some(implementors) = cx.cache().implementors.get(&it.item_id.expect_def_id()) { let mut res = implementors .iter() - .filter(|i| !i.is_on_local_type(cache)) + .filter(|i| !i.is_on_local_type(cx)) .filter_map(|i| extract_for_impl_name(&i.impl_item, cx)) .collect::>(); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 8683e6dfcd99e..d115185562ce4 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -823,7 +823,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } let (local, foreign) = - implementors.iter().partition::, _>(|i| i.is_on_local_type(cache)); + implementors.iter().partition::, _>(|i| i.is_on_local_type(cx)); let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) = local.iter().partition(|i| i.inner_impl().kind.is_auto()); diff --git a/src/test/ui/generator/issue-87142.rs b/src/test/ui/generator/issue-87142.rs new file mode 100644 index 0000000000000..fc10d04d46cfb --- /dev/null +++ b/src/test/ui/generator/issue-87142.rs @@ -0,0 +1,32 @@ +// compile-flags: -Cdebuginfo=2 +// build-pass + +// Regression test for #87142 +// This test needs the above flags and the "lib" crate type. + +#![feature(type_alias_impl_trait, generator_trait, generators)] +#![crate_type = "lib"] + +use std::ops::Generator; + +pub trait GeneratorProviderAlt: Sized { + type Gen: Generator<(), Return = (), Yield = ()>; + + fn start(ctx: Context) -> Self::Gen; +} + +pub struct Context { + pub link: Box, +} + +impl GeneratorProviderAlt for () { + type Gen = impl Generator<(), Return = (), Yield = ()>; + fn start(ctx: Context) -> Self::Gen { + move || { + match ctx { + _ => (), + } + yield (); + } + } +}