Auto merge of #97742 - matthiaskrgr:rollup-fr3j0t8, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #97609 (Iterate over `maybe_unused_trait_imports` when checking dead trait imports) - #97688 (test const_copy to make sure bytewise pointer copies are working) - #97707 (Improve soundness of rustc_data_structures) - #97731 (Add regresion test for #87142) - #97735 (Don't generate "Impls on Foreign Types" for std) - #97737 (Fix pretty printing named bound regions under -Zverbose) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
43874a2ee7
17 changed files with 162 additions and 77 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1728,8 +1728,8 @@ rustc_queries! {
|
|||
query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>> {
|
||||
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<LocalDefId> {
|
||||
desc { "fetching potentially unused trait imports" }
|
||||
}
|
||||
query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] {
|
||||
desc { "looking up all possibly unused extern crates" }
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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<LocalDefId, CrateNum>,
|
||||
pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
|
||||
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
|
||||
pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
|
||||
pub reexport_map: FxHashMap<LocalDefId, Vec<ModChild>>,
|
||||
pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
|
||||
|
|
|
@ -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 };
|
||||
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);
|
||||
region_map.insert(var, ty::BrNamed(CRATE_DEF_ID.to_def_id(), 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);
|
||||
region_map.insert(var, ty::BrNamed(def_id, name));
|
||||
ty::BrNamed(def_id, name)
|
||||
}
|
||||
ty::BrNamed(_, 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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<LocalDefId, ty::Visibility>,
|
||||
has_pub_restricted: bool,
|
||||
used_imports: FxHashSet<NodeId>,
|
||||
maybe_unused_trait_imports: FxHashSet<LocalDefId>,
|
||||
maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
|
||||
maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
|
||||
|
||||
/// Privacy errors are delayed until the end in order to deduplicate them.
|
||||
|
|
|
@ -16,46 +16,30 @@ 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() {
|
||||
for &id in tcx.maybe_unused_trait_imports(()) {
|
||||
debug_assert_eq!(tcx.def_kind(id), DefKind::Use);
|
||||
if tcx.visibility(id).is_public() {
|
||||
continue;
|
||||
}
|
||||
let item = tcx.hir().item(id);
|
||||
if used_trait_imports.contains(&id) {
|
||||
continue;
|
||||
}
|
||||
let item = tcx.hir().expect_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_crates_lint(tcx);
|
||||
}
|
||||
|
||||
fn check_import<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
used_trait_imports: &mut FxHashSet<LocalDefId>,
|
||||
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) {
|
||||
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 unused_crates_lint(tcx: TyCtxt<'_>) {
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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<u8>,
|
||||
&mut ptr2 as *mut _ as *mut MaybeUninit<u8>,
|
||||
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<u8>,
|
||||
&mut ptr2 as *mut _ as *mut MaybeUninit<u8>,
|
||||
mem::size_of::<&i32>(),
|
||||
);
|
||||
}
|
||||
|
||||
// Make sure they still work.
|
||||
assert!(*ptr1 == 1);
|
||||
assert!(*ptr2 == 1);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -2281,11 +2281,10 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
|
|||
|sym| format!("<a href=\"#{1}.{0}\">{0}</a>", 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::<Vec<_>>();
|
||||
|
||||
|
|
|
@ -823,7 +823,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
|||
}
|
||||
|
||||
let (local, foreign) =
|
||||
implementors.iter().partition::<Vec<_>, _>(|i| i.is_on_local_type(cache));
|
||||
implementors.iter().partition::<Vec<_>, _>(|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());
|
||||
|
|
32
src/test/ui/generator/issue-87142.rs
Normal file
32
src/test/ui/generator/issue-87142.rs
Normal file
|
@ -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>) -> Self::Gen;
|
||||
}
|
||||
|
||||
pub struct Context<G: 'static + GeneratorProviderAlt> {
|
||||
pub link: Box<G::Gen>,
|
||||
}
|
||||
|
||||
impl GeneratorProviderAlt for () {
|
||||
type Gen = impl Generator<(), Return = (), Yield = ()>;
|
||||
fn start(ctx: Context<Self>) -> Self::Gen {
|
||||
move || {
|
||||
match ctx {
|
||||
_ => (),
|
||||
}
|
||||
yield ();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue