diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 1cd01c8c5bcb0..00b4bf96afa59 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -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 .basic_blocks() .indices() diff --git a/src/librustc_data_structures/box_region.rs b/src/librustc_data_structures/box_region.rs index edeb4f83c7d7e..eb6f4e8213ec7 100644 --- a/src/librustc_data_structures/box_region.rs +++ b/src/librustc_data_structures/box_region.rs @@ -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 = Cell::new(Action::Complete)); - pub struct PinnedGenerator { - generator: Pin, Return = R>>>, + generator: Pin, Return = R>>>, } impl PinnedGenerator { - pub fn new, Return = R> + 'static>( + pub fn new, 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 PinnedGenerator { } 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 + 'static>( + fn new + '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 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"), } } } diff --git a/src/librustc_hir/def.rs b/src/librustc_hir/def.rs index 3334cc32a52f7..88049f85f45e4 100644 --- a/src/librustc_hir/def.rs +++ b/src/librustc_hir/def.rs @@ -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, } } } diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index b66e6101b504b..d342f8b0ad21c 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -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 { diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs index 53f52038ed022..1986838e4016c 100644 --- a/src/librustc_infer/infer/error_reporting/need_type_info.rs +++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs @@ -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) }; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 4c054795136b9..4b09148eab61f 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -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)) diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 1fb260f66fa3b..39d8213f2629b 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -562,8 +562,8 @@ impl MetadataBlob { } impl EntryKind { - fn def_kind(&self) -> Option { - 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 { + 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,20 +1008,19 @@ 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) { - callback(Export { - res: Res::Def(kind, self.local_def_id(child_index)), - ident: self.item_ident(child_index, sess), - vis: self.get_visibility(child_index), - span: self - .root - .tables - .span - .get(self, child_index) - .unwrap() - .decode((self, sess)), - }); - } + 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), + vis: self.get_visibility(child_index), + span: self + .root + .tables + .span + .get(self, child_index) + .unwrap() + .decode((self, sess)), + }); } 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); diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs index aee80b6e14e14..1c71fc57bea5a 100644 --- a/src/librustc_middle/hir/map/mod.rs +++ b/src/librustc_middle/hir/map/mod.rs @@ -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 { - 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> { @@ -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()); } diff --git a/src/librustc_middle/middle/stability.rs b/src/librustc_middle/middle/stability.rs index 9d95a700313d6..54c05bca3bd2b 100644 --- a/src/librustc_middle/middle/stability.rs +++ b/src/librustc_middle/middle/stability.rs @@ -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 diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 341fec0c07b36..34c05ec59f388 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -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> + '_ { - 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 + '_ { 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) -> >::Iter { - self.predecessors_for(node).clone().into_iter() + self.predecessors()[node].clone().into_iter() } } diff --git a/src/librustc_middle/mir/predecessors.rs b/src/librustc_middle/mir/predecessors.rs index 629b5c2efb711..9508365886aa7 100644 --- a/src/librustc_middle/mir/predecessors.rs +++ b/src/librustc_middle/mir/predecessors.rs @@ -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,40 +12,49 @@ use crate::mir::{BasicBlock, BasicBlockData}; pub type Predecessors = IndexVec>; #[derive(Clone, Debug)] -pub struct PredecessorCache { - cache: Lock>, +pub(super) struct PredecessorCache { + cache: Lock>>, } 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>, - ) -> MappedLockGuard<'_, Predecessors> { - LockGuard::map(self.cache.lock(), |cache| { - cache.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 { - for &succ in term.successors() { - preds[succ].push(bb); - } + ) -> Lrc { + 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 { + for &succ in term.successors() { + preds[succ].push(bb); } } + } - preds - }) - }) + Lrc::new(preds) + })) } } diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index 51bbb9016b6a2..8b0509e314ce6 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -620,7 +620,7 @@ rustc_queries! { cache_on_disk_if { true } } - query def_kind(_: DefId) -> Option {} + 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 diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 7797374259cb7..eae4055877b2a 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -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"), - }, - DefPathData::LifetimeNs(..) => ("a", "lifetime"), - DefPathData::Impl => ("an", "implementation"), - DefPathData::TypeNs(..) | DefPathData::ValueNs(..) | DefPathData::MacroNs(..) => { - unreachable!() - } - _ => bug!("article_and_description called on def_id {:?}", def_id), - }) + 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"), + }, + def_kind => (def_kind.article(), def_kind.descr(def_id)), + } } } diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index b785f79e1f35e..d6c8ccf5ea62a 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -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, } }; diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 8c8d20655f96f..2d2704fc2bd89 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -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)) } _ => { diff --git a/src/librustc_middle/ty/util.rs b/src/librustc_middle/ty/util.rs index 4b10a8ba8210b..b46caf7985208 100644 --- a/src/librustc_middle/ty/util.rs +++ b/src/librustc_middle/ty/util.rs @@ -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 diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 6cc4ee432a58c..d424d0525fdd8 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -1269,7 +1269,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, ) -> impl Iterator + '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 { diff --git a/src/librustc_mir/borrow_check/region_infer/values.rs b/src/librustc_mir/borrow_check/region_infer/values.rs index 57a3fa6f79b50..6cd814962c613 100644 --- a/src/librustc_mir/borrow_check/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/region_infer/values.rs @@ -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)), diff --git a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs index af09dc5b8039e..ec52a08c7b216 100644 --- a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs @@ -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) diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 6d0a02ee3a47f..b6d10d1e3701d 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -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)), diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 45abde4347728..a497a6784ff6b 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -632,7 +632,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // FIXME: The above is likely untrue. See // . 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()); diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 9b2b7196fc0e9..0d0ed465c1cc6 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -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) + } } }) } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 8188106b5f187..4d76a23005065 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -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), diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index cad5b114ae455..db1ea72c0a531 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -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); } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index a3465b021826c..bad0b94f3ece7 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -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 { diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 6c852d9e36709..8829b10d5dd79 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -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), } diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index 6d1fbd6c868c5..3b778cacefe13 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -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) } diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 2e48fd9d659bd..ad9934d379ac5 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -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()); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index b1fbba7e1a7b3..e4501b5c3b562 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -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,11 +538,10 @@ 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 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); - } + 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 { @@ -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 => (), } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f9156be3f4ada..bd484fc7a90cf 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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(..) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 77aa7230aa893..26ea75ad7ef64 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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() { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 1939b6261d57b..8456a0304fec6 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -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(..) diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 88b9d257795f7..19260f4d573ac 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -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, }; diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 4f3eba9995638..19765c36ae26a 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -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::Struct + | DefKind::Enum + | DefKind::TyAlias + | DefKind::Union + | DefKind::OpaqueTy => program_clauses_for_type_def(tcx, def_id), _ => List::empty(), }, DefPathData::Impl => program_clauses_for_impl(tcx, def_id), diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 078401ee6a815..478a848cf09dd 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -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, diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 2bca5e7582526..d287589789e2d 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -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, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b7e86c0791f63..d631d3c33405e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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::>().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"; } _ => {} diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 6208c14710183..cd098936ed6a5 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -278,7 +278,7 @@ fn build_type_alias_type(cx: &DocContext<'_>, did: DefId) -> Option } pub fn build_ty(cx: &DocContext, did: DefId) -> Option { - 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)) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 63ab0ef5f1728..55c32e917f25c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2135,7 +2135,7 @@ impl Clean> 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, for_: Type, items: Vec| Item { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index ec5ac48ffe4a8..c4e4802db6c07 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -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)); } } diff --git a/src/test/ui/associated-const/associated-const-dead-code.rs b/src/test/ui/associated-const/associated-const-dead-code.rs index c47e474d2dd74..e659bdb83f9c1 100644 --- a/src/test/ui/associated-const/associated-const-dead-code.rs +++ b/src/test/ui/associated-const/associated-const-dead-code.rs @@ -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() { diff --git a/src/test/ui/associated-const/associated-const-dead-code.stderr b/src/test/ui/associated-const/associated-const-dead-code.stderr index 172aed733fca9..9b6bbb68a71f7 100644 --- a/src/test/ui/associated-const/associated-const-dead-code.stderr +++ b/src/test/ui/associated-const/associated-const-dead-code.stderr @@ -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; diff --git a/src/test/ui/consts/recursive-zst-static.rs b/src/test/ui/consts/recursive-zst-static.rs index df7562bd9f5d2..768df58e1e32e 100644 --- a/src/test/ui/consts/recursive-zst-static.rs +++ b/src/test/ui/consts/recursive-zst-static.rs @@ -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 diff --git a/src/test/ui/consts/recursive-zst-static.stderr b/src/test/ui/consts/recursive-zst-static.stderr new file mode 100644 index 0000000000000..e21dcf691ab0a --- /dev/null +++ b/src/test/ui/consts/recursive-zst-static.stderr @@ -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`. diff --git a/src/test/ui/issues/issue-17718-const-naming.rs b/src/test/ui/issues/issue-17718-const-naming.rs index d30b95843f300..7386478f9f08c 100644 --- a/src/test/ui/issues/issue-17718-const-naming.rs +++ b/src/test/ui/issues/issue-17718-const-naming.rs @@ -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() {} diff --git a/src/test/ui/issues/issue-17718-const-naming.stderr b/src/test/ui/issues/issue-17718-const-naming.stderr index 4c0aa0553ebd2..ce4ebcb5e3ef6 100644 --- a/src/test/ui/issues/issue-17718-const-naming.stderr +++ b/src/test/ui/issues/issue-17718-const-naming.stderr @@ -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; diff --git a/src/test/ui/lint/dead-code/lint-dead-code-1.rs b/src/test/ui/lint/dead-code/lint-dead-code-1.rs index 09977f8df51cf..896147fcc7738 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-1.rs +++ b/src/test/ui/lint/dead-code/lint-dead-code-1.rs @@ -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; diff --git a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr index 0a08aa6da9ac0..af97ea98b2b6d 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr @@ -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; diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.rs b/src/test/ui/lint/dead-code/lint-dead-code-3.rs index 4397522f3f32f..6826d2cd67eb9 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.rs +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.rs @@ -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 diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr index aab25c481e6c7..a2614a0bf74b3 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr @@ -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); diff --git a/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs index 8f750ae62f5e4..38faa24691604 100644 --- a/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs +++ b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs @@ -1,4 +1,4 @@ #![feature(staged_api)] -//~^ ERROR crate has missing stability attribute +//~^ ERROR module has missing stability attribute fn main() {} diff --git a/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr index b6c9564e904c4..c7ade234d3dcc 100644 --- a/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr +++ b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr @@ -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)] diff --git a/src/test/ui/unsized/return-unsized-from-trait-method.rs b/src/test/ui/unsized/return-unsized-from-trait-method.rs new file mode 100644 index 0000000000000..2d265d5db5c14 --- /dev/null +++ b/src/test/ui/unsized/return-unsized-from-trait-method.rs @@ -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) } diff --git a/src/test/ui/unsized/return-unsized-from-trait-method.stderr b/src/test/ui/unsized/return-unsized-from-trait-method.stderr new file mode 100644 index 0000000000000..7ecdd28616674 --- /dev/null +++ b/src/test/ui/unsized/return-unsized-from-trait-method.stderr @@ -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`.