Auto merge of #71566 - Dylan-DPC:rollup-9xoz6fg, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #70043 (Add all remaining `DefKind`s.) - #71140 ([breaking change] Disallow statics initializing themselves) - #71392 (Don't hold the predecessor cache lock longer than necessary) - #71541 (Add regression test for #26376) - #71554 (Replace thread_local with generator resume arguments in box_region.) Failed merges: r? @ghost
This commit is contained in:
commit
b592b37fa3
54 changed files with 369 additions and 307 deletions
|
@ -157,7 +157,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
let cleanup_kinds = analyze::cleanup_kinds(&mir);
|
||||
// Allocate a `Block` for every basic block, except
|
||||
// the start block, if nothing loops back to it.
|
||||
let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty();
|
||||
let reentrant_start_block = !mir.predecessors()[mir::START_BLOCK].is_empty();
|
||||
let block_bxs: IndexVec<mir::BasicBlock, Bx::BasicBlock> = mir
|
||||
.basic_blocks()
|
||||
.indices()
|
||||
|
|
|
@ -1,4 +1,15 @@
|
|||
use std::cell::Cell;
|
||||
//! This module provides a way to deal with self-referential data.
|
||||
//!
|
||||
//! The main idea is to allocate such data in a generator frame and then
|
||||
//! give access to it by executing user-provided closures inside that generator.
|
||||
//! The module provides a safe abstraction for the latter task.
|
||||
//!
|
||||
//! The interface consists of two exported macros meant to be used together:
|
||||
//! * `declare_box_region_type` wraps a generator inside a struct with `access`
|
||||
//! method which accepts closures.
|
||||
//! * `box_region_allow_access` is a helper which should be called inside
|
||||
//! a generator to actually execute those closures.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Generator, GeneratorState};
|
||||
use std::pin::Pin;
|
||||
|
@ -14,24 +25,23 @@ impl AccessAction {
|
|||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Action {
|
||||
Initial,
|
||||
Access(AccessAction),
|
||||
Complete,
|
||||
}
|
||||
|
||||
thread_local!(pub static BOX_REGION_ARG: Cell<Action> = Cell::new(Action::Complete));
|
||||
|
||||
pub struct PinnedGenerator<I, A, R> {
|
||||
generator: Pin<Box<dyn Generator<Yield = YieldType<I, A>, Return = R>>>,
|
||||
generator: Pin<Box<dyn Generator<Action, Yield = YieldType<I, A>, Return = R>>>,
|
||||
}
|
||||
|
||||
impl<I, A, R> PinnedGenerator<I, A, R> {
|
||||
pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
|
||||
pub fn new<T: Generator<Action, Yield = YieldType<I, A>, Return = R> + 'static>(
|
||||
generator: T,
|
||||
) -> (I, Self) {
|
||||
let mut result = PinnedGenerator { generator: Box::pin(generator) };
|
||||
|
||||
// Run it to the first yield to set it up
|
||||
let init = match Pin::new(&mut result.generator).resume(()) {
|
||||
let init = match Pin::new(&mut result.generator).resume(Action::Initial) {
|
||||
GeneratorState::Yielded(YieldType::Initial(y)) => y,
|
||||
_ => panic!(),
|
||||
};
|
||||
|
@ -40,21 +50,17 @@ impl<I, A, R> PinnedGenerator<I, A, R> {
|
|||
}
|
||||
|
||||
pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
|
||||
BOX_REGION_ARG.with(|i| {
|
||||
i.set(Action::Access(AccessAction(closure)));
|
||||
});
|
||||
|
||||
// Call the generator, which in turn will call the closure in BOX_REGION_ARG
|
||||
if let GeneratorState::Complete(_) = Pin::new(&mut self.generator).resume(()) {
|
||||
// Call the generator, which in turn will call the closure
|
||||
if let GeneratorState::Complete(_) =
|
||||
Pin::new(&mut self.generator).resume(Action::Access(AccessAction(closure)))
|
||||
{
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn complete(&mut self) -> R {
|
||||
// Tell the generator we want it to complete, consuming it and yielding a result
|
||||
BOX_REGION_ARG.with(|i| i.set(Action::Complete));
|
||||
|
||||
let result = Pin::new(&mut self.generator).resume(());
|
||||
let result = Pin::new(&mut self.generator).resume(Action::Complete);
|
||||
if let GeneratorState::Complete(r) = result { r } else { panic!() }
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +95,7 @@ macro_rules! declare_box_region_type {
|
|||
>);
|
||||
|
||||
impl $name {
|
||||
fn new<T: ::std::ops::Generator<Yield = $yield_type, Return = $retc> + 'static>(
|
||||
fn new<T: ::std::ops::Generator<$crate::box_region::Action, Yield = $yield_type, Return = $retc> + 'static>(
|
||||
generator: T
|
||||
) -> ($reti, Self) {
|
||||
let (initial, pinned) = $crate::box_region::PinnedGenerator::new(generator);
|
||||
|
@ -98,7 +104,7 @@ macro_rules! declare_box_region_type {
|
|||
|
||||
$v fn access<F: for<$($lifetimes)*> FnOnce($($args,)*) -> R, R>(&mut self, f: F) -> R {
|
||||
// Turn the FnOnce closure into *mut dyn FnMut()
|
||||
// so we can pass it in to the generator using the BOX_REGION_ARG thread local
|
||||
// so we can pass it in to the generator
|
||||
let mut r = None;
|
||||
let mut f = Some(f);
|
||||
let mut_f: &mut dyn for<$($lifetimes)*> FnMut(($($args,)*)) =
|
||||
|
@ -140,9 +146,9 @@ macro_rules! declare_box_region_type {
|
|||
#[macro_export]
|
||||
#[allow_internal_unstable(fn_traits)]
|
||||
macro_rules! box_region_allow_access {
|
||||
(for($($lifetimes:tt)*), ($($args:ty),*), ($($exprs:expr),*) ) => {
|
||||
(for($($lifetimes:tt)*), ($($args:ty),*), ($($exprs:expr),*), $action:ident) => {
|
||||
loop {
|
||||
match $crate::box_region::BOX_REGION_ARG.with(|i| i.get()) {
|
||||
match $action {
|
||||
$crate::box_region::Action::Access(accessor) => {
|
||||
let accessor: &mut dyn for<$($lifetimes)*> FnMut($($args),*) = unsafe {
|
||||
::std::mem::transmute(accessor.get())
|
||||
|
@ -152,10 +158,11 @@ macro_rules! box_region_allow_access {
|
|||
let marker = $crate::box_region::Marker::<
|
||||
for<$($lifetimes)*> fn(($($args,)*))
|
||||
>::new();
|
||||
yield $crate::box_region::YieldType::Accessor(marker)
|
||||
$action = yield $crate::box_region::YieldType::Accessor(marker);
|
||||
};
|
||||
}
|
||||
$crate::box_region::Action::Complete => break,
|
||||
$crate::box_region::Action::Initial => panic!("unexpected box_region action: Initial"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,18 @@ pub enum DefKind {
|
|||
|
||||
// Macro namespace
|
||||
Macro(MacroKind),
|
||||
|
||||
// Not namespaced (or they are, but we don't treat them so)
|
||||
ExternCrate,
|
||||
Use,
|
||||
ForeignMod,
|
||||
AnonConst,
|
||||
Field,
|
||||
LifetimeParam,
|
||||
GlobalAsm,
|
||||
Impl,
|
||||
Closure,
|
||||
Generator,
|
||||
}
|
||||
|
||||
impl DefKind {
|
||||
|
@ -113,6 +125,16 @@ impl DefKind {
|
|||
DefKind::TyParam => "type parameter",
|
||||
DefKind::ConstParam => "const parameter",
|
||||
DefKind::Macro(macro_kind) => macro_kind.descr(),
|
||||
DefKind::LifetimeParam => "lifetime parameter",
|
||||
DefKind::Use => "import",
|
||||
DefKind::ForeignMod => "foreign module",
|
||||
DefKind::AnonConst => "constant expression",
|
||||
DefKind::Field => "field",
|
||||
DefKind::Impl => "implementation",
|
||||
DefKind::Closure => "closure",
|
||||
DefKind::Generator => "generator",
|
||||
DefKind::ExternCrate => "extern crate",
|
||||
DefKind::GlobalAsm => "global assembly block",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +146,10 @@ impl DefKind {
|
|||
| DefKind::AssocOpaqueTy
|
||||
| DefKind::AssocFn
|
||||
| DefKind::Enum
|
||||
| DefKind::OpaqueTy => "an",
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::Impl
|
||||
| DefKind::Use
|
||||
| DefKind::ExternCrate => "an",
|
||||
DefKind::Macro(macro_kind) => macro_kind.article(),
|
||||
_ => "a",
|
||||
}
|
||||
|
@ -155,6 +180,18 @@ impl DefKind {
|
|||
| DefKind::AssocConst => ns == Namespace::ValueNS,
|
||||
|
||||
DefKind::Macro(..) => ns == Namespace::MacroNS,
|
||||
|
||||
// Not namespaced.
|
||||
DefKind::AnonConst
|
||||
| DefKind::Field
|
||||
| DefKind::LifetimeParam
|
||||
| DefKind::ExternCrate
|
||||
| DefKind::Closure
|
||||
| DefKind::Generator
|
||||
| DefKind::Use
|
||||
| DefKind::ForeignMod
|
||||
| DefKind::GlobalAsm
|
||||
| DefKind::Impl => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2452,27 +2452,6 @@ pub enum ItemKind<'hir> {
|
|||
}
|
||||
|
||||
impl ItemKind<'_> {
|
||||
pub fn descr(&self) -> &str {
|
||||
match *self {
|
||||
ItemKind::ExternCrate(..) => "extern crate",
|
||||
ItemKind::Use(..) => "`use` import",
|
||||
ItemKind::Static(..) => "static item",
|
||||
ItemKind::Const(..) => "constant item",
|
||||
ItemKind::Fn(..) => "function",
|
||||
ItemKind::Mod(..) => "module",
|
||||
ItemKind::ForeignMod(..) => "extern block",
|
||||
ItemKind::GlobalAsm(..) => "global asm item",
|
||||
ItemKind::TyAlias(..) => "type alias",
|
||||
ItemKind::OpaqueTy(..) => "opaque type",
|
||||
ItemKind::Enum(..) => "enum",
|
||||
ItemKind::Struct(..) => "struct",
|
||||
ItemKind::Union(..) => "union",
|
||||
ItemKind::Trait(..) => "trait",
|
||||
ItemKind::TraitAlias(..) => "trait alias",
|
||||
ItemKind::Impl { .. } => "implementation",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generics(&self) -> Option<&Generics<'_>> {
|
||||
Some(match *self {
|
||||
ItemKind::Fn(_, ref generics, _)
|
||||
|
@ -2551,16 +2530,6 @@ pub enum ForeignItemKind<'hir> {
|
|||
Type,
|
||||
}
|
||||
|
||||
impl ForeignItemKind<'hir> {
|
||||
pub fn descriptive_variant(&self) -> &str {
|
||||
match *self {
|
||||
ForeignItemKind::Fn(..) => "foreign function",
|
||||
ForeignItemKind::Static(..) => "foreign static item",
|
||||
ForeignItemKind::Type => "foreign type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A variable captured by a closure.
|
||||
#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable_Generic)]
|
||||
pub struct Upvar {
|
||||
|
|
|
@ -207,12 +207,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
.get_opt_name()
|
||||
.map(|parent_symbol| parent_symbol.to_string());
|
||||
|
||||
let type_parent_desc = self
|
||||
.tcx
|
||||
.def_kind(parent_def_id)
|
||||
.map(|parent_def_kind| parent_def_kind.descr(parent_def_id));
|
||||
|
||||
(parent_name, type_parent_desc)
|
||||
(parent_name, Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
|
|
@ -109,7 +109,8 @@ pub fn configure_and_expand(
|
|||
// its contents but the results of name resolution on those contents. Hopefully we'll push
|
||||
// this back at some point.
|
||||
let crate_name = crate_name.to_string();
|
||||
let (result, resolver) = BoxedResolver::new(static move || {
|
||||
let (result, resolver) = BoxedResolver::new(static move |mut action| {
|
||||
let _ = action;
|
||||
let sess = &*sess;
|
||||
let resolver_arenas = Resolver::arenas();
|
||||
let res = configure_and_expand_inner(
|
||||
|
@ -126,11 +127,11 @@ pub fn configure_and_expand(
|
|||
panic!()
|
||||
}
|
||||
Ok((krate, resolver)) => {
|
||||
yield BoxedResolver::initial_yield(Ok(krate));
|
||||
action = yield BoxedResolver::initial_yield(Ok(krate));
|
||||
resolver
|
||||
}
|
||||
};
|
||||
box_region_allow_access!(for(), (&mut Resolver<'_>), (&mut resolver));
|
||||
box_region_allow_access!(for(), (&mut Resolver<'_>), (&mut resolver), action);
|
||||
resolver.into_outputs()
|
||||
});
|
||||
result.map(|k| (k, resolver))
|
||||
|
|
|
@ -562,8 +562,8 @@ impl MetadataBlob {
|
|||
}
|
||||
|
||||
impl EntryKind {
|
||||
fn def_kind(&self) -> Option<DefKind> {
|
||||
Some(match *self {
|
||||
fn def_kind(&self) -> DefKind {
|
||||
match *self {
|
||||
EntryKind::Const(..) => DefKind::Const,
|
||||
EntryKind::AssocConst(..) => DefKind::AssocConst,
|
||||
EntryKind::ImmStatic
|
||||
|
@ -587,14 +587,13 @@ impl EntryKind {
|
|||
EntryKind::Enum(..) => DefKind::Enum,
|
||||
EntryKind::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
|
||||
EntryKind::ForeignType => DefKind::ForeignTy,
|
||||
|
||||
EntryKind::ForeignMod
|
||||
| EntryKind::GlobalAsm
|
||||
| EntryKind::Impl(_)
|
||||
| EntryKind::Field
|
||||
| EntryKind::Generator(_)
|
||||
| EntryKind::Closure => return None,
|
||||
})
|
||||
EntryKind::Impl(_) => DefKind::Impl,
|
||||
EntryKind::Closure => DefKind::Closure,
|
||||
EntryKind::ForeignMod => DefKind::ForeignMod,
|
||||
EntryKind::GlobalAsm => DefKind::GlobalAsm,
|
||||
EntryKind::Field => DefKind::Field,
|
||||
EntryKind::Generator(_) => DefKind::Generator,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -679,11 +678,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn def_kind(&self, index: DefIndex) -> Option<DefKind> {
|
||||
fn def_kind(&self, index: DefIndex) -> DefKind {
|
||||
if !self.is_proc_macro(index) {
|
||||
self.kind(index).def_kind()
|
||||
} else {
|
||||
Some(DefKind::Macro(macro_kind(self.raw_proc_macro(index))))
|
||||
DefKind::Macro(macro_kind(self.raw_proc_macro(index)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1009,7 +1008,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
.get(self, child_index)
|
||||
.unwrap_or(Lazy::empty());
|
||||
for child_index in child_children.decode((self, sess)) {
|
||||
if let Some(kind) = self.def_kind(child_index) {
|
||||
let kind = self.def_kind(child_index);
|
||||
callback(Export {
|
||||
res: Res::Def(kind, self.local_def_id(child_index)),
|
||||
ident: self.item_ident(child_index, sess),
|
||||
|
@ -1023,7 +1022,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
.decode((self, sess)),
|
||||
});
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
EntryKind::Impl(_) => continue,
|
||||
|
@ -1033,10 +1031,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
|||
|
||||
let def_key = self.def_key(child_index);
|
||||
let span = self.get_span(child_index, sess);
|
||||
if let (Some(kind), true) = (
|
||||
self.def_kind(child_index),
|
||||
def_key.disambiguated_data.data.get_opt_name().is_some(),
|
||||
) {
|
||||
if def_key.disambiguated_data.data.get_opt_name().is_some() {
|
||||
let kind = self.def_kind(child_index);
|
||||
let ident = self.item_ident(child_index, sess);
|
||||
let vis = self.get_visibility(child_index);
|
||||
let def_id = self.local_def_id(child_index);
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::ty::TyCtxt;
|
|||
use rustc_ast::ast::{self, Name, NodeId};
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::{DefKey, DefPath, Definitions};
|
||||
use rustc_hir::intravisit;
|
||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
||||
|
@ -227,10 +227,14 @@ impl<'hir> Map<'hir> {
|
|||
self.tcx.definitions.opt_local_def_id_to_hir_id(def_id)
|
||||
}
|
||||
|
||||
pub fn def_kind(&self, hir_id: HirId) -> Option<DefKind> {
|
||||
let node = self.find(hir_id)?;
|
||||
pub fn def_kind(&self, local_def_id: LocalDefId) -> DefKind {
|
||||
// FIXME(eddyb) support `find` on the crate root.
|
||||
if local_def_id.to_def_id().index == CRATE_DEF_INDEX {
|
||||
return DefKind::Mod;
|
||||
}
|
||||
|
||||
Some(match node {
|
||||
let hir_id = self.local_def_id_to_hir_id(local_def_id);
|
||||
match self.get(hir_id) {
|
||||
Node::Item(item) => match item.kind {
|
||||
ItemKind::Static(..) => DefKind::Static,
|
||||
ItemKind::Const(..) => DefKind::Const,
|
||||
|
@ -243,11 +247,11 @@ impl<'hir> Map<'hir> {
|
|||
ItemKind::Union(..) => DefKind::Union,
|
||||
ItemKind::Trait(..) => DefKind::Trait,
|
||||
ItemKind::TraitAlias(..) => DefKind::TraitAlias,
|
||||
ItemKind::ExternCrate(_)
|
||||
| ItemKind::Use(..)
|
||||
| ItemKind::ForeignMod(..)
|
||||
| ItemKind::GlobalAsm(..)
|
||||
| ItemKind::Impl { .. } => return None,
|
||||
ItemKind::ExternCrate(_) => DefKind::ExternCrate,
|
||||
ItemKind::Use(..) => DefKind::Use,
|
||||
ItemKind::ForeignMod(..) => DefKind::ForeignMod,
|
||||
ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
|
||||
ItemKind::Impl { .. } => DefKind::Impl,
|
||||
},
|
||||
Node::ForeignItem(item) => match item.kind {
|
||||
ForeignItemKind::Fn(..) => DefKind::Fn,
|
||||
|
@ -268,7 +272,7 @@ impl<'hir> Map<'hir> {
|
|||
Node::Variant(_) => DefKind::Variant,
|
||||
Node::Ctor(variant_data) => {
|
||||
// FIXME(eddyb) is this even possible, if we have a `Node::Ctor`?
|
||||
variant_data.ctor_hir_id()?;
|
||||
assert_ne!(variant_data.ctor_hir_id(), None);
|
||||
|
||||
let ctor_of = match self.find(self.get_parent_node(hir_id)) {
|
||||
Some(Node::Item(..)) => def::CtorOf::Struct,
|
||||
|
@ -277,10 +281,20 @@ impl<'hir> Map<'hir> {
|
|||
};
|
||||
DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data))
|
||||
}
|
||||
Node::AnonConst(_)
|
||||
| Node::Field(_)
|
||||
| Node::Expr(_)
|
||||
| Node::Stmt(_)
|
||||
Node::AnonConst(_) => DefKind::AnonConst,
|
||||
Node::Field(_) => DefKind::Field,
|
||||
Node::Expr(expr) => match expr.kind {
|
||||
ExprKind::Closure(.., None) => DefKind::Closure,
|
||||
ExprKind::Closure(.., Some(_)) => DefKind::Generator,
|
||||
_ => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)),
|
||||
},
|
||||
Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
|
||||
Node::GenericParam(param) => match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
|
||||
GenericParamKind::Type { .. } => DefKind::TyParam,
|
||||
GenericParamKind::Const { .. } => DefKind::ConstParam,
|
||||
},
|
||||
Node::Stmt(_)
|
||||
| Node::PathSegment(_)
|
||||
| Node::Ty(_)
|
||||
| Node::TraitRef(_)
|
||||
|
@ -292,14 +306,8 @@ impl<'hir> Map<'hir> {
|
|||
| Node::Lifetime(_)
|
||||
| Node::Visibility(_)
|
||||
| Node::Block(_)
|
||||
| Node::Crate(_) => return None,
|
||||
Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
|
||||
Node::GenericParam(param) => match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => return None,
|
||||
GenericParamKind::Type { .. } => DefKind::TyParam,
|
||||
GenericParamKind::Const { .. } => DefKind::ConstParam,
|
||||
},
|
||||
})
|
||||
| Node::Crate(_) => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_entry(&self, id: HirId) -> Option<Entry<'hir>> {
|
||||
|
@ -1082,6 +1090,5 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
|
|||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers<'_>) {
|
||||
providers.def_kind =
|
||||
|tcx, def_id| tcx.hir().def_kind(tcx.hir().as_local_hir_id(def_id.expect_local()));
|
||||
providers.def_kind = |tcx, def_id| tcx.hir().def_kind(def_id.expect_local());
|
||||
}
|
||||
|
|
|
@ -246,7 +246,7 @@ pub enum EvalResult {
|
|||
fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, mut def_id: DefId) -> bool {
|
||||
// Check if `def_id` is a trait method.
|
||||
match tcx.def_kind(def_id) {
|
||||
Some(DefKind::AssocFn) | Some(DefKind::AssocTy) | Some(DefKind::AssocConst) => {
|
||||
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
|
||||
if let ty::TraitContainer(trait_def_id) = tcx.associated_item(def_id).container {
|
||||
// Trait methods do not declare visibility (even
|
||||
// for visibility info in cstore). Use containing
|
||||
|
|
|
@ -23,14 +23,12 @@ use rustc_ast::ast::Name;
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::graph::dominators::{dominators, Dominators};
|
||||
use rustc_data_structures::graph::{self, GraphSuccessors};
|
||||
use rustc_data_structures::sync::MappedLockGuard;
|
||||
use rustc_index::bit_set::BitMatrix;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_serialize::{Decodable, Encodable};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use smallvec::SmallVec;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::{self, Debug, Display, Formatter, Write};
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
@ -170,7 +168,7 @@ pub struct Body<'tcx> {
|
|||
/// FIXME(oli-obk): rewrite the promoted during promotion to eliminate the cell components.
|
||||
pub ignore_interior_mut_in_const_validation: bool,
|
||||
|
||||
pub predecessor_cache: PredecessorCache,
|
||||
predecessor_cache: PredecessorCache,
|
||||
}
|
||||
|
||||
impl<'tcx> Body<'tcx> {
|
||||
|
@ -398,15 +396,6 @@ impl<'tcx> Body<'tcx> {
|
|||
Location { block: bb, statement_index: self[bb].statements.len() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn predecessors_for(
|
||||
&self,
|
||||
bb: BasicBlock,
|
||||
) -> impl std::ops::Deref<Target = SmallVec<[BasicBlock; 4]>> + '_ {
|
||||
let predecessors = self.predecessor_cache.compute(&self.basic_blocks);
|
||||
MappedLockGuard::map(predecessors, |preds| &mut preds[bb])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn predecessors(&self) -> impl std::ops::Deref<Target = Predecessors> + '_ {
|
||||
self.predecessor_cache.compute(&self.basic_blocks)
|
||||
|
@ -2684,7 +2673,7 @@ impl graph::GraphPredecessors<'graph> for Body<'tcx> {
|
|||
impl graph::WithPredecessors for Body<'tcx> {
|
||||
#[inline]
|
||||
fn predecessors(&self, node: Self::Node) -> <Self as graph::GraphPredecessors<'_>>::Iter {
|
||||
self.predecessors_for(node).clone().into_iter()
|
||||
self.predecessors()[node].clone().into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
//! Lazily compute the reverse control-flow graph for the MIR.
|
||||
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::{Lock, LockGuard, MappedLockGuard};
|
||||
use rustc_data_structures::sync::{Lock, Lrc};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_serialize as serialize;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -10,28 +12,38 @@ use crate::mir::{BasicBlock, BasicBlockData};
|
|||
pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PredecessorCache {
|
||||
cache: Lock<Option<Predecessors>>,
|
||||
pub(super) struct PredecessorCache {
|
||||
cache: Lock<Option<Lrc<Predecessors>>>,
|
||||
}
|
||||
|
||||
impl PredecessorCache {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
pub(super) fn new() -> Self {
|
||||
PredecessorCache { cache: Lock::new(None) }
|
||||
}
|
||||
|
||||
/// Invalidates the predecessor cache.
|
||||
///
|
||||
/// Invalidating the predecessor cache requires mutating the MIR, which in turn requires a
|
||||
/// unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
|
||||
/// callers of `invalidate` have a unique reference to the MIR and thus to the predecessor
|
||||
/// cache. This means we don't actually need to take a lock when `invalidate` is called.
|
||||
#[inline]
|
||||
pub fn invalidate(&mut self) {
|
||||
pub(super) fn invalidate(&mut self) {
|
||||
*self.cache.get_mut() = None;
|
||||
}
|
||||
|
||||
/// Returns a ref-counted smart pointer containing the predecessor graph for this MIR.
|
||||
///
|
||||
/// We use ref-counting instead of a mapped `LockGuard` here to ensure that the lock for
|
||||
/// `cache` is only held inside this function. As long as no other locks are taken while
|
||||
/// computing the predecessor graph, deadlock is impossible.
|
||||
#[inline]
|
||||
pub fn compute(
|
||||
pub(super) fn compute(
|
||||
&self,
|
||||
basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
|
||||
) -> MappedLockGuard<'_, Predecessors> {
|
||||
LockGuard::map(self.cache.lock(), |cache| {
|
||||
cache.get_or_insert_with(|| {
|
||||
) -> Lrc<Predecessors> {
|
||||
Lrc::clone(self.cache.lock().get_or_insert_with(|| {
|
||||
let mut preds = IndexVec::from_elem(SmallVec::new(), basic_blocks);
|
||||
for (bb, data) in basic_blocks.iter_enumerated() {
|
||||
if let Some(term) = &data.terminator {
|
||||
|
@ -41,9 +53,8 @@ impl PredecessorCache {
|
|||
}
|
||||
}
|
||||
|
||||
preds
|
||||
})
|
||||
})
|
||||
Lrc::new(preds)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -620,7 +620,7 @@ rustc_queries! {
|
|||
cache_on_disk_if { true }
|
||||
}
|
||||
|
||||
query def_kind(_: DefId) -> Option<DefKind> {}
|
||||
query def_kind(_: DefId) -> DefKind {}
|
||||
query def_span(_: DefId) -> Span {
|
||||
// FIXME(mw): DefSpans are not really inputs since they are derived from
|
||||
// HIR. But at the moment HIR hashing still contains some hacks that allow
|
||||
|
|
|
@ -48,7 +48,7 @@ use rustc_errors::ErrorReported;
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::{DefPathData, DefPathHash, Definitions};
|
||||
use rustc_hir::definitions::{DefPathHash, Definitions};
|
||||
use rustc_hir::lang_items;
|
||||
use rustc_hir::lang_items::PanicLocationLangItem;
|
||||
use rustc_hir::{HirId, Node, TraitCandidate};
|
||||
|
@ -1492,21 +1492,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
|
||||
pub fn article_and_description(&self, def_id: DefId) -> (&'static str, &'static str) {
|
||||
self.def_kind(def_id)
|
||||
.map(|def_kind| (def_kind.article(), def_kind.descr(def_id)))
|
||||
.unwrap_or_else(|| match self.def_key(def_id).disambiguated_data.data {
|
||||
DefPathData::ClosureExpr => match self.generator_kind(def_id) {
|
||||
None => ("a", "closure"),
|
||||
Some(rustc_hir::GeneratorKind::Async(..)) => ("an", "async closure"),
|
||||
Some(rustc_hir::GeneratorKind::Gen) => ("a", "generator"),
|
||||
match self.def_kind(def_id) {
|
||||
DefKind::Generator => match self.generator_kind(def_id).unwrap() {
|
||||
rustc_hir::GeneratorKind::Async(..) => ("an", "async closure"),
|
||||
rustc_hir::GeneratorKind::Gen => ("a", "generator"),
|
||||
},
|
||||
DefPathData::LifetimeNs(..) => ("a", "lifetime"),
|
||||
DefPathData::Impl => ("an", "implementation"),
|
||||
DefPathData::TypeNs(..) | DefPathData::ValueNs(..) | DefPathData::MacroNs(..) => {
|
||||
unreachable!()
|
||||
def_kind => (def_kind.article(), def_kind.descr(def_id)),
|
||||
}
|
||||
_ => bug!("article_and_description called on def_id {:?}", def_id),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2680,7 +2680,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
} else {
|
||||
match self.def_kind(def_id) {
|
||||
Some(DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy) => true,
|
||||
DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => true,
|
||||
_ => false,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -888,7 +888,7 @@ pub trait PrettyPrinter<'tcx>:
|
|||
p!(write("::{:?}", promoted));
|
||||
} else {
|
||||
match self.tcx().def_kind(did) {
|
||||
Some(DefKind::Static | DefKind::Const | DefKind::AssocConst) => {
|
||||
DefKind::Static | DefKind::Const | DefKind::AssocConst => {
|
||||
p!(print_value_path(did, substs))
|
||||
}
|
||||
_ => {
|
||||
|
|
|
@ -16,7 +16,6 @@ use rustc_errors::ErrorReported;
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{Integer, Size, TargetDataLayout};
|
||||
|
@ -446,24 +445,24 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// those are not yet phased out). The parent of the closure's
|
||||
/// `DefId` will also be the context where it appears.
|
||||
pub fn is_closure(self, def_id: DefId) -> bool {
|
||||
self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
|
||||
matches!(self.def_kind(def_id), DefKind::Closure | DefKind::Generator)
|
||||
}
|
||||
|
||||
/// Returns `true` if `def_id` refers to a trait (i.e., `trait Foo { ... }`).
|
||||
pub fn is_trait(self, def_id: DefId) -> bool {
|
||||
self.def_kind(def_id) == Some(DefKind::Trait)
|
||||
self.def_kind(def_id) == DefKind::Trait
|
||||
}
|
||||
|
||||
/// Returns `true` if `def_id` refers to a trait alias (i.e., `trait Foo = ...;`),
|
||||
/// and `false` otherwise.
|
||||
pub fn is_trait_alias(self, def_id: DefId) -> bool {
|
||||
self.def_kind(def_id) == Some(DefKind::TraitAlias)
|
||||
self.def_kind(def_id) == DefKind::TraitAlias
|
||||
}
|
||||
|
||||
/// Returns `true` if this `DefId` refers to the implicit constructor for
|
||||
/// a tuple struct like `struct Foo(u32)`, and `false` otherwise.
|
||||
pub fn is_constructor(self, def_id: DefId) -> bool {
|
||||
self.def_key(def_id).disambiguated_data.data == DefPathData::Ctor
|
||||
matches!(self.def_kind(def_id), DefKind::Ctor(..))
|
||||
}
|
||||
|
||||
/// Given the def-ID of a fn or closure, returns the def-ID of
|
||||
|
|
|
@ -1269,7 +1269,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
location: Location,
|
||||
) -> impl Iterator<Item = Location> + 'a {
|
||||
if location.statement_index == 0 {
|
||||
let predecessors = body.predecessors_for(location.block).to_vec();
|
||||
let predecessors = body.predecessors()[location.block].to_vec();
|
||||
Either::Left(predecessors.into_iter().map(move |bb| body.terminator_loc(bb)))
|
||||
} else {
|
||||
Either::Right(std::iter::once(Location {
|
||||
|
|
|
@ -89,7 +89,7 @@ impl RegionValueElements {
|
|||
// If this is a basic block head, then the predecessors are
|
||||
// the terminators of other basic blocks
|
||||
stack.extend(
|
||||
body.predecessors_for(block)
|
||||
body.predecessors()[block]
|
||||
.iter()
|
||||
.map(|&pred_bb| body.terminator_loc(pred_bb))
|
||||
.map(|pred_loc| self.point_from_location(pred_loc)),
|
||||
|
|
|
@ -303,7 +303,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
|||
}
|
||||
|
||||
let body = self.cx.body;
|
||||
for &pred_block in body.predecessors_for(block).iter() {
|
||||
for &pred_block in body.predecessors()[block].iter() {
|
||||
debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,);
|
||||
|
||||
// Check whether the variable is (at least partially)
|
||||
|
|
|
@ -341,7 +341,7 @@ pub fn const_eval_raw_provider<'tcx>(
|
|||
// because any code that existed before validation could not have failed
|
||||
// validation thus preventing such a hard error from being a backwards
|
||||
// compatibility hazard
|
||||
Some(DefKind::Const | DefKind::AssocConst) => {
|
||||
DefKind::Const | DefKind::AssocConst => {
|
||||
let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
|
||||
err.report_as_lint(
|
||||
tcx.at(tcx.def_span(def_id)),
|
||||
|
|
|
@ -632,7 +632,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
// FIXME: The above is likely untrue. See
|
||||
// <https://github.com/rust-lang/rust/pull/70004#issuecomment-602022110>. Is it
|
||||
// okay to ignore `StorageDead`/`StorageLive` annotations during CTFE?
|
||||
Some(DefKind::Static | DefKind::Const | DefKind::AssocConst) => {}
|
||||
DefKind::Static | DefKind::Const | DefKind::AssocConst => {}
|
||||
_ => {
|
||||
// Mark locals that use `Storage*` annotations as dead on function entry.
|
||||
let always_live = AlwaysLiveLocals::new(self.body());
|
||||
|
|
|
@ -400,7 +400,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
|||
|
||||
// We can still be zero-sized in this branch, in which case we have to
|
||||
// return `None`.
|
||||
if size.bytes() == 0 { None } else { Some(ptr) }
|
||||
if size.bytes() == 0 {
|
||||
// We may be reading from a static.
|
||||
// In order to ensure that `static FOO: Type = FOO;` causes a cycle error
|
||||
// instead of magically pulling *any* ZST value from the ether, we need to
|
||||
// actually access the referenced allocation. The caller is likely
|
||||
// to short-circuit on `None`, so we trigger the access here to
|
||||
// make sure it happens.
|
||||
self.get_raw(ptr.alloc_id)?;
|
||||
None
|
||||
} else {
|
||||
Some(ptr)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -248,13 +248,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
}
|
||||
};
|
||||
|
||||
let alloc = self.memory.get_raw(ptr.alloc_id)?;
|
||||
|
||||
match mplace.layout.abi {
|
||||
Abi::Scalar(..) => {
|
||||
let scalar = self.memory.get_raw(ptr.alloc_id)?.read_scalar(
|
||||
self,
|
||||
ptr,
|
||||
mplace.layout.size,
|
||||
)?;
|
||||
let scalar = alloc.read_scalar(self, ptr, mplace.layout.size)?;
|
||||
Ok(Some(ImmTy { imm: scalar.into(), layout: mplace.layout }))
|
||||
}
|
||||
Abi::ScalarPair(ref a, ref b) => {
|
||||
|
@ -267,8 +265,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
let b_offset = a_size.align_to(b.align(self).abi);
|
||||
assert!(b_offset.bytes() > 0); // we later use the offset to tell apart the fields
|
||||
let b_ptr = ptr.offset(b_offset, self)?;
|
||||
let a_val = self.memory.get_raw(ptr.alloc_id)?.read_scalar(self, a_ptr, a_size)?;
|
||||
let b_val = self.memory.get_raw(ptr.alloc_id)?.read_scalar(self, b_ptr, b_size)?;
|
||||
let a_val = alloc.read_scalar(self, a_ptr, a_size)?;
|
||||
let b_val = alloc.read_scalar(self, b_ptr, b_size)?;
|
||||
Ok(Some(ImmTy { imm: Immediate::ScalarPair(a_val, b_val), layout: mplace.layout }))
|
||||
}
|
||||
_ => Ok(None),
|
||||
|
|
|
@ -779,7 +779,7 @@ fn compute_codegen_unit_name(
|
|||
cgu_def_id = Some(DefId { krate: def_id.krate, index: CRATE_DEF_INDEX });
|
||||
}
|
||||
break;
|
||||
} else if tcx.def_kind(current_def_id) == Some(DefKind::Mod) {
|
||||
} else if tcx.def_kind(current_def_id) == DefKind::Mod {
|
||||
if cgu_def_id.is_none() {
|
||||
cgu_def_id = Some(current_def_id);
|
||||
}
|
||||
|
|
|
@ -69,10 +69,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
|||
let hir_id = tcx.hir().as_local_hir_id(source.def_id().expect_local());
|
||||
|
||||
let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some();
|
||||
let is_assoc_const = match tcx.def_kind(source.def_id()) {
|
||||
Some(DefKind::AssocConst) => true,
|
||||
_ => false,
|
||||
};
|
||||
let is_assoc_const = tcx.def_kind(source.def_id()) == DefKind::AssocConst;
|
||||
|
||||
// Only run const prop on functions, methods, closures and associated constants
|
||||
if !is_fn_like && !is_assoc_const {
|
||||
|
|
|
@ -807,17 +807,17 @@ fn write_mir_sig(
|
|||
trace!("write_mir_sig: {:?}", src.instance);
|
||||
let kind = tcx.def_kind(src.def_id());
|
||||
let is_function = match kind {
|
||||
Some(DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..)) => true,
|
||||
DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true,
|
||||
_ => tcx.is_closure(src.def_id()),
|
||||
};
|
||||
match (kind, src.promoted) {
|
||||
(_, Some(i)) => write!(w, "{:?} in ", i)?,
|
||||
(Some(DefKind::Const | DefKind::AssocConst), _) => write!(w, "const ")?,
|
||||
(Some(DefKind::Static), _) => {
|
||||
(DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?,
|
||||
(DefKind::Static, _) => {
|
||||
write!(w, "static {}", if tcx.is_mutable_static(src.def_id()) { "mut " } else { "" })?
|
||||
}
|
||||
(_, _) if is_function => write!(w, "fn ")?,
|
||||
(None, _) => {} // things like anon const, not an item
|
||||
(DefKind::AnonConst, _) => {} // things like anon const, not an item
|
||||
_ => bug!("Unexpected def kind {:?}", kind),
|
||||
}
|
||||
|
||||
|
|
|
@ -553,12 +553,13 @@ impl DeadVisitor<'tcx> {
|
|||
id: hir::HirId,
|
||||
span: rustc_span::Span,
|
||||
name: ast::Name,
|
||||
node_type: &str,
|
||||
participle: &str,
|
||||
) {
|
||||
if !name.as_str().starts_with('_') {
|
||||
self.tcx.struct_span_lint_hir(lint::builtin::DEAD_CODE, id, span, |lint| {
|
||||
lint.build(&format!("{} is never {}: `{}`", node_type, participle, name)).emit()
|
||||
let def_id = self.tcx.hir().local_def_id(id);
|
||||
let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
|
||||
lint.build(&format!("{} is never {}: `{}`", descr, participle, name)).emit()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -604,7 +605,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
|
|||
hir::ItemKind::Struct(..) => "constructed", // Issue #52325
|
||||
_ => "used",
|
||||
};
|
||||
self.warn_dead_code(item.hir_id, span, item.ident.name, item.kind.descr(), participle);
|
||||
self.warn_dead_code(item.hir_id, span, item.ident.name, participle);
|
||||
} else {
|
||||
// Only continue if we didn't warn
|
||||
intravisit::walk_item(self, item);
|
||||
|
@ -618,13 +619,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
|
|||
id: hir::HirId,
|
||||
) {
|
||||
if self.should_warn_about_variant(&variant) {
|
||||
self.warn_dead_code(
|
||||
variant.id,
|
||||
variant.span,
|
||||
variant.ident.name,
|
||||
"variant",
|
||||
"constructed",
|
||||
);
|
||||
self.warn_dead_code(variant.id, variant.span, variant.ident.name, "constructed");
|
||||
} else {
|
||||
intravisit::walk_variant(self, variant, g, id);
|
||||
}
|
||||
|
@ -632,20 +627,14 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
|
|||
|
||||
fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem<'tcx>) {
|
||||
if self.should_warn_about_foreign_item(fi) {
|
||||
self.warn_dead_code(
|
||||
fi.hir_id,
|
||||
fi.span,
|
||||
fi.ident.name,
|
||||
fi.kind.descriptive_variant(),
|
||||
"used",
|
||||
);
|
||||
self.warn_dead_code(fi.hir_id, fi.span, fi.ident.name, "used");
|
||||
}
|
||||
intravisit::walk_foreign_item(self, fi);
|
||||
}
|
||||
|
||||
fn visit_struct_field(&mut self, field: &'tcx hir::StructField<'tcx>) {
|
||||
if self.should_warn_about_field(&field) {
|
||||
self.warn_dead_code(field.hir_id, field.span, field.ident.name, "field", "read");
|
||||
self.warn_dead_code(field.hir_id, field.span, field.ident.name, "read");
|
||||
}
|
||||
intravisit::walk_struct_field(self, field);
|
||||
}
|
||||
|
@ -658,7 +647,6 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
|
|||
impl_item.hir_id,
|
||||
impl_item.span,
|
||||
impl_item.ident.name,
|
||||
"associated const",
|
||||
"used",
|
||||
);
|
||||
}
|
||||
|
@ -667,13 +655,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
|
|||
hir::ImplItemKind::Fn(_, body_id) => {
|
||||
if !self.symbol_is_live(impl_item.hir_id) {
|
||||
let span = self.tcx.sess.source_map().guess_head_span(impl_item.span);
|
||||
self.warn_dead_code(
|
||||
impl_item.hir_id,
|
||||
span,
|
||||
impl_item.ident.name,
|
||||
"method",
|
||||
"used",
|
||||
);
|
||||
self.warn_dead_code(impl_item.hir_id, span, impl_item.ident.name, "used");
|
||||
}
|
||||
self.visit_nested_body(body_id)
|
||||
}
|
||||
|
|
|
@ -337,12 +337,14 @@ struct MissingStabilityAnnotations<'a, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> MissingStabilityAnnotations<'a, 'tcx> {
|
||||
fn check_missing_stability(&self, hir_id: HirId, span: Span, name: &str) {
|
||||
fn check_missing_stability(&self, hir_id: HirId, span: Span) {
|
||||
let stab = self.tcx.stability().local_stability(hir_id);
|
||||
let is_error =
|
||||
!self.tcx.sess.opts.test && stab.is_none() && self.access_levels.is_reachable(hir_id);
|
||||
if is_error {
|
||||
self.tcx.sess.span_err(span, &format!("{} has missing stability attribute", name));
|
||||
let def_id = self.tcx.hir().local_def_id(hir_id);
|
||||
let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
|
||||
self.tcx.sess.span_err(span, &format!("{} has missing stability attribute", descr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -362,42 +364,42 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
|
|||
// optional. They inherit stability from their parents when unannotated.
|
||||
hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {}
|
||||
|
||||
_ => self.check_missing_stability(i.hir_id, i.span, i.kind.descr()),
|
||||
_ => self.check_missing_stability(i.hir_id, i.span),
|
||||
}
|
||||
|
||||
intravisit::walk_item(self, i)
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
|
||||
self.check_missing_stability(ti.hir_id, ti.span, "item");
|
||||
self.check_missing_stability(ti.hir_id, ti.span);
|
||||
intravisit::walk_trait_item(self, ti);
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
|
||||
let impl_def_id = self.tcx.hir().local_def_id(self.tcx.hir().get_parent_item(ii.hir_id));
|
||||
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
|
||||
self.check_missing_stability(ii.hir_id, ii.span, "item");
|
||||
self.check_missing_stability(ii.hir_id, ii.span);
|
||||
}
|
||||
intravisit::walk_impl_item(self, ii);
|
||||
}
|
||||
|
||||
fn visit_variant(&mut self, var: &'tcx Variant<'tcx>, g: &'tcx Generics<'tcx>, item_id: HirId) {
|
||||
self.check_missing_stability(var.id, var.span, "variant");
|
||||
self.check_missing_stability(var.id, var.span);
|
||||
intravisit::walk_variant(self, var, g, item_id);
|
||||
}
|
||||
|
||||
fn visit_struct_field(&mut self, s: &'tcx StructField<'tcx>) {
|
||||
self.check_missing_stability(s.hir_id, s.span, "field");
|
||||
self.check_missing_stability(s.hir_id, s.span);
|
||||
intravisit::walk_struct_field(self, s);
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
|
||||
self.check_missing_stability(i.hir_id, i.span, i.kind.descriptive_variant());
|
||||
self.check_missing_stability(i.hir_id, i.span);
|
||||
intravisit::walk_foreign_item(self, i);
|
||||
}
|
||||
|
||||
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
|
||||
self.check_missing_stability(md.hir_id, md.span, "macro");
|
||||
self.check_missing_stability(md.hir_id, md.span);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -585,7 +587,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
|||
if tcx.stability().staged_api[&LOCAL_CRATE] {
|
||||
let krate = tcx.hir().krate();
|
||||
let mut missing = MissingStabilityAnnotations { tcx, access_levels };
|
||||
missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.span, "crate");
|
||||
missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.span);
|
||||
intravisit::walk_crate(&mut missing, krate);
|
||||
krate.visit_all_item_likes(&mut missing.as_deep_visitor());
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(nll)]
|
||||
#![feature(or_patterns)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
use rustc_ast::ast::Ident;
|
||||
|
@ -537,12 +538,11 @@ impl EmbargoVisitor<'tcx> {
|
|||
for item_id in module.item_ids {
|
||||
let hir_id = item_id.id;
|
||||
let item_def_id = self.tcx.hir().local_def_id(hir_id);
|
||||
if let Some(def_kind) = self.tcx.def_kind(item_def_id) {
|
||||
let def_kind = self.tcx.def_kind(item_def_id);
|
||||
let item = self.tcx.hir().expect_item(hir_id);
|
||||
let vis = ty::Visibility::from_hir(&item.vis, hir_id, self.tcx);
|
||||
self.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod);
|
||||
}
|
||||
}
|
||||
if let Some(exports) = self.tcx.module_exports(module_def_id) {
|
||||
for export in exports {
|
||||
if export.vis.is_accessible_from(defining_mod, self.tcx) {
|
||||
|
@ -613,7 +613,7 @@ impl EmbargoVisitor<'tcx> {
|
|||
}
|
||||
|
||||
// These have type privacy, so are not reachable unless they're
|
||||
// public
|
||||
// public, or are not namespaced at all.
|
||||
DefKind::AssocConst
|
||||
| DefKind::AssocTy
|
||||
| DefKind::AssocOpaqueTy
|
||||
|
@ -626,7 +626,17 @@ impl EmbargoVisitor<'tcx> {
|
|||
| DefKind::AssocFn
|
||||
| DefKind::Trait
|
||||
| DefKind::TyParam
|
||||
| DefKind::Variant => (),
|
||||
| DefKind::Variant
|
||||
| DefKind::LifetimeParam
|
||||
| DefKind::ExternCrate
|
||||
| DefKind::Use
|
||||
| DefKind::ForeignMod
|
||||
| DefKind::AnonConst
|
||||
| DefKind::Field
|
||||
| DefKind::GlobalAsm
|
||||
| DefKind::Impl
|
||||
| DefKind::Closure
|
||||
| DefKind::Generator => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -906,7 +906,21 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||
Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => {
|
||||
self.r.define(parent, ident, MacroNS, (res, vis, span, expansion))
|
||||
}
|
||||
Res::Def(DefKind::TyParam | DefKind::ConstParam, _)
|
||||
Res::Def(
|
||||
DefKind::TyParam
|
||||
| DefKind::ConstParam
|
||||
| DefKind::ExternCrate
|
||||
| DefKind::Use
|
||||
| DefKind::ForeignMod
|
||||
| DefKind::AnonConst
|
||||
| DefKind::Field
|
||||
| DefKind::LifetimeParam
|
||||
| DefKind::GlobalAsm
|
||||
| DefKind::Closure
|
||||
| DefKind::Impl
|
||||
| DefKind::Generator,
|
||||
_,
|
||||
)
|
||||
| Res::Local(..)
|
||||
| Res::SelfTy(..)
|
||||
| Res::SelfCtor(..)
|
||||
|
|
|
@ -2504,10 +2504,8 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
|
||||
let container = match parent.kind {
|
||||
ModuleKind::Def(DefKind::Mod, _, _) => "module",
|
||||
ModuleKind::Def(DefKind::Trait, _, _) => "trait",
|
||||
ModuleKind::Def(kind, _, _) => kind.descr(parent.def_id().unwrap()),
|
||||
ModuleKind::Block(..) => "block",
|
||||
_ => "enum",
|
||||
};
|
||||
|
||||
let old_noun = match old_binding.is_import() {
|
||||
|
|
|
@ -760,9 +760,23 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
|
|||
Res::Def(HirDefKind::Mod, def_id) => {
|
||||
Some(Ref { kind: RefKind::Mod, span, ref_id: id_from_def_id(def_id) })
|
||||
}
|
||||
Res::PrimTy(..)
|
||||
|
||||
Res::Def(
|
||||
HirDefKind::Macro(..)
|
||||
| HirDefKind::ExternCrate
|
||||
| HirDefKind::ForeignMod
|
||||
| HirDefKind::LifetimeParam
|
||||
| HirDefKind::AnonConst
|
||||
| HirDefKind::Use
|
||||
| HirDefKind::Field
|
||||
| HirDefKind::GlobalAsm
|
||||
| HirDefKind::Impl
|
||||
| HirDefKind::Closure
|
||||
| HirDefKind::Generator,
|
||||
_,
|
||||
)
|
||||
| Res::PrimTy(..)
|
||||
| Res::SelfTy(..)
|
||||
| Res::Def(HirDefKind::Macro(..), _)
|
||||
| Res::ToolMod
|
||||
| Res::NonMacroAttr(..)
|
||||
| Res::SelfCtor(..)
|
||||
|
|
|
@ -1487,7 +1487,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
// ```
|
||||
debug!("parent_def_kind: {:?}", self.tcx.def_kind(parent_did));
|
||||
let is_raw_borrow_inside_fn_like_call = match self.tcx.def_kind(parent_did) {
|
||||
Some(DefKind::Fn | DefKind::Ctor(..)) => target_ty.is_unsafe_ptr(),
|
||||
DefKind::Fn | DefKind::Ctor(..) => target_ty.is_unsafe_ptr(),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
|
|
|
@ -150,10 +150,10 @@ crate fn program_clauses_for(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
|
|||
// FIXME(eddyb) this should only be using `def_kind`.
|
||||
match tcx.def_key(def_id).disambiguated_data.data {
|
||||
DefPathData::TypeNs(..) => match tcx.def_kind(def_id) {
|
||||
Some(DefKind::Trait | DefKind::TraitAlias) => program_clauses_for_trait(tcx, def_id),
|
||||
DefKind::Trait | DefKind::TraitAlias => program_clauses_for_trait(tcx, def_id),
|
||||
// FIXME(eddyb) deduplicate this `associated_item` call with
|
||||
// `program_clauses_for_associated_type_{value,def}`.
|
||||
Some(DefKind::AssocTy) => match tcx.associated_item(def_id).container {
|
||||
DefKind::AssocTy => match tcx.associated_item(def_id).container {
|
||||
ty::AssocItemContainer::ImplContainer(_) => {
|
||||
program_clauses_for_associated_type_value(tcx, def_id)
|
||||
}
|
||||
|
@ -161,13 +161,11 @@ crate fn program_clauses_for(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
|
|||
program_clauses_for_associated_type_def(tcx, def_id)
|
||||
}
|
||||
},
|
||||
Some(
|
||||
DefKind::Struct
|
||||
| DefKind::Enum
|
||||
| DefKind::TyAlias
|
||||
| DefKind::Union
|
||||
| DefKind::OpaqueTy,
|
||||
) => program_clauses_for_type_def(tcx, def_id),
|
||||
| DefKind::OpaqueTy => program_clauses_for_type_def(tcx, def_id),
|
||||
_ => List::empty(),
|
||||
},
|
||||
DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
|
||||
|
|
|
@ -94,10 +94,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
|
|||
}
|
||||
Err(_) => {
|
||||
let item_span = tcx.def_span(self_type_did);
|
||||
let self_descr = tcx
|
||||
.def_kind(self_type_did)
|
||||
.map(|kind| kind.descr(self_type_did))
|
||||
.unwrap_or("type");
|
||||
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
drop_impl_span,
|
||||
|
@ -244,10 +241,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
|||
|
||||
if !assumptions_in_impl_context.iter().any(predicate_matches_closure) {
|
||||
let item_span = tcx.hir().span(self_type_hir_id);
|
||||
let self_descr = tcx
|
||||
.def_kind(self_type_did)
|
||||
.map(|kind| kind.descr(self_type_did.to_def_id()))
|
||||
.unwrap_or("type");
|
||||
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did.to_def_id());
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
*predicate_sp,
|
||||
|
|
|
@ -1564,10 +1564,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
base_did: DefId,
|
||||
) {
|
||||
let struct_path = self.tcx().def_path_str(base_did);
|
||||
let kind_name = match self.tcx().def_kind(base_did) {
|
||||
Some(def_kind) => def_kind.descr(base_did),
|
||||
_ => " ",
|
||||
};
|
||||
let kind_name = self.tcx().def_kind(base_did).descr(base_did);
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx().sess,
|
||||
field.span,
|
||||
|
|
|
@ -831,6 +831,13 @@ fn primary_body_of(
|
|||
}
|
||||
|
||||
fn has_typeck_tables(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
// FIXME(#71104) some `LocalDefId` do not seem to have a corresponding `HirId`.
|
||||
if let Some(def_id) = def_id.as_local() {
|
||||
if tcx.hir().opt_local_def_id_to_hir_id(def_id).is_none() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Closures' tables come from their outermost function,
|
||||
// as they are part of the same "inference environment".
|
||||
let outer_def_id = tcx.closure_base_def_id(def_id);
|
||||
|
@ -838,11 +845,8 @@ fn has_typeck_tables(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
|||
return tcx.has_typeck_tables(outer_def_id);
|
||||
}
|
||||
|
||||
// FIXME(#71104) Should really be using just `as_local_hir_id` but
|
||||
// some `LocalDefId` do not seem to have a corresponding HirId.
|
||||
if let Some(id) =
|
||||
def_id.as_local().and_then(|def_id| tcx.hir().opt_local_def_id_to_hir_id(def_id))
|
||||
{
|
||||
if let Some(def_id) = def_id.as_local() {
|
||||
let id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
primary_body_of(tcx, id).is_some()
|
||||
} else {
|
||||
false
|
||||
|
@ -4971,15 +4975,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => {
|
||||
sugg_call = fields.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
|
||||
match def_id
|
||||
.as_local()
|
||||
.map(|def_id| hir.as_local_hir_id(def_id))
|
||||
.and_then(|hir_id| hir.def_kind(hir_id))
|
||||
{
|
||||
Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, _)) => {
|
||||
match def_id.as_local().map(|def_id| hir.def_kind(def_id)) {
|
||||
Some(DefKind::Ctor(hir::def::CtorOf::Variant, _)) => {
|
||||
msg = "instantiate this tuple variant";
|
||||
}
|
||||
Some(hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, _)) => {
|
||||
Some(DefKind::Ctor(CtorOf::Struct, _)) => {
|
||||
msg = "instantiate this tuple struct";
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -278,7 +278,7 @@ fn build_type_alias_type(cx: &DocContext<'_>, did: DefId) -> Option<clean::Type>
|
|||
}
|
||||
|
||||
pub fn build_ty(cx: &DocContext, did: DefId) -> Option<clean::Type> {
|
||||
match cx.tcx.def_kind(did)? {
|
||||
match cx.tcx.def_kind(did) {
|
||||
DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Const | DefKind::Static => {
|
||||
Some(cx.tcx.type_of(did).clean(cx))
|
||||
}
|
||||
|
|
|
@ -2135,7 +2135,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
|
|||
|
||||
let for_ = self.for_.clean(cx);
|
||||
let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) {
|
||||
Some(DefKind::TyAlias) => Some(cx.tcx.type_of(did).clean(cx)),
|
||||
DefKind::TyAlias => Some(cx.tcx.type_of(did).clean(cx)),
|
||||
_ => None,
|
||||
});
|
||||
let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| Item {
|
||||
|
|
|
@ -209,7 +209,7 @@ pub fn get_real_types(
|
|||
res.extend(adds);
|
||||
} else if !ty.is_full_generic() {
|
||||
if let Some(kind) =
|
||||
ty.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx))
|
||||
ty.def_id().map(|did| cx.tcx.def_kind(did).clean(cx))
|
||||
{
|
||||
res.insert((ty, kind));
|
||||
}
|
||||
|
@ -226,9 +226,7 @@ pub fn get_real_types(
|
|||
if !adds.is_empty() {
|
||||
res.extend(adds);
|
||||
} else if !ty.is_full_generic() {
|
||||
if let Some(kind) =
|
||||
ty.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx))
|
||||
{
|
||||
if let Some(kind) = ty.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) {
|
||||
res.insert((ty.clone(), kind));
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +234,7 @@ pub fn get_real_types(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if let Some(kind) = arg.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx)) {
|
||||
if let Some(kind) = arg.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) {
|
||||
res.insert((arg.clone(), kind));
|
||||
}
|
||||
if let Some(gens) = arg.generics() {
|
||||
|
@ -246,9 +244,7 @@ pub fn get_real_types(
|
|||
if !adds.is_empty() {
|
||||
res.extend(adds);
|
||||
}
|
||||
} else if let Some(kind) =
|
||||
gen.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx))
|
||||
{
|
||||
} else if let Some(kind) = gen.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) {
|
||||
res.insert((gen.clone(), kind));
|
||||
}
|
||||
}
|
||||
|
@ -275,7 +271,7 @@ pub fn get_all_types(
|
|||
if !args.is_empty() {
|
||||
all_types.extend(args);
|
||||
} else {
|
||||
if let Some(kind) = arg.type_.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx)) {
|
||||
if let Some(kind) = arg.type_.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) {
|
||||
all_types.insert((arg.type_.clone(), kind));
|
||||
}
|
||||
}
|
||||
|
@ -285,9 +281,7 @@ pub fn get_all_types(
|
|||
FnRetTy::Return(ref return_type) => {
|
||||
let mut ret = get_real_types(generics, &return_type, cx, 0);
|
||||
if ret.is_empty() {
|
||||
if let Some(kind) =
|
||||
return_type.def_id().and_then(|did| cx.tcx.def_kind(did).clean(cx))
|
||||
{
|
||||
if let Some(kind) = return_type.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) {
|
||||
ret.insert((return_type.clone(), kind));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ struct MyFoo;
|
|||
|
||||
impl MyFoo {
|
||||
const BAR: u32 = 1;
|
||||
//~^ ERROR associated const is never used: `BAR`
|
||||
//~^ ERROR associated constant is never used: `BAR`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: associated const is never used: `BAR`
|
||||
error: associated constant is never used: `BAR`
|
||||
--> $DIR/associated-const-dead-code.rs:6:5
|
||||
|
|
||||
LL | const BAR: u32 = 1;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
// build-pass
|
||||
// This test ensures that we do not allow ZST statics to initialize themselves without ever
|
||||
// actually creating a value of that type. This is important, as the ZST may have private fields
|
||||
// that users can reasonably expect to only get initialized by their own code. Thus unsafe code
|
||||
// can depend on this fact and will thus do unsound things when it is violated.
|
||||
// See https://github.com/rust-lang/rust/issues/71078 for more details.
|
||||
|
||||
static FOO: () = FOO;
|
||||
static FOO: () = FOO; //~ cycle detected when const-evaluating `FOO`
|
||||
|
||||
fn main() {
|
||||
FOO
|
||||
|
|
21
src/test/ui/consts/recursive-zst-static.stderr
Normal file
21
src/test/ui/consts/recursive-zst-static.stderr
Normal file
|
@ -0,0 +1,21 @@
|
|||
error[E0391]: cycle detected when const-evaluating `FOO`
|
||||
--> $DIR/recursive-zst-static.rs:7:18
|
||||
|
|
||||
LL | static FOO: () = FOO;
|
||||
| ^^^
|
||||
|
|
||||
note: ...which requires const-evaluating `FOO`...
|
||||
--> $DIR/recursive-zst-static.rs:7:1
|
||||
|
|
||||
LL | static FOO: () = FOO;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires const-evaluating `FOO`, completing the cycle
|
||||
note: cycle used when const-evaluating + checking `FOO`
|
||||
--> $DIR/recursive-zst-static.rs:7:1
|
||||
|
|
||||
LL | static FOO: () = FOO;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
|
@ -3,6 +3,6 @@
|
|||
|
||||
const foo: isize = 3;
|
||||
//~^ ERROR: should have an upper case name
|
||||
//~^^ ERROR: constant item is never used
|
||||
//~^^ ERROR: constant is never used
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: constant item is never used: `foo`
|
||||
error: constant is never used: `foo`
|
||||
--> $DIR/issue-17718-const-naming.rs:4:1
|
||||
|
|
||||
LL | const foo: isize = 3;
|
||||
|
|
|
@ -17,14 +17,14 @@ mod foo2 {
|
|||
}
|
||||
|
||||
pub static pub_static: isize = 0;
|
||||
static priv_static: isize = 0; //~ ERROR: static item is never used
|
||||
static priv_static: isize = 0; //~ ERROR: static is never used
|
||||
const used_static: isize = 0;
|
||||
pub static used_static2: isize = used_static;
|
||||
const USED_STATIC: isize = 0;
|
||||
const STATIC_USED_IN_ENUM_DISCRIMINANT: isize = 10;
|
||||
|
||||
pub const pub_const: isize = 0;
|
||||
const priv_const: isize = 0; //~ ERROR: constant item is never used
|
||||
const priv_const: isize = 0; //~ ERROR: constant is never used
|
||||
const used_const: isize = 0;
|
||||
pub const used_const2: isize = used_const;
|
||||
const USED_CONST: isize = 1;
|
||||
|
|
|
@ -10,13 +10,13 @@ note: the lint level is defined here
|
|||
LL | #![deny(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: static item is never used: `priv_static`
|
||||
error: static is never used: `priv_static`
|
||||
--> $DIR/lint-dead-code-1.rs:20:1
|
||||
|
|
||||
LL | static priv_static: isize = 0;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: constant item is never used: `priv_const`
|
||||
error: constant is never used: `priv_const`
|
||||
--> $DIR/lint-dead-code-1.rs:27:1
|
||||
|
|
||||
LL | const priv_const: isize = 0;
|
||||
|
|
|
@ -12,7 +12,7 @@ extern {
|
|||
|
||||
struct Foo; //~ ERROR: struct is never constructed
|
||||
impl Foo {
|
||||
fn foo(&self) { //~ ERROR: method is never used
|
||||
fn foo(&self) { //~ ERROR: associated function is never used
|
||||
bar()
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ mod blah {
|
|||
|
||||
enum c_void {} //~ ERROR: enum is never used
|
||||
extern {
|
||||
fn free(p: *const c_void); //~ ERROR: foreign function is never used
|
||||
fn free(p: *const c_void); //~ ERROR: function is never used
|
||||
}
|
||||
|
||||
// Check provided method
|
||||
|
|
|
@ -10,7 +10,7 @@ note: the lint level is defined here
|
|||
LL | #![deny(dead_code)]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: method is never used: `foo`
|
||||
error: associated function is never used: `foo`
|
||||
--> $DIR/lint-dead-code-3.rs:15:5
|
||||
|
|
||||
LL | fn foo(&self) {
|
||||
|
@ -28,7 +28,7 @@ error: enum is never used: `c_void`
|
|||
LL | enum c_void {}
|
||||
| ^^^^^^
|
||||
|
||||
error: foreign function is never used: `free`
|
||||
error: function is never used: `free`
|
||||
--> $DIR/lint-dead-code-3.rs:61:5
|
||||
|
|
||||
LL | fn free(p: *const c_void);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(staged_api)]
|
||||
//~^ ERROR crate has missing stability attribute
|
||||
//~^ ERROR module has missing stability attribute
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: crate has missing stability attribute
|
||||
error: module has missing stability attribute
|
||||
--> $DIR/missing-stability-attr-at-top-level.rs:1:1
|
||||
|
|
||||
LL | / #![feature(staged_api)]
|
||||
|
|
16
src/test/ui/unsized/return-unsized-from-trait-method.rs
Normal file
16
src/test/ui/unsized/return-unsized-from-trait-method.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// ignore-tidy-linelength
|
||||
|
||||
// regression test for #26376
|
||||
|
||||
trait Foo {
|
||||
fn foo(&self) -> [u8];
|
||||
}
|
||||
|
||||
fn foo(f: Option<&dyn Foo>) {
|
||||
if let Some(f) = f {
|
||||
let _ = f.foo();
|
||||
//~^ ERROR cannot move a value of type [u8]: the size of [u8] cannot be statically determined
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { foo(None) }
|
|
@ -0,0 +1,9 @@
|
|||
error[E0161]: cannot move a value of type [u8]: the size of [u8] cannot be statically determined
|
||||
--> $DIR/return-unsized-from-trait-method.rs:11:17
|
||||
|
|
||||
LL | let _ = f.foo();
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0161`.
|
Loading…
Add table
Add a link
Reference in a new issue