1
Fork 0

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:
bors 2022-06-04 23:14:09 +00:00
commit 43874a2ee7
17 changed files with 162 additions and 77 deletions

View file

@ -15,7 +15,9 @@ fn test_encode() {
test(u64::MAX as u128, base); test(u64::MAX as u128, base);
test(u128::MAX, 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); test(i * 983, base);
} }
} }

View file

@ -156,7 +156,10 @@ fn test_deep_linear() {
v v
*/ */
#[cfg(not(miri))]
const NR_NODES: usize = 1 << 14; const NR_NODES: usize = 1 << 14;
#[cfg(miri)]
const NR_NODES: usize = 1 << 3;
let mut nodes = vec![]; let mut nodes = vec![];
for i in 1..NR_NODES { for i in 1..NR_NODES {
nodes.push((i - 1, i)); nodes.push((i - 1, i));

View file

@ -1,3 +1,5 @@
// FIXME: owning_ref is not sound under stacked borrows. Preferably, get rid of it.
#[cfg(not(miri))]
mod owning_ref { mod owning_ref {
use super::super::OwningRef; use super::super::OwningRef;
use super::super::{BoxRef, Erased, ErasedBoxRef, RcRef}; 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 { mod owning_ref_mut {
use super::super::BoxRef; use super::super::BoxRef;
use super::super::{BoxRefMut, Erased, ErasedBoxRefMut, OwningRefMut}; use super::super::{BoxRefMut, Erased, ErasedBoxRefMut, OwningRefMut};

View file

@ -255,8 +255,9 @@ impl SipHasher128 {
// elements from spill (at most LEN - 1 bytes could have overflowed // elements from spill (at most LEN - 1 bytes could have overflowed
// into the spill). The memcpy call is optimized away because the size // into the spill). The memcpy call is optimized away because the size
// is known. And the whole copy is optimized away for LEN == 1. // 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; 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. // This function should only be called when the write fills the buffer.
// Therefore, when LEN == 1, the new `self.nbuf` must be zero. // Therefore, when LEN == 1, the new `self.nbuf` must be zero.

View file

@ -1728,8 +1728,8 @@ rustc_queries! {
query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>> { 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) } desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) }
} }
query maybe_unused_trait_import(def_id: LocalDefId) -> bool { query maybe_unused_trait_imports(_: ()) -> &'tcx FxIndexSet<LocalDefId> {
desc { |tcx| "maybe_unused_trait_import for `{}`", tcx.def_path_str(def_id.to_def_id()) } desc { "fetching potentially unused trait imports" }
} }
query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] { query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] {
desc { "looking up all possibly unused extern crates" } desc { "looking up all possibly unused extern crates" }

View file

@ -2893,8 +2893,8 @@ pub fn provide(providers: &mut ty::query::Providers) {
assert_eq!(id, LOCAL_CRATE); assert_eq!(id, LOCAL_CRATE);
tcx.crate_name tcx.crate_name
}; };
providers.maybe_unused_trait_import = providers.maybe_unused_trait_imports =
|tcx, id| tcx.resolutions(()).maybe_unused_trait_imports.contains(&id); |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
providers.maybe_unused_extern_crates = providers.maybe_unused_extern_crates =
|tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..]; |tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..];
providers.names_imported_by_glob_use = |tcx, id| { providers.names_imported_by_glob_use = |tcx, id| {

View file

@ -28,7 +28,7 @@ pub use generics::*;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_data_structures::fingerprint::Fingerprint; 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::intern::{Interned, WithStableHash};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
@ -138,7 +138,7 @@ pub struct ResolverOutputs {
pub has_pub_restricted: bool, pub has_pub_restricted: bool,
pub access_levels: AccessLevels, pub access_levels: AccessLevels,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>, 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 maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
pub reexport_map: FxHashMap<LocalDefId, Vec<ModChild>>, pub reexport_map: FxHashMap<LocalDefId, Vec<ModChild>>,
pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>, pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,

View file

@ -2190,34 +2190,40 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
// this is not *quite* right and changes the ordering of some output // this is not *quite* right and changes the ordering of some output
// anyways. // anyways.
let (new_value, map) = if self.tcx().sess.verbose() { let (new_value, map) = if self.tcx().sess.verbose() {
// anon index + 1 (BrEnv takes 0) -> name let regions: Vec<_> = value
let mut region_map: FxHashMap<_, _> = Default::default(); .bound_vars()
let bound_vars = value.bound_vars(); .into_iter()
for var in bound_vars { .map(|var| {
let ty::BoundVariableKind::Region(var) = var else { continue }; let ty::BoundVariableKind::Region(var) = var else {
match var { // This doesn't really matter because it doesn't get used,
ty::BrAnon(_) | ty::BrEnv => { // it's just an empty value
start_or_continue(&mut self, "for<", ", "); return ty::BrAnon(0);
let name = next_name(&self); };
do_continue(&mut self, name); match var {
region_map.insert(var, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)); 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)
}
} }
ty::BrNamed(def_id, kw::UnderscoreLifetime) => { })
start_or_continue(&mut self, "for<", ", "); .collect();
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);
}
}
}
start_or_continue(&mut self, "", "> "); start_or_continue(&mut self, "", "> ");
self.tcx.replace_late_bound_regions(value.clone(), |br| { 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( self.tcx.mk_region(ty::ReLateBound(
ty::INNERMOST, ty::INNERMOST,
ty::BoundRegion { var: br.var, kind }, ty::BoundRegion { var: br.var, kind },

View file

@ -37,7 +37,7 @@ use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, T
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind; use rustc_ast::expand::allocator::AllocatorKind;
use rustc_attr as attr; 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::steal::Steal;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;

View file

@ -28,7 +28,7 @@ use rustc_ast::node_id::NodeMap;
use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID}; use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID};
use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path}; use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering}; 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::intern::Interned;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed};
@ -941,7 +941,7 @@ pub struct Resolver<'a> {
visibilities: FxHashMap<LocalDefId, ty::Visibility>, visibilities: FxHashMap<LocalDefId, ty::Visibility>,
has_pub_restricted: bool, has_pub_restricted: bool,
used_imports: FxHashSet<NodeId>, used_imports: FxHashSet<NodeId>,
maybe_unused_trait_imports: FxHashSet<LocalDefId>, maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
/// Privacy errors are delayed until the end in order to deduplicate them. /// Privacy errors are delayed until the end in order to deduplicate them.

View file

@ -16,48 +16,32 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
used_trait_imports.extend(imports.iter()); used_trait_imports.extend(imports.iter());
} }
for id in tcx.hir().items() { for &id in tcx.maybe_unused_trait_imports(()) {
if matches!(tcx.def_kind(id.def_id), DefKind::Use) { debug_assert_eq!(tcx.def_kind(id), DefKind::Use);
if tcx.visibility(id.def_id).is_public() { if tcx.visibility(id).is_public() {
continue; 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);
}
} }
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); 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) {
format!("unused import: `{}`", snippet)
} else {
"unused import".to_owned()
};
lint.build(&msg).emit();
});
}
fn unused_crates_lint(tcx: TyCtxt<'_>) { fn unused_crates_lint(tcx: TyCtxt<'_>) {
let lint = lint::builtin::UNUSED_EXTERN_CRATES; let lint = lint::builtin::UNUSED_EXTERN_CRATES;

View file

@ -84,6 +84,7 @@
#![feature(const_option)] #![feature(const_option)]
#![feature(const_option_ext)] #![feature(const_option_ext)]
#![feature(const_result)] #![feature(const_result)]
#![feature(const_intrinsic_copy)]
#![feature(integer_atomics)] #![feature(integer_atomics)]
#![feature(int_roundings)] #![feature(int_roundings)]
#![feature(slice_group_by)] #![feature(slice_group_by)]

View file

@ -1,4 +1,5 @@
use core::cell::RefCell; use core::cell::RefCell;
use core::mem::{self, MaybeUninit};
use core::num::NonZeroUsize; use core::num::NonZeroUsize;
use core::ptr; use core::ptr;
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);
};
}

View file

@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId;
pub(crate) use renderer::{run_format, FormatRenderer}; pub(crate) use renderer::{run_format, FormatRenderer};
use crate::clean::{self, ItemId}; 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 /// Specifies whether rendering directly implemented trait items or ones from a certain Deref
/// impl. /// impl.
@ -65,7 +65,8 @@ impl Impl {
// Returns true if this is an implementation on a "local" type, meaning: // 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 // the type is in the current crate, or the type and the trait are both
// re-exported by the current crate. // 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_; let for_type = &self.inner_impl().for_;
if let Some(for_type_did) = for_type.def_id(cache) { 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. // 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 { if for_type_did.krate == trait_did.krate {
return true; 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; return false;
}; };

View file

@ -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), |sym| format!("<a href=\"#{1}.{0}\">{0}</a>", sym, ItemType::Method),
); );
let cache = cx.cache(); if let Some(implementors) = cx.cache().implementors.get(&it.item_id.expect_def_id()) {
if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
let mut res = implementors let mut res = implementors
.iter() .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)) .filter_map(|i| extract_for_impl_name(&i.impl_item, cx))
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View file

@ -823,7 +823,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
} }
let (local, foreign) = 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>) = let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
local.iter().partition(|i| i.inner_impl().kind.is_auto()); local.iter().partition(|i| i.inner_impl().kind.is_auto());

View 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 ();
}
}
}