Importing rustc-1.60.0 Test: ./build.py --lto=thin Bug: 218368713 Change-Id: Id769ad47aab28ec7b551d06785fb811cdf441aec
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index a9db846..b133441 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml
@@ -12,8 +12,8 @@ either = "1.5.0" gsgdt = "0.1.2" tracing = "0.1" -rustc-rayon = "0.3.1" -rustc-rayon-core = "0.3.1" +rustc-rayon = "0.3.2" +rustc-rayon-core = "0.3.2" polonius-engine = "0.13.0" rustc_apfloat = { path = "../rustc_apfloat" } rustc_attr = { path = "../rustc_attr" } @@ -29,7 +29,7 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -chalk-ir = "0.75.0" +chalk-ir = "0.76.0" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_session = { path = "../rustc_session" } rustc_type_ir = { path = "../rustc_type_ir" }
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index a936852..c4e6734 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs
@@ -52,6 +52,9 @@ Vec<rustc_middle::traits::query::OutlivesBound<'tcx>> > >, + [] dtorck_constraint: rustc_middle::traits::query::DtorckConstraint<'tcx>, + [] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>, + [] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>, [] type_op_subtype: rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, ()> @@ -85,7 +88,8 @@ // Interned types [] tys: rustc_middle::ty::TyS<'tcx>, - [] predicates: rustc_middle::ty::PredicateInner<'tcx>, + [] predicates: rustc_middle::ty::PredicateS<'tcx>, + [] consts: rustc_middle::ty::ConstS<'tcx>, // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena @@ -95,6 +99,7 @@ // This is used to decode the &'tcx [Span] for InlineAsm's line_spans. [decode] span: rustc_span::Span, [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>, + [decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>, [] dep_kind: rustc_middle::dep_graph::DepKindStruct, ]);
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 5c7cdbe..d20be0a 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -266,7 +266,9 @@ /// has been removed. fn extract_def_id<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> { if self.kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash { - Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()))) + Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()), &mut || { + panic!("Failed to extract DefId: {:?} {}", self.kind, self.hash) + })) } else { None }
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 79d7ca3..6bfd1b7 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -1,6 +1,5 @@ use crate::ty::{self, TyCtxt}; use rustc_data_structures::profiling::SelfProfilerRef; -use rustc_data_structures::sync::Lock; use rustc_query_system::ich::StableHashingContext; use rustc_session::Session; @@ -17,6 +16,7 @@ pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>; pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>; +pub type TaskDepsRef<'a> = rustc_query_system::dep_graph::TaskDepsRef<'a, DepKind>; pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery<DepKind>; pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph<DepKind>; pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter<DepKind>; @@ -45,7 +45,7 @@ write!(f, ")") } - fn with_deps<OP, R>(task_deps: Option<&Lock<TaskDeps>>, op: OP) -> R + fn with_deps<OP, R>(task_deps: TaskDepsRef<'_>, op: OP) -> R where OP: FnOnce() -> R, { @@ -58,10 +58,10 @@ fn read_deps<OP>(op: OP) where - OP: for<'a> FnOnce(Option<&'a Lock<TaskDeps>>), + OP: for<'a> FnOnce(TaskDepsRef<'a>), { ty::tls::with_context_opt(|icx| { - let icx = if let Some(icx) = icx { icx } else { return }; + let Some(icx) = icx else { return }; op(icx.task_deps) }) }
diff --git a/compiler/rustc_middle/src/hir/exports.rs b/compiler/rustc_middle/src/hir/exports.rs deleted file mode 100644 index f37b976..0000000 --- a/compiler/rustc_middle/src/hir/exports.rs +++ /dev/null
@@ -1,28 +0,0 @@ -use crate::ty; - -use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def::Res; -use rustc_hir::def_id::LocalDefId; -use rustc_macros::HashStable; -use rustc_span::symbol::Ident; -use rustc_span::Span; - -use std::fmt::Debug; - -/// This is the replacement export map. It maps a module to all of the exports -/// within. -pub type ExportMap = FxHashMap<LocalDefId, Vec<Export>>; - -#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] -pub struct Export { - /// The name of the target. - pub ident: Ident, - /// The resolution of the target. - /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter. - pub res: Res<!>, - /// The span of the target. - pub span: Span, - /// The visibility of the export. - /// We include non-`pub` exports for hygienic macros that get used from extern crates. - pub vis: ty::Visibility, -}
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 394a1fc..f36847c 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -12,6 +12,7 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::*; use rustc_index::vec::Idx; +use rustc_middle::hir::nested_filter; use rustc_span::def_id::StableCrateId; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; @@ -117,13 +118,13 @@ } impl<'hir> Iterator for ParentOwnerIterator<'hir> { - type Item = (HirId, OwnerNode<'hir>); + type Item = (LocalDefId, OwnerNode<'hir>); fn next(&mut self) -> Option<Self::Item> { if self.current_id.local_id.index() != 0 { self.current_id.local_id = ItemLocalId::new(0); if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { - return Some((self.current_id, node.node)); + return Some((self.current_id.owner, node.node)); } } if self.current_id == CRATE_HIR_ID { @@ -141,42 +142,42 @@ // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`. if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { - return Some((self.current_id, node.node)); + return Some((self.current_id.owner, node.node)); } } } } impl<'hir> Map<'hir> { - pub fn krate(&self) -> &'hir Crate<'hir> { + pub fn krate(self) -> &'hir Crate<'hir> { self.tcx.hir_crate(()) } - pub fn root_module(&self) -> &'hir Mod<'hir> { + pub fn root_module(self) -> &'hir Mod<'hir> { match self.tcx.hir_owner(CRATE_DEF_ID).map(|o| o.node) { Some(OwnerNode::Crate(item)) => item, _ => bug!(), } } - pub fn items(&self) -> impl Iterator<Item = &'hir Item<'hir>> + 'hir { + pub fn items(self) -> impl Iterator<Item = &'hir Item<'hir>> + 'hir { let krate = self.krate(); - krate.owners.iter().filter_map(|owner| match owner.as_ref()?.node() { + krate.owners.iter().filter_map(|owner| match owner.as_owner()?.node() { OwnerNode::Item(item) => Some(item), _ => None, }) } - pub fn def_key(&self, def_id: LocalDefId) -> DefKey { + pub fn def_key(self, def_id: LocalDefId) -> DefKey { // Accessing the DefKey is ok, since it is part of DefPathHash. self.tcx.untracked_resolutions.definitions.def_key(def_id) } - pub fn def_path_from_hir_id(&self, id: HirId) -> Option<DefPath> { + pub fn def_path_from_hir_id(self, id: HirId) -> Option<DefPath> { self.opt_local_def_id(id).map(|def_id| self.def_path(def_id)) } - pub fn def_path(&self, def_id: LocalDefId) -> DefPath { + pub fn def_path(self, def_id: LocalDefId) -> DefPath { // Accessing the DefPath is ok, since it is part of DefPathHash. self.tcx.untracked_resolutions.definitions.def_path(def_id) } @@ -188,7 +189,7 @@ } #[inline] - pub fn local_def_id(&self, hir_id: HirId) -> LocalDefId { + pub fn local_def_id(self, hir_id: HirId) -> LocalDefId { self.opt_local_def_id(hir_id).unwrap_or_else(|| { bug!( "local_def_id: no entry for `{:?}`, which has a map of `{:?}`", @@ -199,25 +200,32 @@ } #[inline] - pub fn opt_local_def_id(&self, hir_id: HirId) -> Option<LocalDefId> { - // FIXME(#85914) is this access safe for incr. comp.? - self.tcx.untracked_resolutions.definitions.opt_hir_id_to_local_def_id(hir_id) + pub fn opt_local_def_id(self, hir_id: HirId) -> Option<LocalDefId> { + if hir_id.local_id == ItemLocalId::new(0) { + Some(hir_id.owner) + } else { + self.tcx + .hir_owner_nodes(hir_id.owner) + .as_owner()? + .local_id_to_def_id + .get(&hir_id.local_id) + .copied() + } } #[inline] - pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId { - // FIXME(#85914) is this access safe for incr. comp.? - self.tcx.untracked_resolutions.definitions.local_def_id_to_hir_id(def_id) + pub fn local_def_id_to_hir_id(self, def_id: LocalDefId) -> HirId { + self.tcx.local_def_id_to_hir_id(def_id) } - pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ { + pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'hir { // Create a dependency to the crate to be sure we reexcute this when the amount of // definitions change. self.tcx.ensure().hir_crate(()); self.tcx.untracked_resolutions.definitions.iter_local_def_id() } - pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> { + pub fn opt_def_kind(self, local_def_id: LocalDefId) -> Option<DefKind> { let hir_id = self.local_def_id_to_hir_id(local_def_id); let def_kind = match self.find(hir_id)? { Node::Item(item) => match item.kind { @@ -304,49 +312,60 @@ Some(def_kind) } - pub fn def_kind(&self, local_def_id: LocalDefId) -> DefKind { + pub fn def_kind(self, local_def_id: LocalDefId) -> DefKind { self.opt_def_kind(local_def_id) .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", local_def_id)) } - pub fn find_parent_node(&self, id: HirId) -> Option<HirId> { + pub fn find_parent_node(self, id: HirId) -> Option<HirId> { if id.local_id == ItemLocalId::from_u32(0) { Some(self.tcx.hir_owner_parent(id.owner)) } else { - let owner = self.tcx.hir_owner_nodes(id.owner)?; + let owner = self.tcx.hir_owner_nodes(id.owner).as_owner()?; let node = owner.nodes[id.local_id].as_ref()?; let hir_id = HirId { owner: id.owner, local_id: node.parent }; Some(hir_id) } } - pub fn get_parent_node(&self, hir_id: HirId) -> HirId { + pub fn get_parent_node(self, hir_id: HirId) -> HirId { self.find_parent_node(hir_id).unwrap() } /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. - pub fn find(&self, id: HirId) -> Option<Node<'hir>> { + pub fn find(self, id: HirId) -> Option<Node<'hir>> { if id.local_id == ItemLocalId::from_u32(0) { let owner = self.tcx.hir_owner(id.owner)?; Some(owner.node.into()) } else { - let owner = self.tcx.hir_owner_nodes(id.owner)?; + let owner = self.tcx.hir_owner_nodes(id.owner).as_owner()?; let node = owner.nodes[id.local_id].as_ref()?; Some(node.node) } } + /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. + #[inline] + pub fn find_by_def_id(self, id: LocalDefId) -> Option<Node<'hir>> { + self.find(self.local_def_id_to_hir_id(id)) + } + /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found. - pub fn get(&self, id: HirId) -> Node<'hir> { + pub fn get(self, id: HirId) -> Node<'hir> { self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id)) } - pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> { + /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found. + #[inline] + pub fn get_by_def_id(self, id: LocalDefId) -> Node<'hir> { + self.find_by_def_id(id).unwrap_or_else(|| bug!("couldn't find {:?} in the HIR map", id)) + } + + pub fn get_if_local(self, id: DefId) -> Option<Node<'hir>> { id.as_local().and_then(|id| self.find(self.local_def_id_to_hir_id(id))) } - pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> { - let id = id.as_local()?; + pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { let node = self.tcx.hir_owner(id)?; match node.node { OwnerNode::ImplItem(impl_item) => Some(&impl_item.generics), @@ -367,27 +386,27 @@ } } - pub fn item(&self, id: ItemId) -> &'hir Item<'hir> { + pub fn item(self, id: ItemId) -> &'hir Item<'hir> { self.tcx.hir_owner(id.def_id).unwrap().node.expect_item() } - pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> { + pub fn trait_item(self, id: TraitItemId) -> &'hir TraitItem<'hir> { self.tcx.hir_owner(id.def_id).unwrap().node.expect_trait_item() } - pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> { + pub fn impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> { self.tcx.hir_owner(id.def_id).unwrap().node.expect_impl_item() } - pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { + pub fn foreign_item(self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { self.tcx.hir_owner(id.def_id).unwrap().node.expect_foreign_item() } - pub fn body(&self, id: BodyId) -> &'hir Body<'hir> { + pub fn body(self, id: BodyId) -> &'hir Body<'hir> { self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[&id.hir_id.local_id] } - pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { + pub fn fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { if let Some(node) = self.find(hir_id) { fn_decl(node) } else { @@ -395,7 +414,7 @@ } } - pub fn fn_sig_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> { + pub fn fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> { if let Some(node) = self.find(hir_id) { fn_sig(node) } else { @@ -403,7 +422,7 @@ } } - pub fn enclosing_body_owner(&self, hir_id: HirId) -> HirId { + pub fn enclosing_body_owner(self, hir_id: HirId) -> HirId { for (parent, _) in self.parent_iter(hir_id) { if let Some(body) = self.maybe_body_owned_by(parent) { return self.body_owner(body); @@ -416,24 +435,24 @@ /// Returns the `HirId` that corresponds to the definition of /// which this is the body of, i.e., a `fn`, `const` or `static` /// item (possibly associated), a closure, or a `hir::AnonConst`. - pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> HirId { + pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId { let parent = self.get_parent_node(hir_id); assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id))); parent } - pub fn body_owner_def_id(&self, id: BodyId) -> LocalDefId { + pub fn body_owner_def_id(self, id: BodyId) -> LocalDefId { self.local_def_id(self.body_owner(id)) } /// Given a `HirId`, returns the `BodyId` associated with it, /// if the node is a body owner, otherwise returns `None`. - pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option<BodyId> { + pub fn maybe_body_owned_by(self, hir_id: HirId) -> Option<BodyId> { self.find(hir_id).map(associated_body).flatten() } /// Given a body owner's id, returns the `BodyId` associated with it. - pub fn body_owned_by(&self, id: HirId) -> BodyId { + pub fn body_owned_by(self, id: HirId) -> BodyId { self.maybe_body_owned_by(id).unwrap_or_else(|| { span_bug!( self.span(id), @@ -443,7 +462,7 @@ }) } - pub fn body_param_names(&self, id: BodyId) -> impl Iterator<Item = Ident> + 'hir { + pub fn body_param_names(self, id: BodyId) -> impl Iterator<Item = Ident> + 'hir { self.body(id).params.iter().map(|arg| match arg.pat.kind { PatKind::Binding(_, _, ident, _) => ident, _ => Ident::empty(), @@ -453,7 +472,7 @@ /// Returns the `BodyOwnerKind` of this `LocalDefId`. /// /// Panics if `LocalDefId` does not have an associated body. - pub fn body_owner_kind(&self, id: HirId) -> BodyOwnerKind { + pub fn body_owner_kind(self, id: HirId) -> BodyOwnerKind { match self.get(id) { Node::Item(&Item { kind: ItemKind::Const(..), .. }) | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) @@ -476,7 +495,7 @@ /// This should only be used for determining the context of a body, a return /// value of `Some` does not always suggest that the owner of the body is `const`, /// just that it has to be checked as if it were. - pub fn body_const_context(&self, did: LocalDefId) -> Option<ConstContext> { + pub fn body_const_context(self, did: LocalDefId) -> Option<ConstContext> { let hir_id = self.local_def_id_to_hir_id(did); let ccx = match self.body_owner_kind(hir_id) { BodyOwnerKind::Const => ConstContext::Const, @@ -503,7 +522,7 @@ .owners .iter_enumerated() .flat_map(move |(owner, owner_info)| { - let bodies = &owner_info.as_ref()?.nodes.bodies; + let bodies = &owner_info.as_owner()?.nodes.bodies; Some(bodies.iter().map(move |&(local_id, _)| { let hir_id = HirId { owner, local_id }; let body_id = BodyId { hir_id }; @@ -520,7 +539,7 @@ par_iter(&self.krate().owners.raw).enumerate().for_each(|(owner, owner_info)| { let owner = LocalDefId::new(owner); - if let Some(owner_info) = owner_info { + if let MaybeOwner::Owner(owner_info) = owner_info { par_iter(owner_info.nodes.bodies.range(..)).for_each(|(local_id, _)| { let hir_id = HirId { owner, local_id: *local_id }; let body_id = BodyId { hir_id }; @@ -530,15 +549,17 @@ }); } - pub fn ty_param_owner(&self, id: HirId) -> HirId { + pub fn ty_param_owner(self, id: HirId) -> LocalDefId { match self.get(id) { - Node::Item(&Item { kind: ItemKind::Trait(..) | ItemKind::TraitAlias(..), .. }) => id, - Node::GenericParam(_) => self.get_parent_node(id), + Node::Item(&Item { kind: ItemKind::Trait(..) | ItemKind::TraitAlias(..), .. }) => { + id.expect_owner() + } + Node::GenericParam(_) => self.get_parent_item(id), _ => bug!("ty_param_owner: {} not a type parameter", self.node_to_string(id)), } } - pub fn ty_param_name(&self, id: HirId) -> Symbol { + pub fn ty_param_name(self, id: HirId) -> Symbol { match self.get(id) { Node::Item(&Item { kind: ItemKind::Trait(..) | ItemKind::TraitAlias(..), .. }) => { kw::SelfUpper @@ -548,18 +569,18 @@ } } - pub fn trait_impls(&self, trait_did: DefId) -> &'hir [LocalDefId] { + pub fn trait_impls(self, trait_did: DefId) -> &'hir [LocalDefId] { self.tcx.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..]) } /// Gets the attributes on the crate. This is preferable to /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. - pub fn krate_attrs(&self) -> &'hir [ast::Attribute] { + pub fn krate_attrs(self) -> &'hir [ast::Attribute] { self.attrs(CRATE_HIR_ID) } - pub fn get_module(&self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) { + pub fn get_module(self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = HirId::make_owner(module); match self.tcx.hir_owner(module).map(|o| o.node) { Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => { @@ -580,7 +601,7 @@ pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) { let krate = self.krate(); for (owner, info) in krate.owners.iter_enumerated() { - if let Some(info) = info { + if let MaybeOwner::Owner(info) = info { for (local_id, attrs) in info.attrs.map.iter() { let id = HirId { owner, local_id: *local_id }; for a in *attrs { @@ -599,12 +620,12 @@ /// follows lexical scoping rules -- then you want a different /// approach. You should override `visit_nested_item` in your /// visitor and then call `intravisit::walk_crate` instead. - pub fn visit_all_item_likes<V>(&self, visitor: &mut V) + pub fn visit_all_item_likes<V>(self, visitor: &mut V) where V: itemlikevisit::ItemLikeVisitor<'hir>, { let krate = self.krate(); - for owner in krate.owners.iter().filter_map(Option::as_ref) { + for owner in krate.owners.iter().filter_map(|i| i.as_owner()) { match owner.node() { OwnerNode::Item(item) => visitor.visit_item(item), OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), @@ -616,21 +637,23 @@ } /// A parallel version of `visit_all_item_likes`. - pub fn par_visit_all_item_likes<V>(&self, visitor: &V) + pub fn par_visit_all_item_likes<V>(self, visitor: &V) where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send, { let krate = self.krate(); - par_for_each_in(&krate.owners.raw, |owner| match owner.as_ref().map(OwnerInfo::node) { - Some(OwnerNode::Item(item)) => visitor.visit_item(item), - Some(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item), - Some(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item), - Some(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item), - Some(OwnerNode::Crate(_)) | None => {} + par_for_each_in(&krate.owners.raw, |owner| match owner.map(OwnerInfo::node) { + MaybeOwner::Owner(OwnerNode::Item(item)) => visitor.visit_item(item), + MaybeOwner::Owner(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item), + MaybeOwner::Owner(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item), + MaybeOwner::Owner(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item), + MaybeOwner::Owner(OwnerNode::Crate(_)) + | MaybeOwner::NonOwner(_) + | MaybeOwner::Phantom => {} }) } - pub fn visit_item_likes_in_module<V>(&self, module: LocalDefId, visitor: &mut V) + pub fn visit_item_likes_in_module<V>(self, module: LocalDefId, visitor: &mut V) where V: ItemLikeVisitor<'hir>, { @@ -653,7 +676,7 @@ } } - pub fn for_each_module(&self, f: impl Fn(LocalDefId)) { + pub fn for_each_module(self, f: impl Fn(LocalDefId)) { let mut queue = VecDeque::new(); queue.push_back(CRATE_DEF_ID); @@ -666,12 +689,12 @@ #[cfg(not(parallel_compiler))] #[inline] - pub fn par_for_each_module(&self, f: impl Fn(LocalDefId)) { + pub fn par_for_each_module(self, f: impl Fn(LocalDefId)) { self.for_each_module(f) } #[cfg(parallel_compiler)] - pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + Sync) { + pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync) { use rustc_data_structures::sync::{par_iter, ParallelIterator}; par_iter_submodules(self.tcx, CRATE_DEF_ID, &f); @@ -698,7 +721,7 @@ } /// Checks if the node is left-hand side of an assignment. - pub fn is_lhs(&self, id: HirId) -> bool { + pub fn is_lhs(self, id: HirId) -> bool { match self.find(self.get_parent_node(id)) { Some(Node::Expr(expr)) => match expr.kind { ExprKind::Assign(lhs, _rhs, _span) => lhs.hir_id == id, @@ -710,7 +733,7 @@ /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context. /// Used exclusively for diagnostics, to avoid suggestion function calls. - pub fn is_inside_const_context(&self, hir_id: HirId) -> bool { + pub fn is_inside_const_context(self, hir_id: HirId) -> bool { self.body_const_context(self.local_def_id(self.enclosing_body_owner(hir_id))).is_some() } @@ -736,7 +759,7 @@ /// false /// } /// ``` - pub fn get_return_block(&self, id: HirId) -> Option<HirId> { + pub fn get_return_block(self, id: HirId) -> Option<HirId> { let mut iter = self.parent_iter(id).peekable(); let mut ignore_tail = false; if let Some(node) = self.find(id) { @@ -776,23 +799,23 @@ /// parent item is in this map. The "parent item" is the closest parent node /// in the HIR which is recorded by the map and is an item, either an item /// in a module, trait, or impl. - pub fn get_parent_item(&self, hir_id: HirId) -> HirId { - if let Some((hir_id, _node)) = self.parent_owner_iter(hir_id).next() { - hir_id + pub fn get_parent_item(self, hir_id: HirId) -> LocalDefId { + if let Some((def_id, _node)) = self.parent_owner_iter(hir_id).next() { + def_id } else { - CRATE_HIR_ID + CRATE_DEF_ID } } /// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no /// module parent is in this map. - pub(super) fn get_module_parent_node(&self, hir_id: HirId) -> HirId { - for (hir_id, node) in self.parent_owner_iter(hir_id) { + pub(super) fn get_module_parent_node(self, hir_id: HirId) -> LocalDefId { + for (def_id, node) in self.parent_owner_iter(hir_id) { if let OwnerNode::Item(&Item { kind: ItemKind::Mod(_), .. }) = node { - return hir_id; + return def_id; } } - CRATE_HIR_ID + CRATE_DEF_ID } /// When on an if expression, a match arm tail expression or a match arm, give back @@ -800,7 +823,7 @@ /// /// Used by error reporting when there's a type error in an if or match arm caused by the /// expression needing to be unit. - pub fn get_if_cause(&self, hir_id: HirId) -> Option<&'hir Expr<'hir>> { + pub fn get_if_cause(self, hir_id: HirId) -> Option<&'hir Expr<'hir>> { for (_, node) in self.parent_iter(hir_id) { match node { Node::Item(_) @@ -818,7 +841,7 @@ } /// Returns the nearest enclosing scope. A scope is roughly an item or block. - pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option<HirId> { + pub fn get_enclosing_scope(self, hir_id: HirId) -> Option<HirId> { for (hir_id, node) in self.parent_iter(hir_id) { if let Node::Item(Item { kind: @@ -845,7 +868,7 @@ } /// Returns the defining scope for an opaque type definition. - pub fn get_defining_scope(&self, id: HirId) -> HirId { + pub fn get_defining_scope(self, id: HirId) -> HirId { let mut scope = id; loop { scope = self.get_enclosing_scope(scope).unwrap_or(CRATE_HIR_ID); @@ -855,50 +878,49 @@ } } - pub fn get_parent_did(&self, id: HirId) -> LocalDefId { - self.local_def_id(self.get_parent_item(id)) - } - - pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi { + pub fn get_foreign_abi(self, hir_id: HirId) -> Abi { let parent = self.get_parent_item(hir_id); - if let Some(node) = self.tcx.hir_owner(self.local_def_id(parent)) { + if let Some(node) = self.tcx.hir_owner(parent) { if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node.node { return *abi; } } - bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent)) + bug!( + "expected foreign mod or inlined parent, found {}", + self.node_to_string(HirId::make_owner(parent)) + ) } - pub fn expect_item(&self, id: LocalDefId) -> &'hir Item<'hir> { + pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> { match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::Item(item), .. }) => item, _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))), } } - pub fn expect_impl_item(&self, id: LocalDefId) -> &'hir ImplItem<'hir> { + pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> { match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item, _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))), } } - pub fn expect_trait_item(&self, id: LocalDefId) -> &'hir TraitItem<'hir> { + pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> { match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item, _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))), } } - pub fn expect_variant(&self, id: HirId) -> &'hir Variant<'hir> { + pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> { match self.find(id) { Some(Node::Variant(variant)) => variant, _ => bug!("expected variant, found {}", self.node_to_string(id)), } } - pub fn expect_foreign_item(&self, id: LocalDefId) -> &'hir ForeignItem<'hir> { + pub fn expect_foreign_item(self, id: LocalDefId) -> &'hir ForeignItem<'hir> { match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item, _ => { @@ -907,14 +929,14 @@ } } - pub fn expect_expr(&self, id: HirId) -> &'hir Expr<'hir> { + pub fn expect_expr(self, id: HirId) -> &'hir Expr<'hir> { match self.find(id) { Some(Node::Expr(expr)) => expr, _ => bug!("expected expr, found {}", self.node_to_string(id)), } } - pub fn opt_name(&self, id: HirId) -> Option<Symbol> { + pub fn opt_name(self, id: HirId) -> Option<Symbol> { Some(match self.get(id) { Node::Item(i) => i.ident.name, Node::ForeignItem(fi) => fi.ident.name, @@ -925,12 +947,12 @@ Node::Lifetime(lt) => lt.name.ident().name, Node::GenericParam(param) => param.name.ident().name, Node::Binding(&Pat { kind: PatKind::Binding(_, _, l, _), .. }) => l.name, - Node::Ctor(..) => self.name(self.get_parent_item(id)), + Node::Ctor(..) => self.name(HirId::make_owner(self.get_parent_item(id))), _ => return None, }) } - pub fn name(&self, id: HirId) -> Symbol { + pub fn name(self, id: HirId) -> Symbol { match self.opt_name(id) { Some(name) => name, None => bug!("no name for {}", self.node_to_string(id)), @@ -939,18 +961,18 @@ /// Given a node ID, gets a list of attributes associated with the AST /// corresponding to the node-ID. - pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] { + pub fn attrs(self, id: HirId) -> &'hir [ast::Attribute] { self.tcx.hir_attrs(id.owner).get(id.local_id) } /// Gets the span of the definition of the specified HIR node. /// This is used by `tcx.get_span` - pub fn span(&self, hir_id: HirId) -> Span { + pub fn span(self, hir_id: HirId) -> Span { self.opt_span(hir_id) .unwrap_or_else(|| bug!("hir::map::Map::span: id not in map: {:?}", hir_id)) } - pub fn opt_span(&self, hir_id: HirId) -> Option<Span> { + pub fn opt_span(self, hir_id: HirId) -> Option<Span> { let span = match self.find(hir_id)? { Node::Param(param) => param.span, Node::Item(item) => match &item.kind { @@ -999,7 +1021,7 @@ /// Like `hir.span()`, but includes the body of function items /// (instead of just the function header) - pub fn span_with_body(&self, hir_id: HirId) -> Span { + pub fn span_with_body(self, hir_id: HirId) -> Span { match self.find(hir_id) { Some(Node::TraitItem(item)) => item.span, Some(Node::ImplItem(impl_item)) => impl_item.span, @@ -1009,11 +1031,11 @@ } } - pub fn span_if_local(&self, id: DefId) -> Option<Span> { + pub fn span_if_local(self, id: DefId) -> Option<Span> { id.as_local().and_then(|id| self.opt_span(self.local_def_id_to_hir_id(id))) } - pub fn res_span(&self, res: Res) -> Option<Span> { + pub fn res_span(self, res: Res) -> Option<Span> { match res { Res::Err => None, Res::Local(id) => Some(self.span(id)), @@ -1023,13 +1045,13 @@ /// Get a representation of this `id` for debugging purposes. /// NOTE: Do NOT use this in diagnostics! - pub fn node_to_string(&self, id: HirId) -> String { + pub fn node_to_string(self, id: HirId) -> String { hir_id_to_string(self, id) } /// Returns the HirId of `N` in `struct Foo<const N: usize = { ... }>` when /// called with the HirId for the `{ ... }` anon const - pub fn opt_const_param_default_param_hir_id(&self, anon_const: HirId) -> Option<HirId> { + pub fn opt_const_param_default_param_hir_id(self, anon_const: HirId) -> Option<HirId> { match self.get(self.get_parent_node(anon_const)) { Node::GenericParam(GenericParam { hir_id: param_id, @@ -1043,27 +1065,27 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> { fn find(&self, hir_id: HirId) -> Option<Node<'hir>> { - self.find(hir_id) + (*self).find(hir_id) } fn body(&self, id: BodyId) -> &'hir Body<'hir> { - self.body(id) + (*self).body(id) } fn item(&self, id: ItemId) -> &'hir Item<'hir> { - self.item(id) + (*self).item(id) } fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.trait_item(id) + (*self).trait_item(id) } fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.impl_item(id) + (*self).impl_item(id) } fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { - self.foreign_item(id) + (*self).foreign_item(id) } } @@ -1101,7 +1123,7 @@ .owners .iter_enumerated() .filter_map(|(def_id, info)| { - let _ = info.as_ref()?; + let _ = info.as_owner()?; let def_path_hash = definitions.def_path_hash(def_id); let span = definitions.def_span(def_id); debug_assert_eq!(span.parent(), None); @@ -1132,7 +1154,7 @@ upstream_crates } -fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String { +fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { let id_str = format!(" (hir_id={})", id); let path_str = || { @@ -1256,10 +1278,10 @@ } impl<'hir> Visitor<'hir> for ModuleCollector<'hir> { - type Map = Map<'hir>; + type NestedFilter = nested_filter::All; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> { - intravisit::NestedVisitorMap::All(self.tcx.hir()) + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() } fn visit_item(&mut self, item: &'hir Item<'hir>) {
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 95d7273b..1053f0c 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -2,8 +2,8 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html -pub mod exports; pub mod map; +pub mod nested_filter; pub mod place; use crate::ty::query::Providers; @@ -59,26 +59,33 @@ pub fn provide(providers: &mut Providers) { providers.parent_module_from_def_id = |tcx, id| { let hir = tcx.hir(); - hir.local_def_id(hir.get_module_parent_node(hir.local_def_id_to_hir_id(id))) + hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)) }; providers.hir_crate = |tcx, ()| tcx.untracked_crate; providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; providers.hir_owner = |tcx, id| { - let owner = tcx.hir_crate(()).owners[id].as_ref()?; + let owner = tcx.hir_crate(()).owners.get(id)?.as_owner()?; let node = owner.node(); Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies }) }; - providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map(|i| &i.nodes); + providers.local_def_id_to_hir_id = |tcx, id| { + let owner = tcx.hir_crate(()).owners[id].map(|_| ()); + match owner { + MaybeOwner::Owner(_) => HirId::make_owner(id), + MaybeOwner::Phantom => bug!("No HirId for {:?}", id), + MaybeOwner::NonOwner(hir_id) => hir_id, + } + }; + providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].map(|i| &i.nodes); providers.hir_owner_parent = |tcx, id| { // Accessing the def_key is ok since its value is hashed as part of `id`'s DefPathHash. let parent = tcx.untracked_resolutions.definitions.def_key(id).parent; let parent = parent.map_or(CRATE_HIR_ID, |local_def_index| { let def_id = LocalDefId { local_def_index }; - let mut parent_hir_id = - tcx.untracked_resolutions.definitions.local_def_id_to_hir_id(def_id); + let mut parent_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); if let Some(local_id) = - tcx.hir_crate(()).owners[parent_hir_id.owner].as_ref().unwrap().parenting.get(&id) + tcx.hir_crate(()).owners[parent_hir_id.owner].unwrap().parenting.get(&id) { parent_hir_id.local_id = *local_id; } @@ -87,7 +94,7 @@ parent }; providers.hir_attrs = - |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map_or(AttributeMap::EMPTY, |o| &o.attrs); + |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs); providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id); providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP); providers.fn_arg_names = |tcx, id| { @@ -111,4 +118,6 @@ let id = id.expect_local(); tcx.resolutions(()).definitions.expansion_that_defined(id) }; + providers.in_scope_traits_map = + |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map(|owner_info| &owner_info.trait_map); }
diff --git a/compiler/rustc_middle/src/hir/nested_filter.rs b/compiler/rustc_middle/src/hir/nested_filter.rs new file mode 100644 index 0000000..7cfb207 --- /dev/null +++ b/compiler/rustc_middle/src/hir/nested_filter.rs
@@ -0,0 +1,27 @@ +use rustc_hir::intravisit::nested_filter::NestedFilter; + +/// Do not visit nested item-like things, but visit nested things +/// that are inside of an item-like. +/// +/// **This is the most common choice.** A very common pattern is +/// to use `visit_all_item_likes()` as an outer loop, +/// and to have the visitor that visits the contents of each item +/// using this setting. +pub struct OnlyBodies(()); +impl<'hir> NestedFilter<'hir> for OnlyBodies { + type Map = crate::hir::map::Map<'hir>; + const INTER: bool = false; + const INTRA: bool = true; +} + +/// Visits all nested things, including item-likes. +/// +/// **This is an unusual choice.** It is used when you want to +/// process everything within their lexical context. Typically you +/// kick off the visit by doing `walk_krate()`. +pub struct All(()); +impl<'hir> NestedFilter<'hir> for All { + type Map = crate::hir::map::Map<'hir>; + const INTER: bool = true; + const INTRA: bool = true; +}
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 605fff6..419ed42 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -23,7 +23,7 @@ use crate::infer::MemberConstraint; use crate::ty::subst::GenericArg; -use crate::ty::{self, BoundVar, List, Region, TyCtxt}; +use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt}; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use smallvec::SmallVec; @@ -64,9 +64,9 @@ /// result. #[derive(Clone, Debug)] pub struct OriginalQueryValues<'tcx> { - /// Map from the universes that appear in the query to the - /// universes in the caller context. For the time being, we only - /// ever put ROOT values into the query, so this map is very + /// Map from the universes that appear in the query to the universes in the + /// caller context. For all queries except `evaluate_goal` (used by Chalk), + /// we only ever put ROOT values into the query, so this map is very /// simple. pub universe_map: SmallVec<[ty::UniverseIndex; 4]>, @@ -104,7 +104,7 @@ CanonicalVarKind::PlaceholderTy(_) => false, CanonicalVarKind::Region(_) => true, CanonicalVarKind::PlaceholderRegion(..) => false, - CanonicalVarKind::Const(_) => true, + CanonicalVarKind::Const(..) => true, CanonicalVarKind::PlaceholderConst(_) => false, } } @@ -130,7 +130,7 @@ PlaceholderRegion(ty::PlaceholderRegion), /// Some kind of const inference variable. - Const(ty::UniverseIndex), + Const(ty::UniverseIndex, Ty<'tcx>), /// A "placeholder" that represents "any const". PlaceholderConst(ty::PlaceholderConst<'tcx>), @@ -147,7 +147,7 @@ CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe, CanonicalVarKind::Region(ui) => ui, CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe, - CanonicalVarKind::Const(ui) => ui, + CanonicalVarKind::Const(ui, _) => ui, CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.universe, } } @@ -328,8 +328,8 @@ tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into() } GenericArgKind::Const(ct) => tcx - .mk_const(ty::Const { - ty: ct.ty, + .mk_const(ty::ConstS { + ty: ct.ty(), val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)), }) .into(),
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index dcc49a5..dd303aa 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -32,9 +32,11 @@ impl<'tcx> UnifyKey for RegionVidKey<'tcx> { type Value = UnifiedRegion<'tcx>; + #[inline] fn index(&self) -> u32 { self.vid.as_u32() } + #[inline] fn from_index(i: u32) -> Self { RegionVidKey::from(ty::RegionVid::from_u32(i)) } @@ -95,14 +97,14 @@ #[derive(Copy, Clone, Debug)] pub enum ConstVariableValue<'tcx> { - Known { value: &'tcx ty::Const<'tcx> }, + Known { value: ty::Const<'tcx> }, Unknown { universe: ty::UniverseIndex }, } impl<'tcx> ConstVariableValue<'tcx> { /// If this value is known, returns the const it is known to be. /// Otherwise, `None`. - pub fn known(&self) -> Option<&'tcx ty::Const<'tcx>> { + pub fn known(&self) -> Option<ty::Const<'tcx>> { match *self { ConstVariableValue::Unknown { .. } => None, ConstVariableValue::Known { value } => Some(value), @@ -118,9 +120,11 @@ impl<'tcx> UnifyKey for ty::ConstVid<'tcx> { type Value = ConstVarValue<'tcx>; + #[inline] fn index(&self) -> u32 { self.index } + #[inline] fn from_index(i: u32) -> Self { ty::ConstVid { index: i, phantom: PhantomData } } @@ -130,7 +134,7 @@ } impl<'tcx> UnifyValue for ConstVarValue<'tcx> { - type Error = (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>); + type Error = (ty::Const<'tcx>, ty::Const<'tcx>); fn unify_values(&value1: &Self, &value2: &Self) -> Result<Self, Self::Error> { Ok(match (value1.val, value2.val) { @@ -162,18 +166,18 @@ } } -impl<'tcx> EqUnifyValue for &'tcx ty::Const<'tcx> {} +impl<'tcx> EqUnifyValue for ty::Const<'tcx> {} pub fn replace_if_possible<'tcx, V, L>( table: &mut UnificationTable<InPlace<ty::ConstVid<'tcx>, V, L>>, - c: &'tcx ty::Const<'tcx>, -) -> &'tcx ty::Const<'tcx> + c: ty::Const<'tcx>, +) -> ty::Const<'tcx> where V: snapshot_vec::VecLike<unify::Delegate<ty::ConstVid<'tcx>>>, L: UndoLogs<snapshot_vec::UndoLog<unify::Delegate<ty::ConstVid<'tcx>>>>, { - if let ty::Const { val: ty::ConstKind::Infer(InferConst::Var(vid)), .. } = c { - match table.probe_value(*vid).val.known() { + if let ty::ConstKind::Infer(InferConst::Var(vid)) = c.val() { + match table.probe_value(vid).val.known() { Some(c) => c, None => c, }
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index e6dd4e4..e85cb41 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs
@@ -56,6 +56,7 @@ #![feature(nonzero_ops)] #![feature(unwrap_infallible)] #![recursion_limit = "512"] +#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))] #[macro_use] extern crate bitflags; @@ -84,6 +85,7 @@ pub mod hir; pub mod infer; pub mod lint; +pub mod metadata; pub mod middle; pub mod mir; pub mod thir;
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index eef1035..17c77c1 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs
@@ -221,7 +221,6 @@ decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b>) + 'd>, ) { // Check for future incompatibility lints and issue a stronger warning. - let lint_id = LintId::of(lint); let future_incompatible = lint.future_incompatible; let has_future_breakage = future_incompatible.map_or( @@ -262,7 +261,7 @@ if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { // Any suggestions made here are likely to be incorrect, so anything we // emit shouldn't be automatically fixed by rustfix. - err.allow_suggestions(false); + err.disable_suggestions(); // If this is a future incompatible that is not an edition fixing lint // it'll become a hard error, so we have to emit *something*. Also, @@ -345,31 +344,29 @@ err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn }); if let Some(future_incompatible) = future_incompatible { - let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) { - "once this associated item is added to the standard library, the ambiguity may \ - cause an error or change in behavior!" - .to_owned() - } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) { - "this borrowing pattern was not meant to be accepted, and may become a hard error \ - in the future" - .to_owned() - } else if let FutureIncompatibilityReason::EditionError(edition) = - future_incompatible.reason - { - let current_edition = sess.edition(); - format!( - "this is accepted in the current edition (Rust {}) but is a hard error in Rust {}!", - current_edition, edition - ) - } else if let FutureIncompatibilityReason::EditionSemanticsChange(edition) = - future_incompatible.reason - { - format!("this changes meaning in Rust {}", edition) - } else { - "this was previously accepted by the compiler but is being phased out; \ - it will become a hard error in a future release!" - .to_owned() + let explanation = match future_incompatible.reason { + FutureIncompatibilityReason::FutureReleaseError + | FutureIncompatibilityReason::FutureReleaseErrorReportNow => { + "this was previously accepted by the compiler but is being phased out; \ + it will become a hard error in a future release!" + .to_owned() + } + FutureIncompatibilityReason::FutureReleaseSemanticsChange => { + "this will change its meaning in a future release!".to_owned() + } + FutureIncompatibilityReason::EditionError(edition) => { + let current_edition = sess.edition(); + format!( + "this is accepted in the current edition (Rust {}) but is a hard error in Rust {}!", + current_edition, edition + ) + } + FutureIncompatibilityReason::EditionSemanticsChange(edition) => { + format!("this changes meaning in Rust {}", edition) + } + FutureIncompatibilityReason::Custom(reason) => reason.to_owned(), }; + if future_incompatible.explain_reason { err.warn(&explanation); }
diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs new file mode 100644 index 0000000..6dcdc58 --- /dev/null +++ b/compiler/rustc_middle/src/metadata.rs
@@ -0,0 +1,24 @@ +use crate::ty; + +use rustc_hir::def::Res; +use rustc_macros::HashStable; +use rustc_span::symbol::Ident; +use rustc_span::Span; + +/// This structure is supposed to keep enough data to re-create `NameBinding`s for other crates +/// during name resolution. Right now the bindings are not recreated entirely precisely so we may +/// need to add more data in the future to correctly support macros 2.0, for example. +/// Module child can be either a proper item or a reexport (including private imports). +/// In case of reexport all the fields describe the reexport item itself, not what it refers to. +#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] +pub struct ModChild { + /// Name of the item. + pub ident: Ident, + /// Resolution result corresponding to the item. + /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter. + pub res: Res<!>, + /// Visibility of the item. + pub vis: ty::Visibility, + /// Span of the item. + pub span: Span, +}
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index b054d21a..54eb2dc 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -89,6 +89,8 @@ /// the MIR `InstrumentCoverage` pass and not added to the coverage map /// during codegen. const NO_COVERAGE = 1 << 15; + /// `#[used(linker)]`: indicates that LLVM nor the linker can eliminate this function. + const USED_LINKER = 1 << 16; } }
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index f33bd34..ff993ac 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -28,7 +28,7 @@ } /// Holds a map of accessibility levels for reachable HIR nodes. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AccessLevels<Id = LocalDefId> { pub map: FxHashMap<Id, AccessLevel>, }
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 39ca41c..75dd223 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs
@@ -308,7 +308,7 @@ /// The reason is that semantically, until the `box` expression returns, /// the values are still owned by their containing expressions. So /// we'll see that `&x`. - pub yield_in_scope: FxHashMap<Scope, YieldData>, + pub yield_in_scope: FxHashMap<Scope, Vec<YieldData>>, /// The number of visit_expr and visit_pat calls done in the body. /// Used to sanity check visit_expr/visit_pat call count when @@ -423,8 +423,8 @@ /// Checks whether the given scope contains a `yield`. If so, /// returns `Some(YieldData)`. If not, returns `None`. - pub fn yield_in_scope(&self, scope: Scope) -> Option<YieldData> { - self.yield_in_scope.get(&scope).cloned() + pub fn yield_in_scope(&self, scope: Scope) -> Option<&Vec<YieldData>> { + self.yield_in_scope.get(&scope) } /// Gives the number of expressions visited in a body.
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 175d31d..fedf456 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -29,7 +29,7 @@ } /// An entry in the `depr_map`. -#[derive(Clone, HashStable, Debug)] +#[derive(Copy, Clone, HashStable, Debug)] pub struct DeprecationEntry { /// The metadata of the attribute associated with this entry. pub attr: Deprecation, @@ -198,7 +198,7 @@ } else { let since = since.as_ref().map(Symbol::as_str); - if since.as_deref() == Some("TBD") { + if since == Some("TBD") { format!("use of {} `{}` that will be deprecated in a future Rust version", kind, path) } else { format!( @@ -348,7 +348,7 @@ // Deprecated attributes apply in-crate and cross-crate. if let Some(id) = id { if let Some(depr_entry) = self.lookup_deprecation_entry(def_id) { - let parent_def_id = self.hir().local_def_id(self.hir().get_parent_item(id)); + let parent_def_id = self.hir().get_parent_item(id); let skip = self .lookup_deprecation_entry(parent_def_id.to_def_id()) .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
diff --git a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs index 5f02897..e2f3d6e 100644 --- a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs +++ b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
@@ -45,8 +45,9 @@ impl<D: serialize::Decoder> serialize::Decodable<D> for GraphIsCyclicCache { #[inline] - fn decode(d: &mut D) -> Result<Self, D::Error> { - serialize::Decodable::decode(d).map(|_v: ()| Self::new()) + fn decode(d: &mut D) -> Self { + let () = serialize::Decodable::decode(d); + Self::new() } }
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index b762a10..66f2c6e 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -273,20 +273,20 @@ impl<'s> AllocDecodingSession<'s> { /// Decodes an `AllocId` in a thread-safe way. - pub fn decode_alloc_id<'tcx, D>(&self, decoder: &mut D) -> Result<AllocId, D::Error> + pub fn decode_alloc_id<'tcx, D>(&self, decoder: &mut D) -> AllocId where D: TyDecoder<'tcx>, { // Read the index of the allocation. - let idx = usize::try_from(decoder.read_u32()?).unwrap(); + let idx = usize::try_from(decoder.read_u32()).unwrap(); let pos = usize::try_from(self.state.data_offsets[idx]).unwrap(); // Decode the `AllocDiscriminant` now so that we know if we have to reserve an // `AllocId`. let (alloc_kind, pos) = decoder.with_position(pos, |decoder| { - let alloc_kind = AllocDiscriminant::decode(decoder)?; - Ok((alloc_kind, decoder.position())) - })?; + let alloc_kind = AllocDiscriminant::decode(decoder); + (alloc_kind, decoder.position()) + }); // Check the decoding state to see if it's already decoded or if we should // decode it here. @@ -295,7 +295,7 @@ match *entry { State::Done(alloc_id) => { - return Ok(alloc_id); + return alloc_id; } ref mut entry @ State::Empty => { // We are allowed to decode. @@ -329,7 +329,7 @@ State::InProgress(ref mut sessions, alloc_id) => { if sessions.contains(&self.session_id) { // Don't recurse. - return Ok(alloc_id); + return alloc_id; } else { // Start decoding concurrently. sessions.insert(self.session_id); @@ -343,37 +343,37 @@ let alloc_id = decoder.with_position(pos, |decoder| { match alloc_kind { AllocDiscriminant::Alloc => { - let alloc = <&'tcx Allocation as Decodable<_>>::decode(decoder)?; + let alloc = <&'tcx Allocation as Decodable<_>>::decode(decoder); // We already have a reserved `AllocId`. let alloc_id = alloc_id.unwrap(); trace!("decoded alloc {:?}: {:#?}", alloc_id, alloc); decoder.tcx().set_alloc_id_same_memory(alloc_id, alloc); - Ok(alloc_id) + alloc_id } AllocDiscriminant::Fn => { assert!(alloc_id.is_none()); trace!("creating fn alloc ID"); - let instance = ty::Instance::decode(decoder)?; + let instance = ty::Instance::decode(decoder); trace!("decoded fn alloc instance: {:?}", instance); let alloc_id = decoder.tcx().create_fn_alloc(instance); - Ok(alloc_id) + alloc_id } AllocDiscriminant::Static => { assert!(alloc_id.is_none()); trace!("creating extern static alloc ID"); - let did = <DefId as Decodable<D>>::decode(decoder)?; + let did = <DefId as Decodable<D>>::decode(decoder); trace!("decoded static def-ID: {:?}", did); let alloc_id = decoder.tcx().create_static_alloc(did); - Ok(alloc_id) + alloc_id } } - })?; + }); self.state.decoding_state[idx].with_lock(|entry| { *entry = State::Done(alloc_id); }); - Ok(alloc_id) + alloc_id } }
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index f983185..4a57f48 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -38,7 +38,7 @@ ct: ty::Unevaluated<'tcx>, span: Option<Span>, ) -> EvalToConstValueResult<'tcx> { - match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs(self)) { + match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: ct.promoted }; self.const_eval_global_id(param_env, cid, span) @@ -98,4 +98,12 @@ let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?; Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory()) } + + /// Destructure a constant ADT or array into its variant index and its field values. + pub fn destructure_const( + self, + param_env_and_val: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>, + ) -> mir::DestructuredConst<'tcx> { + self.try_destructure_const(param_env_and_val).unwrap() + } }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 52ef380..7e5f801 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -13,6 +13,7 @@ use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex}; +use rustc_errors::ErrorReported; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::{self, GeneratorKind}; @@ -162,7 +163,7 @@ } /// Where a specific `mir::Body` comes from. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable)] pub struct MirSource<'tcx> { pub instance: InstanceDef<'tcx>, @@ -284,11 +285,12 @@ predecessor_cache: PredecessorCache, is_cyclic: GraphIsCyclicCache, + + pub tainted_by_errors: Option<ErrorReported>, } impl<'tcx> Body<'tcx> { pub fn new( - tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>, source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>, @@ -298,6 +300,7 @@ var_debug_info: Vec<VarDebugInfo<'tcx>>, span: Span, generator_kind: Option<GeneratorKind>, + tainted_by_errors: Option<ErrorReported>, ) -> Self { // We need `arg_count` locals, and one for the return place. assert!( @@ -330,8 +333,9 @@ is_polymorphic: false, predecessor_cache: PredecessorCache::new(), is_cyclic: GraphIsCyclicCache::new(), + tainted_by_errors, }; - body.is_polymorphic = body.definitely_has_param_types_or_consts(tcx); + body.is_polymorphic = body.has_param_types_or_consts(); body } @@ -341,7 +345,7 @@ /// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different /// crate. pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self { - Body { + let mut body = Body { phase: MirPhase::Build, source: MirSource::item(DefId::local(CRATE_DEF_INDEX)), basic_blocks, @@ -357,7 +361,10 @@ is_polymorphic: false, predecessor_cache: PredecessorCache::new(), is_cyclic: GraphIsCyclicCache::new(), - } + tainted_by_errors: None, + }; + body.is_polymorphic = body.has_param_types_or_consts(); + body } #[inline] @@ -618,20 +625,20 @@ } impl<'tcx, D: TyDecoder<'tcx>, T: Decodable<D>> Decodable<D> for ClearCrossCrate<T> { #[inline] - fn decode(d: &mut D) -> Result<ClearCrossCrate<T>, D::Error> { + fn decode(d: &mut D) -> ClearCrossCrate<T> { if D::CLEAR_CROSS_CRATE { - return Ok(ClearCrossCrate::Clear); + return ClearCrossCrate::Clear; } - let discr = u8::decode(d)?; + let discr = u8::decode(d); match discr { - TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(ClearCrossCrate::Clear), + TAG_CLEAR_CROSS_CRATE_CLEAR => ClearCrossCrate::Clear, TAG_CLEAR_CROSS_CRATE_SET => { - let val = T::decode(d)?; - Ok(ClearCrossCrate::Set(val)) + let val = T::decode(d); + ClearCrossCrate::Set(val) } - tag => Err(d.error(&format!("Invalid tag for ClearCrossCrate: {:?}", tag))), + tag => panic!("Invalid tag for ClearCrossCrate: {:?}", tag), } } } @@ -893,7 +900,7 @@ /// across a suspension point against the type components of the generator /// which type checking knows are live across a suspension point. We need to /// flag drop flags to avoid triggering this check as they are introduced - /// after typeck. + /// outside of type inference. /// /// This should be sound because the drop flags are fully algebraic, and /// therefore don't affect the auto-trait or outlives properties of the @@ -1254,17 +1261,7 @@ ResumedAfterPanic(GeneratorKind), } -#[derive( - Clone, - Debug, - PartialEq, - PartialOrd, - TyEncodable, - TyDecodable, - Hash, - HashStable, - TypeFoldable -)] +#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)] pub enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, @@ -1565,10 +1562,6 @@ /// End the current live range for the storage of the local. StorageDead(Local), - /// Executes a piece of inline Assembly. Stored in a Box to keep the size - /// of `StatementKind` low. - LlvmInlineAsm(Box<LlvmInlineAsm<'tcx>>), - /// Retag references in the given place, ensuring they got fresh tags. This is /// part of the Stacked Borrows model. These statements are currently only interpreted /// by miri and only generated when "-Z mir-emit-retag" is passed. @@ -1590,7 +1583,7 @@ /// - `Bivariant` -- no effect AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance), - /// Marks the start of a "coverage region", injected with '-Zinstrument-coverage'. A + /// Marks the start of a "coverage region", injected with '-Cinstrument-coverage'. A /// `Coverage` statement carries metadata about the coverage region, used to inject a coverage /// map into the binary. If `Coverage::kind` is a `Counter`, the statement also generates /// executable code, to increment a counter variable at runtime, each time the code region is @@ -1655,7 +1648,7 @@ ForMatchedPlace(Option<DefId>), /// A fake read of the RefWithinGuard version of a bind-by-value variable - /// in a match guard to ensure that it's value hasn't change by the time + /// in a match guard to ensure that its value hasn't change by the time /// we create the OutsideGuard version. ForGuardBinding, @@ -1688,13 +1681,6 @@ ForIndex, } -#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)] -pub struct LlvmInlineAsm<'tcx> { - pub asm: hir::LlvmInlineAsmInner, - pub outputs: Box<[Place<'tcx>]>, - pub inputs: Box<[(Span, Operand<'tcx>)]>, -} - impl Debug for Statement<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { use self::StatementKind::*; @@ -1719,9 +1705,6 @@ SetDiscriminant { ref place, variant_index } => { write!(fmt, "discriminant({:?}) = {:?}", place, variant_index) } - LlvmInlineAsm(ref asm) => { - write!(fmt, "llvm_asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs) - } AscribeUserType(box (ref place, ref c_ty), ref variance) => { write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty) } @@ -1760,7 +1743,7 @@ /// A path to a value; something that can be evaluated without /// changing or disturbing program state. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, HashStable)] pub struct Place<'tcx> { pub local: Local, @@ -2085,7 +2068,7 @@ /// These are values that can appear inside an rvalue. They are intentionally /// limited to prevent rvalues from being nested in one another. -#[derive(Clone, PartialEq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum Operand<'tcx> { /// Copy: The value must be available for use afterwards. /// @@ -2202,7 +2185,7 @@ Use(Operand<'tcx>), /// [x; 32] - Repeat(Operand<'tcx>, &'tcx ty::Const<'tcx>), + Repeat(Operand<'tcx>, ty::Const<'tcx>), /// &x or &mut x Ref(Region<'tcx>, BorrowKind, Place<'tcx>), @@ -2287,11 +2270,13 @@ Mul, /// The `/` operator (division) /// - /// Division by zero is UB. + /// Division by zero is UB, because the compiler should have inserted checks + /// prior to this. Div, /// The `%` operator (modulus) /// - /// Using zero as the modulus (second operand) is UB. + /// Using zero as the modulus (second operand) is UB, because the compiler + /// should have inserted checks prior to this. Rem, /// The `^` operator (bitwise xor) BitXor, @@ -2352,7 +2337,7 @@ match *self { Use(ref place) => write!(fmt, "{:?}", place), - Repeat(ref a, ref b) => { + Repeat(ref a, b) => { write!(fmt, "[{:?}; ", a)?; pretty_print_const(b, fmt, false)?; write!(fmt, "]") @@ -2439,7 +2424,7 @@ CtorKind::Fictive => { let mut struct_fmt = fmt.debug_struct(&name); for (field, place) in iter::zip(&variant_def.fields, places) { - struct_fmt.field(field.ident.as_str(), place); + struct_fmt.field(field.name.as_str(), place); } struct_fmt.finish() } @@ -2449,7 +2434,6 @@ AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| { if let Some(def_id) = def_id.as_local() { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let name = if tcx.sess.opts.debugging_opts.span_free_formats { let substs = tcx.lift(substs).unwrap(); format!( @@ -2457,7 +2441,7 @@ tcx.def_path_str_with_substs(def_id.to_def_id(), substs), ) } else { - let span = tcx.hir().span(hir_id); + let span = tcx.def_span(def_id); format!( "[closure@{}]", tcx.sess.source_map().span_to_diagnostic_string(span) @@ -2481,8 +2465,7 @@ AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| { if let Some(def_id) = def_id.as_local() { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let name = format!("[generator@{:?}]", tcx.hir().span(hir_id)); + let name = format!("[generator@{:?}]", tcx.def_span(def_id)); let mut struct_fmt = fmt.debug_struct(&name); // FIXME(project-rfc-2229#48): This should be a list of capture names/places @@ -2515,7 +2498,7 @@ /// this does not necessarily mean that they are `==` in Rust. In /// particular, one must be wary of `NaN`! -#[derive(Clone, Copy, PartialEq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] pub struct Constant<'tcx> { pub span: Span, @@ -2529,11 +2512,11 @@ pub literal: ConstantKind<'tcx>, } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable, Debug)] #[derive(Lift)] pub enum ConstantKind<'tcx> { /// This constant came from the type system - Ty(&'tcx ty::Const<'tcx>), + Ty(ty::Const<'tcx>), /// This constant cannot go back into the type system, as it represents /// something the type system cannot handle (e.g. pointers). Val(interpret::ConstValue<'tcx>, Ty<'tcx>), @@ -2541,7 +2524,7 @@ impl<'tcx> Constant<'tcx> { pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> { - match self.literal.const_for_ty()?.val.try_to_scalar() { + match self.literal.try_to_scalar() { Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) { GlobalAlloc::Static(def_id) => { assert!(!tcx.is_thread_local_static(def_id)); @@ -2558,33 +2541,33 @@ } } -impl<'tcx> From<&'tcx ty::Const<'tcx>> for ConstantKind<'tcx> { +impl<'tcx> From<ty::Const<'tcx>> for ConstantKind<'tcx> { #[inline] - fn from(ct: &'tcx ty::Const<'tcx>) -> Self { + fn from(ct: ty::Const<'tcx>) -> Self { Self::Ty(ct) } } impl<'tcx> ConstantKind<'tcx> { /// Returns `None` if the constant is not trivially safe for use in the type system. - pub fn const_for_ty(&self) -> Option<&'tcx ty::Const<'tcx>> { + pub fn const_for_ty(&self) -> Option<ty::Const<'tcx>> { match self { - ConstantKind::Ty(c) => Some(c), + ConstantKind::Ty(c) => Some(*c), ConstantKind::Val(..) => None, } } pub fn ty(&self) -> Ty<'tcx> { match self { - ConstantKind::Ty(c) => c.ty, - ConstantKind::Val(_, ty) => ty, + ConstantKind::Ty(c) => c.ty(), + ConstantKind::Val(_, ty) => *ty, } } #[inline] pub fn try_to_value(self) -> Option<interpret::ConstValue<'tcx>> { match self { - ConstantKind::Ty(c) => c.val.try_to_value(), + ConstantKind::Ty(c) => c.val().try_to_value(), ConstantKind::Val(val, _) => Some(val), } } @@ -2785,7 +2768,7 @@ field: Field, ) -> Self { self.projs.push(ProjectionElem::Downcast( - Some(adt_def.variants[variant_index].ident.name), + Some(adt_def.variants[variant_index].name), variant_index, )); self.projs.push(ProjectionElem::Field(field, ())); @@ -2848,7 +2831,7 @@ } fn pretty_print_const<'tcx>( - c: &ty::Const<'tcx>, + c: ty::Const<'tcx>, fmt: &mut Formatter<'_>, print_types: bool, ) -> fmt::Result { @@ -2964,7 +2947,7 @@ let mut visited = FxHashSet::default(); while let Some(block) = queue.pop() { - // If we haven't visited this block before, then make sure we visit it's predecessors. + // If we haven't visited this block before, then make sure we visit its predecessors. if visited.insert(block) { queue.extend(predecessors[block].iter().cloned()); } else {
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 1422537..8928083 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -179,15 +179,11 @@ pub fn local_span(&self, tcx: TyCtxt<'tcx>) -> Option<Span> { match *self { - MonoItem::Fn(Instance { def, .. }) => { - def.def_id().as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) - } - MonoItem::Static(def_id) => { - def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) - } - MonoItem::GlobalAsm(item_id) => Some(item_id.hir_id()), + MonoItem::Fn(Instance { def, .. }) => def.def_id().as_local(), + MonoItem::Static(def_id) => def_id.as_local(), + MonoItem::GlobalAsm(item_id) => Some(item_id.def_id), } - .map(|hir_id| tcx.hir().span(hir_id)) + .map(|def_id| tcx.def_span(def_id)) } // Only used by rustc_codegen_cranelift @@ -247,6 +243,9 @@ items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>, size_estimate: Option<usize>, primary: bool, + /// True if this is CGU is used to hold code coverage information for dead code, + /// false otherwise. + is_code_coverage_dead_code_cgu: bool, } /// Specifies the linkage type for a `MonoItem`. @@ -277,7 +276,13 @@ impl<'tcx> CodegenUnit<'tcx> { #[inline] pub fn new(name: Symbol) -> CodegenUnit<'tcx> { - CodegenUnit { name, items: Default::default(), size_estimate: None, primary: false } + CodegenUnit { + name, + items: Default::default(), + size_estimate: None, + primary: false, + is_code_coverage_dead_code_cgu: false, + } } pub fn name(&self) -> Symbol { @@ -304,6 +309,15 @@ &mut self.items } + pub fn is_code_coverage_dead_code_cgu(&self) -> bool { + self.is_code_coverage_dead_code_cgu + } + + /// Marks this CGU as the one used to contain code coverage information for dead code. + pub fn make_code_coverage_dead_code_cgu(&mut self) { + self.is_code_coverage_dead_code_cgu = true; + } + pub fn mangle_name(human_readable_name: &str) -> String { // We generate a 80 bit hash from the name. This should be enough to // avoid collisions and is still reasonably short for filenames. @@ -404,9 +418,11 @@ // The size estimate is not relevant to the hash size_estimate: _, primary: _, + is_code_coverage_dead_code_cgu, } = *self; name.hash_stable(hcx, hasher); + is_code_coverage_dead_code_cgu.hash_stable(hcx, hasher); let mut items: Vec<(Fingerprint, _)> = items .iter()
diff --git a/compiler/rustc_middle/src/mir/predecessors.rs b/compiler/rustc_middle/src/mir/predecessors.rs index fd6bb76..2562baac 100644 --- a/compiler/rustc_middle/src/mir/predecessors.rs +++ b/compiler/rustc_middle/src/mir/predecessors.rs
@@ -57,14 +57,15 @@ impl<S: serialize::Encoder> serialize::Encodable<S> for PredecessorCache { #[inline] fn encode(&self, s: &mut S) -> Result<(), S::Error> { - serialize::Encodable::encode(&(), s) + s.emit_unit() } } impl<D: serialize::Decoder> serialize::Decodable<D> for PredecessorCache { #[inline] - fn decode(d: &mut D) -> Result<Self, D::Error> { - serialize::Decodable::decode(d).map(|_v: ()| Self::new()) + fn decode(d: &mut D) -> Self { + let () = d.read_unit(); + Self::new() } }
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 8cc7053..784babf 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -17,9 +17,8 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::MirSource; use rustc_middle::mir::*; -use rustc_middle::ty::{self, TyCtxt, TyS, TypeFoldable, TypeVisitor}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_target::abi::Size; -use std::ops::ControlFlow; const INDENT: &str = " "; /// Alignment for lining up comments following MIR statements @@ -427,12 +426,12 @@ } } -fn use_verbose<'tcx>(ty: &&TyS<'tcx>, fn_def: bool) -> bool { - match ty.kind() { +fn use_verbose<'tcx>(ty: Ty<'tcx>, fn_def: bool) -> bool { + match *ty.kind() { ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false, // Unit type ty::Tuple(g_args) if g_args.is_empty() => false, - ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(&g_arg.expect_ty(), fn_def)), + ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(g_arg.expect_ty(), fn_def)), ty::Array(ty, _) => use_verbose(ty, fn_def), ty::FnDef(..) => fn_def, _ => true, @@ -443,7 +442,7 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); let Constant { span, user_ty, literal } = constant; - if use_verbose(&literal.ty(), true) { + if use_verbose(literal.ty(), true) { self.push("mir::Constant"); self.push(&format!( "+ span: {}", @@ -462,9 +461,10 @@ } } - fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) { + fn visit_const(&mut self, constant: ty::Const<'tcx>, _: Location) { self.super_const(constant); - let ty::Const { ty, val, .. } = constant; + let ty = constant.ty(); + let val = constant.val(); if use_verbose(ty, false) { self.push("ty::Const"); self.push(&format!("+ ty: {:?}", ty)); @@ -476,8 +476,8 @@ ty::ConstKind::Unevaluated(uv) => format!( "Unevaluated({}, {:?}, {:?})", self.tcx.def_path_str(uv.def.did), - uv.substs(self.tcx), - uv.promoted + uv.substs, + uv.promoted, ), ty::ConstKind::Value(val) => format!("Value({:?})", val), ty::ConstKind::Error(_) => "Error".to_string(), @@ -668,6 +668,7 @@ fn alloc_ids_from_alloc(alloc: &Allocation) -> impl DoubleEndedIterator<Item = AllocId> + '_ { alloc.relocations().values().map(|id| *id) } + fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ { match val { ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _size)) => { @@ -681,23 +682,29 @@ } } } - struct CollectAllocIds(BTreeSet<AllocId>); - impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds { - fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> { - // `AllocId`s are only inside of `ConstKind::Value` which - // can't be part of the anon const default substs. - None - } - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { - if let ty::ConstKind::Value(val) = c.val { + struct CollectAllocIds(BTreeSet<AllocId>); + + impl<'tcx> Visitor<'tcx> for CollectAllocIds { + fn visit_const(&mut self, c: ty::Const<'tcx>, _loc: Location) { + if let ty::ConstKind::Value(val) = c.val() { self.0.extend(alloc_ids_from_const(val)); } - c.super_visit_with(self) + } + + fn visit_constant(&mut self, c: &Constant<'tcx>, loc: Location) { + match c.literal { + ConstantKind::Ty(c) => self.visit_const(c, loc), + ConstantKind::Val(val, _) => { + self.0.extend(alloc_ids_from_const(val)); + } + } } } + let mut visitor = CollectAllocIds(Default::default()); - body.visit_with(&mut visitor); + visitor.visit_body(body); + // `seen` contains all seen allocations, including the ones we have *not* printed yet. // The protocol is to first `insert` into `seen`, and only if that returns `true` // then push to `todo`.
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index cb3f385..fbd5a2d 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs
@@ -214,6 +214,7 @@ pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>, pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>, pub used_mut_upvars: SmallVec<[Field; 8]>, + pub tainted_by_errors: Option<ErrorReported>, } /// The result of the `mir_const_qualif` query. @@ -227,7 +228,7 @@ pub needs_drop: bool, pub needs_non_const_drop: bool, pub custom_eq: bool, - pub error_occured: Option<ErrorReported>, + pub tainted_by_errors: Option<ErrorReported>, } /// After we borrow check a closure, we are left with various @@ -340,7 +341,7 @@ /// like `Foo { field: my_val }`) Usage, OpaqueType, - ClosureUpvar(hir::HirId), + ClosureUpvar(Field), /// A constraint from a user-written predicate /// with the provided span, written on the item @@ -362,7 +363,7 @@ #[derive(TyEncodable, TyDecodable, HashStable)] pub enum ReturnConstraint { Normal, - ClosureUpvar(hir::HirId), + ClosureUpvar(Field), } /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing @@ -386,11 +387,11 @@ #[derive(Copy, Clone, Debug, HashStable)] pub struct DestructuredConst<'tcx> { pub variant: Option<VariantIdx>, - pub fields: &'tcx [&'tcx ty::Const<'tcx>], + pub fields: &'tcx [ty::Const<'tcx>], } /// Coverage information summarized from a MIR if instrumented for source code coverage (see -/// compiler option `-Zinstrument-coverage`). This information is generated by the +/// compiler option `-Cinstrument-coverage`). This information is generated by the /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query. #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)] pub struct CoverageInfo {
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 507f997..965d30a 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -230,7 +230,7 @@ } /// Format a string showing the start line and column, and end line and column within a file. -pub fn source_range_no_file<'tcx>(tcx: TyCtxt<'tcx>, span: &Span) -> String { +pub fn source_range_no_file<'tcx>(tcx: TyCtxt<'tcx>, span: Span) -> String { let source_map = tcx.sess.source_map(); let start = source_map.lookup_char_pos(span.lo()); let end = source_map.lookup_char_pos(span.hi()); @@ -245,7 +245,6 @@ SetDiscriminant { .. } => "SetDiscriminant", StorageLive(..) => "StorageLive", StorageDead(..) => "StorageDead", - LlvmInlineAsm(..) => "LlvmInlineAsm", Retag(..) => "Retag", AscribeUserType(..) => "AscribeUserType", Coverage(..) => "Coverage", @@ -630,7 +629,7 @@ let mut text = Vec::new(); text.push(format!("{}: {}:", spanview_id, &source_map.span_to_embeddable_string(span))); for statement in statements { - let source_range = source_range_no_file(tcx, &statement.source_info.span); + let source_range = source_range_no_file(tcx, statement.source_info.span); text.push(format!( "\n{}{}: {}: {:?}", TOOLTIP_INDENT, @@ -640,7 +639,7 @@ )); } if let Some(term) = terminator { - let source_range = source_range_no_file(tcx, &term.source_info.span); + let source_range = source_range_no_file(tcx, term.source_info.span); text.push(format!( "\n{}{}: {}: {:?}", TOOLTIP_INDENT, @@ -665,9 +664,7 @@ } fn fn_span<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Span { - let hir_id = - tcx.hir().local_def_id_to_hir_id(def_id.as_local().expect("expected DefId is local")); - let fn_decl_span = tcx.hir().span(hir_id); + let fn_decl_span = tcx.def_span(def_id); if let Some(body_span) = hir_body(tcx, def_id).map(|hir_body| hir_body.value.span) { if fn_decl_span.ctxt() == body_span.ctxt() { fn_decl_span.to(body_span) } else { body_span } } else {
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index dc53dc8..302921c 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -57,7 +57,7 @@ /// `PlaceElem`, where we can just use the `Ty` that is already /// stored inline on field projection elems. pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> { - self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty) + self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, &ty| ty) } /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })` @@ -93,11 +93,11 @@ ProjectionElem::Subslice { from, to, from_end } => { PlaceTy::from_ty(match self.ty.kind() { ty::Slice(..) => self.ty, - ty::Array(inner, _) if !from_end => tcx.mk_array(inner, (to - from) as u64), + ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64), ty::Array(inner, size) if from_end => { let size = size.eval_usize(tcx, param_env); let len = size - (from as u64) - (to as u64); - tcx.mk_array(inner, len) + tcx.mk_array(*inner, len) } _ => bug!("cannot subslice non-array type: `{:?}`", self), })
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 51e4afa..ae94bd1 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -105,7 +105,7 @@ impl<'a> ExactSizeIterator for SwitchTargetsIter<'a> {} -#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, PartialOrd)] +#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] pub enum TerminatorKind<'tcx> { /// Block should have one successor in the graph; we jump there. Goto { target: BasicBlock }, @@ -430,7 +430,7 @@ pub fn as_switch(&self) -> Option<(&Operand<'tcx>, Ty<'tcx>, &SwitchTargets)> { match self { TerminatorKind::SwitchInt { discr, switch_ty, targets } => { - Some((discr, switch_ty, targets)) + Some((discr, *switch_ty, targets)) } _ => None, }
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 8c930fd..480f286 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -4,8 +4,9 @@ /// Preorder traversal of a graph. /// -/// Preorder traversal is when each node is visited before any of its -/// successors +/// Preorder traversal is when each node is visited after at least one of its predecessors. If you +/// are familar with some basic graph theory, then this performs a depth first search and returns +/// nodes in order of discovery time. /// /// ```text /// @@ -82,8 +83,9 @@ /// Postorder traversal of a graph. /// -/// Postorder traversal is when each node is visited after all of its -/// successors, except when the successor is only reachable by a back-edge +/// Postorder traversal is when each node is visited after all of its successors, except when the +/// successor is only reachable by a back-edge. If you are familiar with some basic graph theory, +/// then this performs a depth first search and returns nodes in order of completion time. /// /// /// ```text
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index f301c68..a618800 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -194,13 +194,13 @@ } fn visit_region(&mut self, - region: & $($mutability)? ty::Region<'tcx>, + region: $(& $mutability)? ty::Region<'tcx>, _: Location) { self.super_region(region); } fn visit_const(&mut self, - constant: & $($mutability)? &'tcx ty::Const<'tcx>, + constant: $(& $mutability)? ty::Const<'tcx>, _: Location) { self.super_const(constant); } @@ -242,7 +242,7 @@ ) { let span = body.span; if let Some(gen) = &$($mutability)? body.generator { - if let Some(yield_ty) = &$($mutability)? gen.yield_ty { + if let Some(yield_ty) = $(& $mutability)? gen.yield_ty { self.visit_ty( yield_ty, TyContext::YieldTy(SourceInfo::outermost(span)) @@ -266,7 +266,7 @@ } self.visit_ty( - &$($mutability)? body.return_ty(), + $(& $mutability)? body.return_ty(), TyContext::ReturnTy(SourceInfo::outermost(body.span)) ); @@ -355,7 +355,7 @@ ty::InstanceDef::DropGlue(_def_id, Some(ty)) | ty::InstanceDef::CloneShim(_def_id, ty) => { // FIXME(eddyb) use a better `TyContext` here. - self.visit_ty(ty, TyContext::Location(location)); + self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } } self.visit_substs(callee_substs, location); @@ -408,19 +408,6 @@ location ); } - StatementKind::LlvmInlineAsm(asm) => { - for output in & $($mutability)? asm.outputs[..] { - self.visit_place( - output, - PlaceContext::MutatingUse(MutatingUseContext::LlvmAsmOutput), - location - ); - } - for (span, input) in & $($mutability)? asm.inputs[..] { - self.visit_span(span); - self.visit_operand(input, location); - } - } StatementKind::Retag(kind, place) => { self.visit_retag(kind, place, location); } @@ -500,7 +487,7 @@ targets: _ } => { self.visit_operand(discr, location); - self.visit_ty(switch_ty, TyContext::Location(location)); + self.visit_ty($(& $mutability)? *switch_ty, TyContext::Location(location)); } TerminatorKind::Drop { @@ -654,7 +641,7 @@ Rvalue::ThreadLocalRef(_) => {} Rvalue::Ref(r, bk, path) => { - self.visit_region(r, location); + self.visit_region($(& $mutability)? *r, location); let ctx = match bk { BorrowKind::Shared => PlaceContext::NonMutatingUse( NonMutatingUseContext::SharedBorrow @@ -693,7 +680,7 @@ Rvalue::Cast(_cast_kind, operand, ty) => { self.visit_operand(operand, location); - self.visit_ty(ty, TyContext::Location(location)); + self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } Rvalue::BinaryOp(_bin_op, box(lhs, rhs)) @@ -715,14 +702,14 @@ } Rvalue::NullaryOp(_op, ty) => { - self.visit_ty(ty, TyContext::Location(location)); + self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } Rvalue::Aggregate(kind, operands) => { let kind = &$($mutability)? **kind; match kind { AggregateKind::Array(ty) => { - self.visit_ty(ty, TyContext::Location(location)); + self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } AggregateKind::Tuple => { } @@ -757,7 +744,7 @@ Rvalue::ShallowInitBox(operand, ty) => { self.visit_operand(operand, location); - self.visit_ty(ty, TyContext::Location(location)); + self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)); } } } @@ -828,7 +815,7 @@ is_block_tail: _, } = local_decl; - self.visit_ty(ty, TyContext::LocalDecl { + self.visit_ty($(& $mutability)? *ty, TyContext::LocalDecl { local, source_info: *source_info, }); @@ -877,8 +864,8 @@ self.visit_span(span); drop(user_ty); // no visit method for this match literal { - ConstantKind::Ty(ct) => self.visit_const(ct, location), - ConstantKind::Val(_, t) => self.visit_ty(t, TyContext::Location(location)), + ConstantKind::Ty(ct) => self.visit_const($(& $mutability)? *ct, location), + ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), } } @@ -907,16 +894,16 @@ ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>, ) { self.visit_span(& $($mutability)? ty.span); - self.visit_ty(& $($mutability)? ty.inferred_ty, TyContext::UserTy(ty.span)); + self.visit_ty($(& $mutability)? ty.inferred_ty, TyContext::UserTy(ty.span)); } fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) { } - fn super_region(&mut self, _region: & $($mutability)? ty::Region<'tcx>) { + fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) { } - fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::Const<'tcx>) { + fn super_const(&mut self, _const: $(& $mutability)? ty::Const<'tcx>) { } fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) { @@ -1178,10 +1165,6 @@ pub enum MutatingUseContext { /// Appears as LHS of an assignment. Store, - /// Can often be treated as a `Store`, but needs to be separate because - /// ASM is allowed to read outputs as well, so a `Store`-`LlvmAsmOutput` sequence - /// cannot be simplified the way a `Store`-`Store` can be. - LlvmAsmOutput, /// Output operand of an inline assembly block. AsmOutput, /// Destination of a call. @@ -1271,7 +1254,6 @@ PlaceContext::MutatingUse( MutatingUseContext::Store | MutatingUseContext::Call - | MutatingUseContext::LlvmAsmOutput | MutatingUseContext::AsmOutput, ) )
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b3db2e6..43cfe6f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs
@@ -56,6 +56,14 @@ desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) } } + /// Gives access to the HIR ID for the given `LocalDefId` owner `key`. + /// + /// This can be conveniently accessed by methods on `tcx.hir()`. + /// Avoid calling this query directly. + query local_def_id_to_hir_id(key: LocalDefId) -> hir::HirId { + desc { |tcx| "HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) } + } + /// Gives access to the HIR node's parent for the HIR owner `key`. /// /// This can be conveniently accessed by methods on `tcx.hir()`. @@ -68,7 +76,7 @@ /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> { + query hir_owner_nodes(key: LocalDefId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> { desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) } } @@ -105,15 +113,11 @@ /// Given the def_id of a const-generic parameter, computes the associated default const /// parameter. e.g. `fn example<const N: usize=3>` called on `N` would return `3`. - query const_param_default(param: DefId) -> &'tcx ty::Const<'tcx> { + query const_param_default(param: DefId) -> ty::Const<'tcx> { desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) } separate_provide_extern } - query default_anon_const_substs(key: DefId) -> SubstsRef<'tcx> { - desc { |tcx| "computing the default generic arguments for `{}`", tcx.def_path_str(key) } - } - /// Records the type of every item. query type_of(key: DefId) -> Ty<'tcx> { desc { |tcx| @@ -211,7 +215,8 @@ desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } - query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLib>> { + query native_libraries(_: CrateNum) -> Vec<NativeLib> { + storage(ArenaCacheSelector<'tcx>) desc { "looking up the native libraries of a linked crate" } separate_provide_extern } @@ -250,13 +255,14 @@ /// Create a THIR tree for debugging. query thir_tree(key: ty::WithOptConstParam<LocalDefId>) -> String { no_hash + storage(ArenaCacheSelector<'tcx>) desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key.did.to_def_id()) } } /// Set of all the `DefId`s in this crate that have MIR associated with /// them. This includes all the body owners, but also things like struct /// constructors. - query mir_keys(_: ()) -> FxHashSet<LocalDefId> { + query mir_keys(_: ()) -> rustc_data_structures::fx::FxIndexSet<LocalDefId> { storage(ArenaCacheSelector<'tcx>) desc { "getting a list of all mir_keys" } } @@ -364,6 +370,7 @@ query symbols_for_closure_captures( key: (LocalDefId, DefId) ) -> Vec<rustc_span::Symbol> { + storage(ArenaCacheSelector<'tcx>) desc { |tcx| "symbols for captures of closure `{}` in `{}`", tcx.def_path_str(key.1), @@ -380,22 +387,12 @@ } /// Returns coverage summary info for a function, after executing the `InstrumentCoverage` - /// MIR pass (assuming the -Zinstrument-coverage option is enabled). + /// MIR pass (assuming the -Cinstrument-coverage option is enabled). query coverageinfo(key: ty::InstanceDef<'tcx>) -> mir::CoverageInfo { desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key.def_id()) } storage(ArenaCacheSelector<'tcx>) } - /// Returns the name of the file that contains the function body, if instrumented for coverage. - query covered_file_name(key: DefId) -> Option<Symbol> { - desc { - |tcx| "retrieving the covered file name, if instrumented, for `{}`", - tcx.def_path_str(key) - } - storage(ArenaCacheSelector<'tcx>) - cache_on_disk_if { key.is_local() } - } - /// Returns the `CodeRegions` for a function that has instrumented coverage, in case the /// function was optimized out before codegen, and before being added to the Coverage Map. query covered_code_regions(key: DefId) -> Vec<&'tcx mir::coverage::CodeRegion> { @@ -544,7 +541,7 @@ query adt_dtorck_constraint( key: DefId - ) -> Result<DtorckConstraint<'tcx>, NoSolution> { + ) -> Result<&'tcx DtorckConstraint<'tcx>, NoSolution> { desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) } } @@ -630,6 +627,32 @@ desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) } } + /// Maps from associated items on a trait to the corresponding associated + /// item on the impl specified by `impl_id`. + /// + /// For example, with the following code + /// + /// ``` + /// struct Type {} + /// // DefId + /// trait Trait { // trait_id + /// fn f(); // trait_f + /// fn g() {} // trait_g + /// } + /// + /// impl Trait for Type { // impl_id + /// fn f() {} // impl_f + /// fn g() {} // impl_g + /// } + /// ``` + /// + /// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be + ///`{ trait_f: impl_f, trait_g: impl_g }` + query impl_item_implementor_ids(impl_id: DefId) -> FxHashMap<DefId, DefId> { + storage(ArenaCacheSelector<'tcx>) + desc { |tcx| "comparing impl items against trait for {}", tcx.def_path_str(impl_id) } + } + /// Given an `impl_id`, return the trait it implements. /// Return `None` if this is an inherent impl. query impl_trait_ref(impl_id: DefId) -> Option<ty::TraitRef<'tcx>> { @@ -738,6 +761,22 @@ desc { |tcx| "checking liveness of variables in {}", describe_as_module(key, tcx) } } + /// Return the live symbols in the crate for dead code check. + /// + /// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone) and + /// their respective impl (i.e., part of the derive macro) + query live_symbols_and_ignored_derived_traits(_: ()) -> ( + FxHashSet<LocalDefId>, + FxHashMap<LocalDefId, Vec<(DefId, DefId)>> + ) { + storage(ArenaCacheSelector<'tcx>) + desc { "find live symbols in crate" } + } + + query check_mod_deathness(key: LocalDefId) -> () { + desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } + } + query check_mod_impl_wf(key: LocalDefId) -> () { desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) } } @@ -772,24 +811,11 @@ desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) } cache_on_disk_if { true } load_cached(tcx, id) { - #[cfg(bootstrap)] - { - match match tcx.on_disk_cache().as_ref() { - Some(c) => c.try_load_query_result(*tcx, id), - None => None, - } { - Some(x) => Some(&*tcx.arena.alloc(x)), - None => None, - } - } - #[cfg(not(bootstrap))] - { - let typeck_results: Option<ty::TypeckResults<'tcx>> = tcx - .on_disk_cache().as_ref() - .and_then(|c| c.try_load_query_result(*tcx, id)); + let typeck_results: Option<ty::TypeckResults<'tcx>> = tcx + .on_disk_cache().as_ref() + .and_then(|c| c.try_load_query_result(*tcx, id)); - typeck_results.map(|x| &*tcx.arena.alloc(x)) - } + typeck_results.map(|x| &*tcx.arena.alloc(x)) } } @@ -898,10 +924,12 @@ } /// Destructure a constant ADT or array into its variant index and its - /// field values. - query destructure_const( - key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>> - ) -> mir::DestructuredConst<'tcx> { + /// field values or return `None` if constant is invalid. + /// + /// Use infallible `TyCtxt::destructure_const` when you know that constant is valid. + query try_destructure_const( + key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>> + ) -> Option<mir::DestructuredConst<'tcx>> { desc { "destructure constant" } remap_env_constness } @@ -909,8 +937,8 @@ /// Dereference a constant reference or raw pointer and turn the result into a constant /// again. query deref_const( - key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>> - ) -> &'tcx ty::Const<'tcx> { + key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>> + ) -> ty::Const<'tcx> { desc { "deref constant" } remap_env_constness } @@ -921,7 +949,7 @@ query lit_to_const( key: LitToConstInput<'tcx> - ) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> { + ) -> Result<ty::Const<'tcx>, LitToConstError> { desc { "converting literal to const" } } @@ -1019,6 +1047,7 @@ /// Gets the rendered value of the specified constant or associated constant. /// Used by rustdoc. query rendered_const(def_id: DefId) -> String { + storage(ArenaCacheSelector<'tcx>) desc { |tcx| "rendering constant intializer of `{}`", tcx.def_path_str(def_id) } separate_provide_extern } @@ -1068,7 +1097,7 @@ query codegen_fulfill_obligation( key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) - ) -> Result<ImplSource<'tcx, ()>, ErrorReported> { + ) -> Result<&'tcx ImplSource<'tcx, ()>, ErrorReported> { cache_on_disk_if { true } desc { |tcx| "checking if `{}` fulfills its obligations", @@ -1077,7 +1106,7 @@ } /// Return all `impl` blocks in the current crate. - query all_local_trait_impls(_: ()) -> &'tcx BTreeMap<DefId, Vec<LocalDefId>> { + query all_local_trait_impls(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexMap<DefId, Vec<LocalDefId>> { desc { "local trait impls" } } @@ -1119,33 +1148,33 @@ desc { "computing whether `{}` is `Copy`", env.value } remap_env_constness } - /// Query backing `TyS::is_sized`. + /// Query backing `Ty::is_sized`. query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Sized`", env.value } remap_env_constness } - /// Query backing `TyS::is_freeze`. + /// Query backing `Ty::is_freeze`. query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is freeze", env.value } remap_env_constness } - /// Query backing `TyS::is_unpin`. + /// Query backing `Ty::is_unpin`. query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Unpin`", env.value } remap_env_constness } - /// Query backing `TyS::needs_drop`. + /// Query backing `Ty::needs_drop`. query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } remap_env_constness } - /// Query backing `TyS::has_significant_drop_raw`. + /// Query backing `Ty::has_significant_drop_raw`. query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` has a significant drop", env.value } remap_env_constness } - /// Query backing `TyS::is_structural_eq_shallow`. + /// Query backing `Ty::is_structural_eq_shallow`. /// /// This is only correct for ADTs. Call `is_structural_eq_shallow` to handle all types /// correctly. @@ -1214,6 +1243,7 @@ } query dependency_formats(_: ()) -> Lrc<crate::middle::dependency_format::Dependencies> { + storage(ArenaCacheSelector<'tcx>) desc { "get the linkage format of all dependencies" } } @@ -1274,8 +1304,8 @@ desc { "traits in scope at a block" } } - query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> { - desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id.to_def_id()) } + query module_reexports(def_id: LocalDefId) -> Option<&'tcx [ModChild]> { + desc { |tcx| "looking up reexports of module `{}`", tcx.def_path_str(def_id.to_def_id()) } } query impl_defaultness(def_id: DefId) -> hir::Defaultness { @@ -1346,13 +1376,15 @@ /// You likely want to call `Instance::upstream_monomorphization()` /// instead of invoking this query directly. query upstream_monomorphizations_for(def_id: DefId) - -> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>> { - desc { |tcx| - "collecting available upstream monomorphizations for `{}`", - tcx.def_path_str(def_id), - } - separate_provide_extern + -> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>> + { + storage(ArenaCacheSelector<'tcx>) + desc { |tcx| + "collecting available upstream monomorphizations for `{}`", + tcx.def_path_str(def_id), } + separate_provide_extern + } /// Returns the upstream crate that exports drop-glue for the given /// type (`substs` is expected to be a single-item list containing the @@ -1373,7 +1405,8 @@ desc { "available upstream drop-glue for `{:?}`", substs } } - query foreign_modules(_: CrateNum) -> Lrc<FxHashMap<DefId, ForeignModule>> { + query foreign_modules(_: CrateNum) -> FxHashMap<DefId, ForeignModule> { + storage(ArenaCacheSelector<'tcx>) desc { "looking up the foreign modules of a linked crate" } separate_provide_extern } @@ -1399,11 +1432,13 @@ separate_provide_extern } query extra_filename(_: CrateNum) -> String { + storage(ArenaCacheSelector<'tcx>) eval_always desc { "looking up the extra filename for a crate" } separate_provide_extern } query crate_extern_paths(_: CrateNum) -> Vec<PathBuf> { + storage(ArenaCacheSelector<'tcx>) eval_always desc { "looking up the paths for extern crates" } separate_provide_extern @@ -1416,13 +1451,6 @@ separate_provide_extern } - /// Given a crate, look up all trait impls in that crate. - /// Return `(impl_id, self_ty)`. - query all_trait_implementations(_: CrateNum) -> &'tcx [(DefId, Option<SimplifiedType>)] { - desc { "looking up all (?) trait implementations" } - separate_provide_extern - } - query is_dllimport_foreign_item(def_id: DefId) -> bool { desc { |tcx| "is_dllimport_foreign_item({})", tcx.def_path_str(def_id) } } @@ -1462,8 +1490,7 @@ /// for each parameter if a trait object were to be passed for that parameter. /// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`. /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`. - query object_lifetime_defaults_map(_: LocalDefId) - -> Option<Vec<ObjectLifetimeDefault>> { + query object_lifetime_defaults(_: LocalDefId) -> Option<&'tcx [ObjectLifetimeDefault]> { desc { "looking up lifetime defaults for a region on an item" } } query late_bound_vars_map(_: LocalDefId) @@ -1472,6 +1499,7 @@ } query lifetime_scope_map(_: LocalDefId) -> Option<FxHashMap<ItemLocalId, LifetimeScopeForPath>> { + storage(ArenaCacheSelector<'tcx>) desc { "finds the lifetime scope for an HirId of a PathSegment" } } @@ -1485,7 +1513,7 @@ /// check whether the forest is empty. query type_uninhabited_from( key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> - ) -> ty::inhabitedness::DefIdForest { + ) -> ty::inhabitedness::DefIdForest<'tcx> { desc { "computing the inhabitedness of `{:?}`", key } remap_env_constness } @@ -1502,8 +1530,8 @@ desc { "fetching what a crate is named" } separate_provide_extern } - query item_children(def_id: DefId) -> &'tcx [Export] { - desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) } + query module_children(def_id: DefId) -> &'tcx [ModChild] { + desc { |tcx| "collecting child items of module `{}`", tcx.def_path_str(def_id) } separate_provide_extern } query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option<CrateNum> { @@ -1564,6 +1592,7 @@ separate_provide_extern } query used_crate_source(_: CrateNum) -> Lrc<CrateSource> { + storage(ArenaCacheSelector<'tcx>) eval_always desc { "looking at the source for a crate" } separate_provide_extern @@ -1654,7 +1683,11 @@ desc { "optimization level used by backend" } } - query output_filenames(_: ()) -> Arc<OutputFilenames> { + /// Return the filenames where output artefacts shall be stored. + /// + /// This query returns an `&Arc` because codegen backends need the value even after the `TyCtxt` + /// has been destroyed. + query output_filenames(_: ()) -> &'tcx Arc<OutputFilenames> { eval_always desc { "output_filenames" } } @@ -1896,6 +1929,7 @@ /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine, /// because the `ty::Ty`-based wfcheck is always run. query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, traits::WellFormedLoc)) -> Option<traits::ObligationCause<'tcx>> { + storage(ArenaCacheSelector<'tcx>) eval_always no_hash desc { "performing HIR wf-checking for predicate {:?} at item {:?}", key.0, key.1 }
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 8d6fd1e..04bc0c8 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs
@@ -17,6 +17,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::infer::canonical::Canonical; use rustc_middle::middle::region; +use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::{ BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp, UserTypeProjection, }; @@ -213,7 +214,7 @@ #[derive(Debug, HashStable)] pub enum ExprKind<'tcx> { - /// `Scope`s are used to explicitely mark destruction scopes, + /// `Scope`s are used to explicitly mark destruction scopes, /// and to track the `HirId` of the expressions within the scope. Scope { region_scope: region::Scope, @@ -368,12 +369,12 @@ }, /// An inline `const` block, e.g. `const {}`. ConstBlock { - value: &'tcx Const<'tcx>, + value: Const<'tcx>, }, /// An array literal constructed from one repeated element, e.g. `[1; 5]`. Repeat { value: ExprId, - count: &'tcx Const<'tcx>, + count: Const<'tcx>, }, /// An array, e.g. `[a, b, c, d]`. Array { @@ -407,7 +408,7 @@ }, /// A literal. Literal { - literal: &'tcx Const<'tcx>, + literal: Const<'tcx>, user_ty: Option<Canonical<'tcx, UserType<'tcx>>>, /// The `DefId` of the `const` item this literal /// was produced from, if this is not a user-written @@ -419,7 +420,8 @@ /// This is only distinguished from `Literal` so that we can register some /// info for diagnostics. StaticRef { - literal: &'tcx Const<'tcx>, + alloc_id: AllocId, + ty: Ty<'tcx>, def_id: DefId, }, /// Inline assembly, i.e. `asm!()`. @@ -431,12 +433,6 @@ }, /// An expression taking a reference to a thread local. ThreadLocalRef(DefId), - /// Inline LLVM assembly, i.e. `llvm_asm!()`. - LlvmInlineAsm { - asm: &'tcx hir::LlvmInlineAsmInner, - outputs: Box<[ExprId]>, - inputs: Box<[ExprId]>, - }, /// A `yield` expression. Yield { value: ExprId, @@ -507,7 +503,7 @@ out_expr: Option<ExprId>, }, Const { - value: &'tcx Const<'tcx>, + value: Const<'tcx>, span: Span, }, SymFn { @@ -646,7 +642,7 @@ /// * Opaque constants, that must not be matched structurally. So anything that does not derive /// `PartialEq` and `Eq`. Constant { - value: &'tcx ty::Const<'tcx>, + value: ty::Const<'tcx>, }, Range(PatRange<'tcx>), @@ -676,8 +672,8 @@ #[derive(Copy, Clone, Debug, PartialEq, HashStable)] pub struct PatRange<'tcx> { - pub lo: &'tcx ty::Const<'tcx>, - pub hi: &'tcx ty::Const<'tcx>, + pub lo: ty::Const<'tcx>, + pub hi: ty::Const<'tcx>, pub end: RangeEnd, } @@ -726,7 +722,7 @@ }; if let Some(variant) = variant { - write!(f, "{}", variant.ident)?; + write!(f, "{}", variant.name)?; // Only for Adt we can have `S {...}`, // which we handle separately here. @@ -738,7 +734,7 @@ if let PatKind::Wild = *p.pattern.kind { continue; } - let name = variant.fields[p.field.index()].ident; + let name = variant.fields[p.field.index()].name; write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?; printed += 1; }
diff --git a/compiler/rustc_middle/src/thir/abstract_const.rs b/compiler/rustc_middle/src/thir/abstract_const.rs index f80bead..e3d004e 100644 --- a/compiler/rustc_middle/src/thir/abstract_const.rs +++ b/compiler/rustc_middle/src/thir/abstract_const.rs
@@ -22,7 +22,7 @@ /// A node of an `AbstractConst`. #[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] pub enum Node<'tcx> { - Leaf(&'tcx ty::Const<'tcx>), + Leaf(ty::Const<'tcx>), Binop(mir::BinOp, NodeId, NodeId), UnaryOp(mir::UnOp, NodeId), FunctionCall(NodeId, &'tcx [NodeId]),
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 7fc15e0..b3e2cb1 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -26,7 +26,7 @@ walk_pat(self, pat); } - fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {} + fn visit_const(&mut self, _cnst: Const<'tcx>) {} } pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) { @@ -123,7 +123,7 @@ } Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {} Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal), - StaticRef { literal, def_id: _ } => visitor.visit_const(literal), + StaticRef { .. } => {} InlineAsm { ref operands, template: _, options: _, line_spans: _ } => { for op in &**operands { use InlineAsmOperand::*; @@ -145,14 +145,6 @@ } } ThreadLocalRef(_) => {} - LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => { - for &out_expr in &**outputs { - visitor.visit_expr(&visitor.thir()[out_expr]); - } - for &in_expr in &**inputs { - visitor.visit_expr(&visitor.thir()[in_expr]); - } - } Yield { value } => visitor.visit_expr(&visitor.thir()[value]), } } @@ -217,7 +209,7 @@ visitor.visit_pat(&subpattern.pattern); } } - Constant { value } => visitor.visit_const(value), + Constant { value } => visitor.visit_const(*value), Range(range) => { visitor.visit_const(range.lo); visitor.visit_const(range.hi);
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index de5beff..b54418e 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -285,6 +285,12 @@ trait_item_def_id: DefId, }, + /// Checking that the bounds of a trait's associated type hold for a given impl + CheckAssociatedTypeBounds { + impl_item_def_id: DefId, + trait_item_def_id: DefId, + }, + /// Checking that this expression can be assigned where it needs to be // FIXME(eddyb) #11161 is the original Expr required? ExprAssignable, @@ -402,7 +408,7 @@ // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ObligationCauseCode<'_>, 40); +static_assert_size!(ObligationCauseCode<'_>, 48); #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum StatementAsExpression { @@ -440,11 +446,11 @@ #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] pub struct DerivedObligationCause<'tcx> { - /// The trait reference of the parent obligation that led to the + /// The trait predicate of the parent obligation that led to the /// current obligation. Note that only trait obligations lead to - /// derived obligations, so we just store the trait reference here + /// derived obligations, so we just store the trait predicate here /// directly. - pub parent_trait_ref: ty::PolyTraitRef<'tcx>, + pub parent_trait_pred: ty::PolyTraitPredicate<'tcx>, /// The parent trait had this cause. pub parent_code: Lrc<ObligationCauseCode<'tcx>>, @@ -566,7 +572,7 @@ TraitAlias(ImplSourceTraitAliasData<'tcx, N>), /// ImplSource for a `const Drop` implementation. - ConstDrop(ImplSourceConstDropData), + ConstDrop(ImplSourceConstDropData<N>), } impl<'tcx, N> ImplSource<'tcx, N> { @@ -581,10 +587,10 @@ ImplSource::Object(d) => d.nested, ImplSource::FnPointer(d) => d.nested, ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) - | ImplSource::Pointee(ImplSourcePointeeData) - | ImplSource::ConstDrop(ImplSourceConstDropData) => Vec::new(), + | ImplSource::Pointee(ImplSourcePointeeData) => Vec::new(), ImplSource::TraitAlias(d) => d.nested, ImplSource::TraitUpcasting(d) => d.nested, + ImplSource::ConstDrop(i) => i.nested, } } @@ -599,10 +605,10 @@ ImplSource::Object(d) => &d.nested, ImplSource::FnPointer(d) => &d.nested, ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) - | ImplSource::Pointee(ImplSourcePointeeData) - | ImplSource::ConstDrop(ImplSourceConstDropData) => &[], + | ImplSource::Pointee(ImplSourcePointeeData) => &[], ImplSource::TraitAlias(d) => &d.nested, ImplSource::TraitUpcasting(d) => &d.nested, + ImplSource::ConstDrop(i) => &i.nested, } } @@ -661,9 +667,9 @@ nested: d.nested.into_iter().map(f).collect(), }) } - ImplSource::ConstDrop(ImplSourceConstDropData) => { - ImplSource::ConstDrop(ImplSourceConstDropData) - } + ImplSource::ConstDrop(i) => ImplSource::ConstDrop(ImplSourceConstDropData { + nested: i.nested.into_iter().map(f).collect(), + }), } } } @@ -755,8 +761,10 @@ #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] pub struct ImplSourcePointeeData; -#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] -pub struct ImplSourceConstDropData; +#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] +pub struct ImplSourceConstDropData<N> { + pub nested: Vec<N>, +} #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)] pub struct ImplSourceTraitAliasData<'tcx, N> {
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index cb35a40..07cfe83 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs
@@ -11,7 +11,6 @@ use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; use rustc_query_system::ich::StableHashingContext; use rustc_span::source_map::Span; @@ -97,7 +96,7 @@ pub type CanonicalTypeOpNormalizeGoal<'tcx, T> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>; -#[derive(Clone, Debug, HashStable)] +#[derive(Copy, Clone, Debug, HashStable)] pub struct NoSolution; pub type Fallible<T> = Result<T, NoSolution>; @@ -191,12 +190,12 @@ pub unsize: bool, } -#[derive(Clone, Debug, HashStable)] +#[derive(Copy, Clone, Debug, HashStable)] pub struct MethodAutoderefStepsResult<'tcx> { /// The valid autoderef steps that could be find. - pub steps: Lrc<Vec<CandidateStep<'tcx>>>, + pub steps: &'tcx [CandidateStep<'tcx>], /// If Some(T), a type autoderef reported an error on. - pub opt_bad_ty: Option<Lrc<MethodAutoderefBadTy<'tcx>>>, + pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>, /// If `true`, `steps` has been truncated due to reaching the /// recursion limit. pub reached_recursion_limit: bool,
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 71ee00c..e18f04d 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs
@@ -146,8 +146,8 @@ BuiltinUnsizeCandidate, - /// Implementation of `const Drop`. - ConstDropCandidate, + /// Implementation of `const Drop`, optionally from a custom `impl const Drop`. + ConstDropCandidate(Option<DefId>), } /// The result of trait evaluation. The order is important
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index 3e9cd6b..03a6daa 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorReported; use rustc_hir::def_id::{DefId, DefIdMap}; -use rustc_span::symbol::Ident; +use rustc_span::symbol::sym; /// A per-trait graph of impls in specialization order. At the moment, this /// graph forms a tree rooted with the trait itself, with all other nodes @@ -46,6 +46,41 @@ } } +/// What kind of overlap check are we doing -- this exists just for testing and feature-gating +/// purposes. +#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable, Debug, TyEncodable, TyDecodable)] +pub enum OverlapMode { + /// The 1.0 rules (either types fail to unify, or where clauses are not implemented for crate-local types) + Stable, + /// Feature-gated test: Stable, *or* there is an explicit negative impl that rules out one of the where-clauses. + WithNegative, + /// Just check for negative impls, not for "where clause not implemented": used for testing. + Strict, +} + +impl OverlapMode { + pub fn get<'tcx>(tcx: TyCtxt<'tcx>, trait_id: DefId) -> OverlapMode { + let with_negative_coherence = tcx.features().with_negative_coherence; + let strict_coherence = tcx.has_attr(trait_id, sym::rustc_strict_coherence); + + if with_negative_coherence { + if strict_coherence { OverlapMode::Strict } else { OverlapMode::WithNegative } + } else if strict_coherence { + bug!("To use strict_coherence you need to set with_negative_coherence feature flag"); + } else { + OverlapMode::Stable + } + } + + pub fn use_negative_impl(&self) -> bool { + *self == OverlapMode::Strict || *self == OverlapMode::WithNegative + } + + pub fn use_implicit_negative(&self) -> bool { + *self == OverlapMode::Stable || *self == OverlapMode::WithNegative + } +} + /// Children of a given impl, grouped into blanket/non-blanket varieties as is /// done in `TraitDef`. #[derive(Default, TyEncodable, TyDecodable, Debug, HashStable)] @@ -75,34 +110,28 @@ Trait(DefId), } -impl<'tcx> Node { +impl Node { pub fn is_from_trait(&self) -> bool { matches!(self, Node::Trait(..)) } - /// Iterate over the items defined directly by the given (impl or trait) node. - pub fn items(&self, tcx: TyCtxt<'tcx>) -> impl 'tcx + Iterator<Item = &'tcx ty::AssocItem> { - tcx.associated_items(self.def_id()).in_definition_order() - } - - /// Finds an associated item defined in this node. + /// Trys to find the associated item that implements `trait_item_def_id` + /// defined in this node. /// /// If this returns `None`, the item can potentially still be found in /// parents of this node. - pub fn item( + pub fn item<'tcx>( &self, tcx: TyCtxt<'tcx>, - trait_item_name: Ident, - trait_item_kind: ty::AssocKind, - trait_def_id: DefId, - ) -> Option<ty::AssocItem> { - tcx.associated_items(self.def_id()) - .filter_by_name_unhygienic(trait_item_name.name) - .find(move |impl_item| { - trait_item_kind == impl_item.kind - && tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id) - }) - .copied() + trait_item_def_id: DefId, + ) -> Option<&'tcx ty::AssocItem> { + match *self { + Node::Trait(_) => Some(tcx.associated_item(trait_item_def_id)), + Node::Impl(impl_def_id) => { + let id = tcx.impl_item_implementor_ids(impl_def_id).get(&trait_item_def_id)?; + Some(tcx.associated_item(*id)) + } + } } pub fn def_id(&self) -> DefId { @@ -181,17 +210,11 @@ impl<'tcx> Ancestors<'tcx> { /// Finds the bottom-most (ie. most specialized) definition of an associated /// item. - pub fn leaf_def( - mut self, - tcx: TyCtxt<'tcx>, - trait_item_name: Ident, - trait_item_kind: ty::AssocKind, - ) -> Option<LeafDef> { - let trait_def_id = self.trait_def_id; + pub fn leaf_def(mut self, tcx: TyCtxt<'tcx>, trait_item_def_id: DefId) -> Option<LeafDef> { let mut finalizing_node = None; self.find_map(|node| { - if let Some(item) = node.item(tcx, trait_item_name, trait_item_kind, trait_def_id) { + if let Some(item) = node.item(tcx, trait_item_def_id) { if finalizing_node.is_none() { let is_specializable = item.defaultness.is_default() || tcx.impl_defaultness(node.def_id()).is_default(); @@ -201,7 +224,7 @@ } } - Some(LeafDef { item, defining_node: node, finalizing_node }) + Some(LeafDef { item: *item, defining_node: node, finalizing_node }) } else { // Item not mentioned. This "finalizes" any defaulted item provided by an ancestor. finalizing_node = Some(node);
diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index aa2f37b..6ce9f5e 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs
@@ -120,6 +120,12 @@ } } +impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDropData<N> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ImplSourceConstDropData(nested={:?})", self.nested) + } +} + /////////////////////////////////////////////////////////////////////////// // Lift implementations @@ -127,5 +133,4 @@ super::IfExpressionCause, super::ImplSourceDiscriminantKindData, super::ImplSourcePointeeData, - super::ImplSourceConstDropData, }
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index e0e3feb..738c48d 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -77,7 +77,7 @@ ) => Ok(a), (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { - Err(TypeError::Sorts(relate::expected_found(self, &a, &b))) + Err(TypeError::Sorts(relate::expected_found(self, a, b))) } (&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(self.tcx().ty_error()), @@ -88,21 +88,21 @@ fn consts( &mut self, - a: &'tcx ty::Const<'tcx>, - b: &'tcx ty::Const<'tcx>, - ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ty::Const<'tcx>> { debug!("{}.consts({:?}, {:?})", self.tag(), a, b); if a == b { return Ok(a); } - match (a.val, b.val) { + match (a.val(), b.val()) { (_, ty::ConstKind::Infer(InferConst::Fresh(_))) => { return Ok(a); } (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => { - return Err(TypeError::ConstMismatch(relate::expected_found(self, &a, &b))); + return Err(TypeError::ConstMismatch(relate::expected_found(self, a, b))); } _ => {}
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 5cde54c..40fbea7 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -4,6 +4,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::HashingControls; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorReported; use rustc_hir as hir; @@ -25,7 +26,7 @@ Destructor, FieldDef, GenericPredicates, ReprOptions, Ty, TyCtxt, VariantDef, VariantDiscr, }; -#[derive(Clone, HashStable, Debug)] +#[derive(Copy, Clone, HashStable, Debug)] pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]); bitflags! { @@ -136,12 +137,13 @@ impl<'a> HashStable<StableHashingContext<'a>> for AdtDef { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { thread_local! { - static CACHE: RefCell<FxHashMap<usize, Fingerprint>> = Default::default(); + static CACHE: RefCell<FxHashMap<(usize, HashingControls), Fingerprint>> = Default::default(); } let hash: Fingerprint = CACHE.with(|cache| { let addr = self as *const AdtDef as usize; - *cache.borrow_mut().entry(addr).or_insert_with(|| { + let hashing_controls = hcx.hashing_controls(); + *cache.borrow_mut().entry((addr, hashing_controls)).or_insert_with(|| { let ty::AdtDef { did, ref variants, ref flags, ref repr } = *self; let mut hasher = StableHasher::new(); @@ -393,7 +395,7 @@ | Res::Def(DefKind::Union, _) | Res::Def(DefKind::TyAlias, _) | Res::Def(DefKind::AssocTy, _) - | Res::SelfTy(..) + | Res::SelfTy { .. } | Res::SelfCtor(..) => self.non_enum_variant(), _ => bug!("unexpected res {:?} in variant_of_res", res), }
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index bf5a3e6..49f84656 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -40,22 +40,30 @@ } } +/// Information about an associated item #[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)] pub struct AssocItem { pub def_id: DefId, - #[stable_hasher(project(name))] - pub ident: Ident, + pub name: Symbol, pub kind: AssocKind, pub vis: Visibility, pub defaultness: hir::Defaultness, pub container: AssocItemContainer, + /// If this is an item in an impl of a trait then this is the `DefId` of + /// the associated item on the trait that this implements. + pub trait_item_def_id: Option<DefId>, + /// Whether this is a method with an explicit self /// as its first parameter, allowing method calls. pub fn_has_self_parameter: bool, } impl AssocItem { + pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { + Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) + } + pub fn signature(&self, tcx: TyCtxt<'_>) -> String { match self.kind { ty::AssocKind::Fn => { @@ -65,9 +73,9 @@ // regions just fine, showing `fn(&MyType)`. tcx.fn_sig(self.def_id).skip_binder().to_string() } - ty::AssocKind::Type => format!("type {};", self.ident), + ty::AssocKind::Type => format!("type {};", self.name), ty::AssocKind::Const => { - format!("const {}: {:?};", self.ident, tcx.type_of(self.def_id)) + format!("const {}: {:?};", self.name, tcx.type_of(self.def_id)) } } } @@ -110,7 +118,7 @@ impl<'tcx> AssocItems<'tcx> { /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order. pub fn new(items_in_def_order: impl IntoIterator<Item = &'tcx ty::AssocItem>) -> Self { - let items = items_in_def_order.into_iter().map(|item| (item.ident.name, item)).collect(); + let items = items_in_def_order.into_iter().map(|item| (item.name, item)).collect(); AssocItems { items } } @@ -134,21 +142,6 @@ self.items.get_by_key(name).copied() } - /// Returns an iterator over all associated items with the given name. - /// - /// Multiple items may have the same name if they are in different `Namespace`s. For example, - /// an associated type can have the same name as a method. Use one of the `find_by_name_and_*` - /// methods below if you know which item you are looking for. - pub fn filter_by_name<'a>( - &'a self, - tcx: TyCtxt<'a>, - ident: Ident, - parent_def_id: DefId, - ) -> impl 'a + Iterator<Item = &'a ty::AssocItem> { - self.filter_by_name_unhygienic(ident.name) - .filter(move |item| tcx.hygienic_eq(ident, item.ident, parent_def_id)) - } - /// Returns the associated item with the given name and `AssocKind`, if one exists. pub fn find_by_name_and_kind( &self, @@ -159,7 +152,19 @@ ) -> Option<&ty::AssocItem> { self.filter_by_name_unhygienic(ident.name) .filter(|item| item.kind == kind) - .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id)) + .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id)) + } + + /// Returns the associated item with the given name and any of `AssocKind`, if one exists. + pub fn find_by_name_and_kinds( + &self, + tcx: TyCtxt<'_>, + ident: Ident, + // Sorted in order of what kinds to look at + kinds: &[AssocKind], + parent_def_id: DefId, + ) -> Option<&ty::AssocItem> { + kinds.iter().find_map(|kind| self.find_by_name_and_kind(tcx, ident, *kind, parent_def_id)) } /// Returns the associated item with the given name in the given `Namespace`, if one exists. @@ -172,6 +177,6 @@ ) -> Option<&ty::AssocItem> { self.filter_by_name_unhygienic(ident.name) .filter(|item| item.kind.namespace() == ns) - .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id)) + .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id)) } }
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 771acc2..8ba6c1f 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -52,35 +52,18 @@ /// Information describing the capture of an upvar. This is computed /// during `typeck`, specifically by `regionck`. #[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] -pub enum UpvarCapture<'tcx> { +pub enum UpvarCapture { /// Upvar is captured by value. This is always true when the /// closure is labeled `move`, but can also be true in other cases /// depending on inference. - /// - /// If the upvar was inferred to be captured by value (e.g. `move` - /// was not used), then the `Span` points to a usage that - /// required it. There may be more than one such usage - /// (e.g. `|| { a; a; }`), in which case we pick an - /// arbitrary one. - ByValue(Option<Span>), + ByValue, /// Upvar is captured by reference. - ByRef(UpvarBorrow<'tcx>), -} - -#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] -pub struct UpvarBorrow<'tcx> { - /// The kind of borrow: by-ref upvars have access to shared - /// immutable borrows, which are not part of the normal language - /// syntax. - pub kind: BorrowKind, - - /// Region of the resulting reference. - pub region: ty::Region<'tcx>, + ByRef(BorrowKind), } pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>; -pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>; +pub type UpvarCaptureMap = FxHashMap<UpvarId, UpvarCapture>; /// Given the closure DefId this map provides a map of root variables to minimum /// set of `CapturedPlace`s that need to be tracked to support all captures of that closure. @@ -133,7 +116,7 @@ } /// Returns the representative scalar type for this closure kind. - /// See `TyS::to_opt_closure_kind` for more details. + /// See `Ty::to_opt_closure_kind` for more details. pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self { ty::ClosureKind::Fn => tcx.types.i8, @@ -150,10 +133,13 @@ pub place: HirPlace<'tcx>, /// `CaptureKind` and expression(s) that resulted in such capture of `place`. - pub info: CaptureInfo<'tcx>, + pub info: CaptureInfo, /// Represents if `place` can be mutated or not. pub mutability: hir::Mutability, + + /// Region of the resulting reference if the upvar is captured by ref. + pub region: Option<ty::Region<'tcx>>, } impl<'tcx> CapturedPlace<'tcx> { @@ -178,7 +164,7 @@ write!( &mut symbol, "__{}", - def.variants[variant].fields[idx as usize].ident.name.as_str(), + def.variants[variant].fields[idx as usize].name.as_str(), ) .unwrap(); } @@ -287,7 +273,7 @@ /// for a particular capture as well as identifying the part of the source code /// that triggered this capture to occur. #[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)] -pub struct CaptureInfo<'tcx> { +pub struct CaptureInfo { /// Expr Id pointing to use that resulted in selecting the current capture kind /// /// Eg: @@ -325,7 +311,7 @@ pub path_expr_id: Option<hir::HirId>, /// Capture mode that was selected - pub capture_kind: UpvarCapture<'tcx>, + pub capture_kind: UpvarCapture, } pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String { @@ -344,7 +330,7 @@ curr_string = format!( "{}.{}", curr_string, - def.variants[variant].fields[idx as usize].ident.name.as_str() + def.variants[variant].fields[idx as usize].name.as_str() ); } ty::Tuple(_) => {
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index db37d98..ecd30ba 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -13,8 +13,9 @@ interpret::{AllocId, Allocation}, }; use crate::thir; +use crate::traits; use crate::ty::subst::SubstsRef; -use crate::ty::{self, List, Ty, TyCtxt}; +use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::Span; @@ -71,7 +72,7 @@ /// `Decodable` can still be implemented in cases where `Decodable` is required /// by a trait bound. pub trait RefDecodable<'tcx, D: TyDecoder<'tcx>> { - fn decode(d: &mut D) -> Result<&'tcx Self, D::Error>; + fn decode(d: &mut D) -> &'tcx Self; } /// Encode the given value or a previously cached shorthand. @@ -137,6 +138,18 @@ } } +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Region<'tcx> { + fn encode(&self, e: &mut E) -> Result<(), E::Error> { + self.kind().encode(e) + } +} + +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Const<'tcx> { + fn encode(&self, e: &mut E) -> Result<(), E::Error> { + self.0.0.encode(e) + } +} + impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AllocId { fn encode(&self, e: &mut E) -> Result<(), E::Error> { e.encode_alloc_id(self) @@ -155,7 +168,7 @@ encodable_via_deref! { &'tcx ty::TypeckResults<'tcx>, - ty::Region<'tcx>, + &'tcx traits::ImplSource<'tcx, ()>, &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, &'tcx mir::BorrowCheckResult<'tcx>, @@ -172,13 +185,9 @@ fn position(&self) -> usize; - fn cached_ty_for_shorthand<F>( - &mut self, - shorthand: usize, - or_insert_with: F, - ) -> Result<Ty<'tcx>, Self::Error> + fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx> where - F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>; + F: FnOnce(&mut Self) -> Ty<'tcx>; fn with_position<F, R>(&mut self, pos: usize, f: F) -> R where @@ -188,35 +197,35 @@ (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0 } - fn decode_alloc_id(&mut self) -> Result<AllocId, Self::Error>; + fn decode_alloc_id(&mut self) -> AllocId; } #[inline] fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable<D>>( decoder: &mut D, -) -> Result<&'tcx T, D::Error> +) -> &'tcx T where D: TyDecoder<'tcx>, { - Ok(decoder.tcx().arena.alloc(Decodable::decode(decoder)?)) + decoder.tcx().arena.alloc(Decodable::decode(decoder)) } #[inline] fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable<D>>( decoder: &mut D, -) -> Result<&'tcx [T], D::Error> +) -> &'tcx [T] where D: TyDecoder<'tcx>, { - Ok(decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable<D>>::decode(decoder)?)) + decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable<D>>::decode(decoder)) } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> { #[allow(rustc::usage_of_ty_tykind)] - fn decode(decoder: &mut D) -> Result<Ty<'tcx>, D::Error> { + fn decode(decoder: &mut D) -> Ty<'tcx> { // Handle shorthands first, if we have a usize > 0x80. if decoder.positioned_at_shorthand() { - let pos = decoder.read_usize()?; + let pos = decoder.read_usize(); assert!(pos >= SHORTHAND_OFFSET); let shorthand = pos - SHORTHAND_OFFSET; @@ -225,87 +234,89 @@ }) } else { let tcx = decoder.tcx(); - Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?)) + tcx.mk_ty(ty::TyKind::decode(decoder)) } } } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<'tcx, ty::PredicateKind<'tcx>> { - fn decode(decoder: &mut D) -> Result<ty::Binder<'tcx, ty::PredicateKind<'tcx>>, D::Error> { - let bound_vars = Decodable::decode(decoder)?; + fn decode(decoder: &mut D) -> ty::Binder<'tcx, ty::PredicateKind<'tcx>> { + let bound_vars = Decodable::decode(decoder); // Handle shorthands first, if we have a usize > 0x80. - Ok(ty::Binder::bind_with_vars( + ty::Binder::bind_with_vars( if decoder.positioned_at_shorthand() { - let pos = decoder.read_usize()?; + let pos = decoder.read_usize(); assert!(pos >= SHORTHAND_OFFSET); let shorthand = pos - SHORTHAND_OFFSET; - decoder.with_position(shorthand, ty::PredicateKind::decode)? + decoder.with_position(shorthand, ty::PredicateKind::decode) } else { - ty::PredicateKind::decode(decoder)? + ty::PredicateKind::decode(decoder) }, bound_vars, - )) + ) } } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> { - fn decode(decoder: &mut D) -> Result<ty::Predicate<'tcx>, D::Error> { - let predicate_kind = Decodable::decode(decoder)?; - let predicate = decoder.tcx().mk_predicate(predicate_kind); - Ok(predicate) + fn decode(decoder: &mut D) -> ty::Predicate<'tcx> { + let predicate_kind = Decodable::decode(decoder); + decoder.tcx().mk_predicate(predicate_kind) } } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for SubstsRef<'tcx> { - fn decode(decoder: &mut D) -> Result<Self, D::Error> { - let len = decoder.read_usize()?; + fn decode(decoder: &mut D) -> Self { + let len = decoder.read_usize(); let tcx = decoder.tcx(); - tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder))) + tcx.mk_substs( + (0..len).map::<ty::subst::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)), + ) } } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> { - fn decode(decoder: &mut D) -> Result<Self, D::Error> { - let local: mir::Local = Decodable::decode(decoder)?; - let len = decoder.read_usize()?; - let projection: &'tcx List<mir::PlaceElem<'tcx>> = - decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?; - Ok(mir::Place { local, projection }) + fn decode(decoder: &mut D) -> Self { + let local: mir::Local = Decodable::decode(decoder); + let len = decoder.read_usize(); + let projection = decoder.tcx().mk_place_elems( + (0..len).map::<mir::PlaceElem<'tcx>, _>(|_| Decodable::decode(decoder)), + ); + mir::Place { local, projection } } } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Region<'tcx> { - fn decode(decoder: &mut D) -> Result<Self, D::Error> { - Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?)) + fn decode(decoder: &mut D) -> Self { + decoder.tcx().mk_region(Decodable::decode(decoder)) } } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarInfos<'tcx> { - fn decode(decoder: &mut D) -> Result<Self, D::Error> { - let len = decoder.read_usize()?; - let interned: Result<Vec<CanonicalVarInfo<'tcx>>, _> = + fn decode(decoder: &mut D) -> Self { + let len = decoder.read_usize(); + let interned: Vec<CanonicalVarInfo<'tcx>> = (0..len).map(|_| Decodable::decode(decoder)).collect(); - Ok(decoder.tcx().intern_canonical_var_infos(interned?.as_slice())) + decoder.tcx().intern_canonical_var_infos(interned.as_slice()) } } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AllocId { - fn decode(decoder: &mut D) -> Result<Self, D::Error> { + fn decode(decoder: &mut D) -> Self { decoder.decode_alloc_id() } } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> { - fn decode(decoder: &mut D) -> Result<Self, D::Error> { - Ok(ty::SymbolName::new(decoder.tcx(), &decoder.read_str()?)) + fn decode(decoder: &mut D) -> Self { + ty::SymbolName::new(decoder.tcx(), &decoder.read_str()) } } macro_rules! impl_decodable_via_ref { ($($t:ty),+) => { $(impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for $t { - fn decode(decoder: &mut D) -> Result<Self, D::Error> { + fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) } })* @@ -313,77 +324,73 @@ } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> { - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - let len = decoder.read_usize()?; - decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder))) + fn decode(decoder: &mut D) -> &'tcx Self { + let len = decoder.read_usize(); + decoder.tcx().mk_type_list((0..len).map::<Ty<'tcx>, _>(|_| Decodable::decode(decoder))) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> { - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - let len = decoder.read_usize()?; - decoder.tcx().mk_poly_existential_predicates((0..len).map(|_| Decodable::decode(decoder))) + fn decode(decoder: &mut D) -> &'tcx Self { + let len = decoder.read_usize(); + decoder.tcx().mk_poly_existential_predicates( + (0..len).map::<ty::Binder<'tcx, _>, _>(|_| Decodable::decode(decoder)), + ) } } -impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::Const<'tcx> { - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?)) +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Const<'tcx> { + fn decode(decoder: &mut D) -> Self { + decoder.tcx().mk_const(Decodable::decode(decoder)) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [ty::ValTree<'tcx>] { - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - Ok(decoder.tcx().arena.alloc_from_iter( - (0..decoder.read_usize()?) - .map(|_| Decodable::decode(decoder)) - .collect::<Result<Vec<_>, _>>()?, - )) + fn decode(decoder: &mut D) -> &'tcx Self { + decoder.tcx().arena.alloc_from_iter( + (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(), + ) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for Allocation { - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?)) + fn decode(decoder: &mut D) -> &'tcx Self { + decoder.tcx().intern_const_alloc(Decodable::decode(decoder)) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>, Span)] { - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - Ok(decoder.tcx().arena.alloc_from_iter( - (0..decoder.read_usize()?) - .map(|_| Decodable::decode(decoder)) - .collect::<Result<Vec<_>, _>>()?, - )) + fn decode(decoder: &mut D) -> &'tcx Self { + decoder.tcx().arena.alloc_from_iter( + (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(), + ) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::Node<'tcx>] { - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - Ok(decoder.tcx().arena.alloc_from_iter( - (0..decoder.read_usize()?) - .map(|_| Decodable::decode(decoder)) - .collect::<Result<Vec<_>, _>>()?, - )) + fn decode(decoder: &mut D) -> &'tcx Self { + decoder.tcx().arena.alloc_from_iter( + (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(), + ) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::NodeId] { - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - Ok(decoder.tcx().arena.alloc_from_iter( - (0..decoder.read_usize()?) - .map(|_| Decodable::decode(decoder)) - .collect::<Result<Vec<_>, _>>()?, - )) + fn decode(decoder: &mut D) -> &'tcx Self { + decoder.tcx().arena.alloc_from_iter( + (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(), + ) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::BoundVariableKind> { - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - let len = decoder.read_usize()?; - decoder.tcx().mk_bound_variable_kinds((0..len).map(|_| Decodable::decode(decoder))) + fn decode(decoder: &mut D) -> &'tcx Self { + let len = decoder.read_usize(); + decoder.tcx().mk_bound_variable_kinds( + (0..len).map::<ty::BoundVariableKind, _>(|_| Decodable::decode(decoder)), + ) } } @@ -391,6 +398,7 @@ &'tcx ty::TypeckResults<'tcx>, &'tcx ty::List<Ty<'tcx>>, &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, + &'tcx traits::ImplSource<'tcx, ()>, &'tcx Allocation, &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, @@ -405,7 +413,7 @@ ($($name:ident -> $ty:ty;)*) => { $( #[inline] - fn $name(&mut self) -> Result<$ty, Self::Error> { + fn $name(&mut self) -> $ty { self.opaque.$name() } )* @@ -418,14 +426,14 @@ [$name:ident: $ty:ty]) => { impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for $ty { #[inline] - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { + fn decode(decoder: &mut D) -> &'tcx Self { decode_arena_allocable(decoder) } } impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [$ty] { #[inline] - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { + fn decode(decoder: &mut D) -> &'tcx Self { decode_arena_allocable_slice(decoder) } } @@ -456,10 +464,8 @@ use super::$DecoderName; impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> { - type Error = String; - $crate::__impl_decoder_methods! { - read_nil -> (); + read_unit -> (); read_u128 -> u128; read_u64 -> u64; @@ -483,13 +489,9 @@ } #[inline] - fn read_raw_bytes_into(&mut self, bytes: &mut [u8]) -> Result<(), Self::Error> { + fn read_raw_bytes_into(&mut self, bytes: &mut [u8]) { self.opaque.read_raw_bytes_into(bytes) } - - fn error(&mut self, err: &str) -> Self::Error { - self.opaque.error(err) - } } } } @@ -505,9 +507,9 @@ } } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<'tcx, $t> { - fn decode(decoder: &mut D) -> Result<Self, D::Error> { - let bound_vars = Decodable::decode(decoder)?; - Ok(ty::Binder::bind_with_vars(Decodable::decode(decoder)?, bound_vars)) + fn decode(decoder: &mut D) -> Self { + let bound_vars = Decodable::decode(decoder); + ty::Binder::bind_with_vars(Decodable::decode(decoder), bound_vars) } } )*
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 27e22cc..a794a8c 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -4,10 +4,12 @@ self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, }; +use rustc_data_structures::intern::Interned; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::HashStable; +use std::fmt; mod int; mod kind; @@ -17,34 +19,53 @@ pub use kind::*; pub use valtree::*; -/// Typed constant value. -#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)] -#[derive(HashStable)] -pub struct Const<'tcx> { - pub ty: Ty<'tcx>, +/// Use this rather than `ConstS`, whenever possible. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] +#[cfg_attr(not(bootstrap), rustc_pass_by_value)] +pub struct Const<'tcx>(pub Interned<'tcx, ConstS<'tcx>>); +impl<'tcx> fmt::Debug for Const<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // This reflects what `Const` looked liked before `Interned` was + // introduced. We print it like this to avoid having to update expected + // output in a lot of tests. + write!(f, "Const {{ ty: {:?}, val: {:?} }}", self.ty(), self.val()) + } +} + +/// Typed constant value. +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)] +pub struct ConstS<'tcx> { + pub ty: Ty<'tcx>, pub val: ConstKind<'tcx>, } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(Const<'_>, 48); +static_assert_size!(ConstS<'_>, 48); impl<'tcx> Const<'tcx> { + pub fn ty(self) -> Ty<'tcx> { + self.0.ty + } + + pub fn val(self) -> ConstKind<'tcx> { + self.0.val + } + /// Literals and const generic parameters are eagerly converted to a constant, everything else /// becomes `Unevaluated`. - pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self { + pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id)) } + #[instrument(skip(tcx), level = "debug")] pub fn from_opt_const_arg_anon_const( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>, - ) -> &'tcx Self { + ) -> Self { debug!("Const::from_anon_const(def={:?})", def); - let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); - - let body_id = match tcx.hir().get(hir_id) { + let body_id = match tcx.hir().get_by_def_id(def.did) { hir::Node::AnonConst(ac) => ac.body, _ => span_bug!( tcx.def_span(def.did.to_def_id()), @@ -53,15 +74,16 @@ }; let expr = &tcx.hir().body(body_id).value; + debug!(?expr); let ty = tcx.type_of(def.def_id_for_type_of()); match Self::try_eval_lit_or_param(tcx, ty, expr) { Some(v) => v, - None => tcx.mk_const(ty::Const { + None => tcx.mk_const(ty::ConstS { val: ty::ConstKind::Unevaluated(ty::Unevaluated { def: def.to_global(), - substs_: None, + substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), promoted: None, }), ty, @@ -69,11 +91,21 @@ } } + #[instrument(skip(tcx), level = "debug")] fn try_eval_lit_or_param( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>, - ) -> Option<&'tcx Self> { + ) -> Option<Self> { + // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments + // currently have to be wrapped in curly brackets, so it's necessary to special-case. + let expr = match &expr.kind { + hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { + block.expr.as_ref().unwrap() + } + _ => expr, + }; + let lit_input = match expr.kind { hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind { @@ -88,22 +120,17 @@ if let Some(lit_input) = lit_input { // If an error occurred, ignore that it's a literal and leave reporting the error up to // mir. - if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) { - return Some(c); - } else { - tcx.sess.delay_span_bug(expr.span, "Const::from_anon_const: couldn't lit_to_const"); + match tcx.at(expr.span).lit_to_const(lit_input) { + Ok(c) => return Some(c), + Err(e) => { + tcx.sess.delay_span_bug( + expr.span, + &format!("Const::from_anon_const: couldn't lit_to_const {:?}", e), + ); + } } } - // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments - // currently have to be wrapped in curly brackets, so it's necessary to special-case. - let expr = match &expr.kind { - hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { - block.expr.as_ref().unwrap() - } - _ => expr, - }; - use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; match expr.kind { ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { @@ -115,7 +142,7 @@ let generics = tcx.generics_of(item_def_id.to_def_id()); let index = generics.param_def_id_to_index[&def_id]; let name = tcx.hir().name(hir_id); - Some(tcx.mk_const(ty::Const { + Some(tcx.mk_const(ty::ConstS { val: ty::ConstKind::Param(ty::ParamConst::new(index, name)), ty, })) @@ -124,7 +151,7 @@ } } - pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self { + pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { debug!("Const::from_inline_const(def_id={:?})", def_id); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); @@ -150,35 +177,35 @@ let substs = InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty }) .substs; - tcx.mk_const(ty::Const { + tcx.mk_const(ty::ConstS { val: ty::ConstKind::Unevaluated(ty::Unevaluated { def: ty::WithOptConstParam::unknown(def_id).to_global(), - substs_: Some(substs), + substs, promoted: None, }), ty, }) } }; - debug_assert!(!ret.has_free_regions(tcx)); + debug_assert!(!ret.has_free_regions()); ret } /// Interns the given value as a constant. #[inline] - pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { - tcx.mk_const(Self { val: ConstKind::Value(val), ty }) + pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self { + tcx.mk_const(ConstS { val: ConstKind::Value(val), ty }) } #[inline] /// Interns the given scalar as a constant. - pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self { + pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> Self { Self::from_value(tcx, ConstValue::Scalar(val), ty) } #[inline] /// Creates a constant with the given integer value and interns it. - pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> &'tcx Self { + pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self { let size = tcx .layout_of(ty) .unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e)) @@ -188,19 +215,19 @@ #[inline] /// Creates an interned zst constant. - pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { + pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { Self::from_scalar(tcx, Scalar::ZST, ty) } #[inline] /// Creates an interned bool constant. - pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> &'tcx Self { + pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self { Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool)) } #[inline] /// Creates an interned usize constant. - pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> &'tcx Self { + pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) } @@ -209,35 +236,35 @@ /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it /// contains const generic parameters or pointers). pub fn try_eval_bits( - &self, + self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, ) -> Option<u128> { - assert_eq!(self.ty, ty); + assert_eq!(self.ty(), ty); let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; // if `ty` does not depend on generic parameters, use an empty param_env - self.val.eval(tcx, param_env).try_to_bits(size) + self.val().eval(tcx, param_env).try_to_bits(size) } #[inline] - pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> { - self.val.eval(tcx, param_env).try_to_bool() + pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> { + self.val().eval(tcx, param_env).try_to_bool() } #[inline] - pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u64> { - self.val.eval(tcx, param_env).try_to_machine_usize(tcx) + pub fn try_eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u64> { + self.val().eval(tcx, param_env).try_to_machine_usize(tcx) } #[inline] /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the /// unevaluated constant. - pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx> { - if let Some(val) = self.val.try_eval(tcx, param_env) { + pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> { + if let Some(val) = self.val().try_eval(tcx, param_env) { match val { - Ok(val) => Const::from_value(tcx, val, self.ty), - Err(ErrorReported) => tcx.const_error(self.ty), + Ok(val) => Const::from_value(tcx, val, self.ty()), + Err(ErrorReported) => tcx.const_error(self.ty()), } } else { self @@ -246,22 +273,21 @@ #[inline] /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. - pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { + pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { self.try_eval_bits(tcx, param_env, ty) .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) } #[inline] /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. - pub fn eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { + pub fn eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { self.try_eval_usize(tcx, param_env) .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } } -pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Const<'tcx> { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let default_def_id = match tcx.hir().get(hir_id) { +pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> { + let default_def_id = match tcx.hir().get_by_def_id(def_id.expect_local()) { hir::Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { ty: _, default: Some(ac) }, ..
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 1f4ebd0..ca1db2f 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -147,8 +147,8 @@ } impl<D: Decoder> Decodable<D> for ScalarInt { - fn decode(d: &mut D) -> Result<ScalarInt, D::Error> { - Ok(ScalarInt { data: d.read_u128()?, size: d.read_u8()? }) + fn decode(d: &mut D) -> ScalarInt { + ScalarInt { data: d.read_u128(), size: d.read_u8() } } } @@ -294,12 +294,22 @@ } } +/// Error returned when a conversion from ScalarInt to char fails. +#[derive(Debug)] +pub struct CharTryFromScalarInt; + impl TryFrom<ScalarInt> for char { - type Error = Size; + type Error = CharTryFromScalarInt; + #[inline] - fn try_from(int: ScalarInt) -> Result<Self, Size> { - int.to_bits(Size::from_bytes(std::mem::size_of::<char>())) - .map(|u| char::from_u32(u.try_into().unwrap()).unwrap()) + fn try_from(int: ScalarInt) -> Result<Self, Self::Error> { + let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::<char>())) else { + return Err(CharTryFromScalarInt); + }; + match char::from_u32(bits.try_into().unwrap()) { + Some(c) => Ok(c), + None => Err(CharTryFromScalarInt), + } } }
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 7188eed..af7c2c5 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,5 +1,4 @@ use std::convert::TryInto; -use std::fmt; use crate::mir::interpret::{AllocId, ConstValue, Scalar}; use crate::mir::Promoted; @@ -13,17 +12,11 @@ use super::ScalarInt; /// An unevaluated, potentially generic, constant. -/// -/// If `substs_` is `None` it means that this anon const -/// still has its default substs. -/// -/// We check for all possible substs in `fn default_anon_const_substs`, -/// so refer to that check for more info. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Hash, HashStable)] pub struct Unevaluated<'tcx, P = Option<Promoted>> { pub def: ty::WithOptConstParam<DefId>, - pub substs_: Option<SubstsRef<'tcx>>, + pub substs: SubstsRef<'tcx>, pub promoted: P, } @@ -31,34 +24,21 @@ #[inline] pub fn shrink(self) -> Unevaluated<'tcx, ()> { debug_assert_eq!(self.promoted, None); - Unevaluated { def: self.def, substs_: self.substs_, promoted: () } + Unevaluated { def: self.def, substs: self.substs, promoted: () } } } impl<'tcx> Unevaluated<'tcx, ()> { #[inline] pub fn expand(self) -> Unevaluated<'tcx> { - Unevaluated { def: self.def, substs_: self.substs_, promoted: None } + Unevaluated { def: self.def, substs: self.substs, promoted: None } } } impl<'tcx, P: Default> Unevaluated<'tcx, P> { #[inline] pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> { - Unevaluated { def, substs_: Some(substs), promoted: Default::default() } - } -} - -impl<'tcx, P: Default + PartialEq + fmt::Debug> Unevaluated<'tcx, P> { - #[inline] - pub fn substs(self, tcx: TyCtxt<'tcx>) -> SubstsRef<'tcx> { - self.substs_.unwrap_or_else(|| { - // We must not use the parents default substs for promoted constants - // as that can result in incorrect substs and calls the `default_anon_const_substs` - // for something that might not actually be a constant. - debug_assert_eq!(self.promoted, Default::default()); - tcx.default_anon_const_substs(self.def.did) - }) + Unevaluated { def, substs, promoted: Default::default() } } } @@ -173,7 +153,7 @@ let param_env_and = if param_env_and.needs_infer() { tcx.param_env(unevaluated.def.did).and(ty::Unevaluated { def: unevaluated.def, - substs_: Some(InternalSubsts::identity_for_item(tcx, unevaluated.def.did)), + substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did), promoted: unevaluated.promoted, }) } else {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index dd571e2..41145d2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs
@@ -5,10 +5,12 @@ use crate::hir::place::Place as HirPlace; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource}; -use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault}; +use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath}; use crate::middle::stability; use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; -use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted}; +use crate::mir::{ + Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted, +}; use crate::thir::Thir; use crate::traits; use crate::ty::query::{self, TyCtxtAt}; @@ -16,14 +18,15 @@ use crate::ty::TyKind::*; use crate::ty::{ self, AdtDef, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, - ClosureSizeProfileData, Const, ConstVid, DefIdTree, ExistentialPredicate, FloatTy, FloatVar, - FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List, ParamConst, - ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind, ProjectionTy, Region, RegionKind, - ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, + ClosureSizeProfileData, Const, ConstS, ConstVid, DefIdTree, ExistentialPredicate, FloatTy, + FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List, + ParamConst, ParamTy, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, Region, + RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, }; use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::intern::Interned; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; @@ -89,7 +92,7 @@ #[derive(TyEncodable, TyDecodable, HashStable)] pub struct DelaySpanBugEmitted(()); -type InternedSet<'tcx, T> = ShardedHashMap<Interned<'tcx, T>, ()>; +type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>; pub struct CtxtInterners<'tcx> { /// The arena that types, regions, etc. are allocated from. @@ -104,15 +107,21 @@ region: InternedSet<'tcx, RegionKind>, poly_existential_predicates: InternedSet<'tcx, List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>>>, - predicate: InternedSet<'tcx, PredicateInner<'tcx>>, + predicate: InternedSet<'tcx, PredicateS<'tcx>>, predicates: InternedSet<'tcx, List<Predicate<'tcx>>>, projs: InternedSet<'tcx, List<ProjectionKind>>, place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>, - const_: InternedSet<'tcx, Const<'tcx>>, + const_: InternedSet<'tcx, ConstS<'tcx>>, const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>, layout: InternedSet<'tcx, Layout>, adt_def: InternedSet<'tcx, AdtDef>, + + /// `#[stable]` and `#[unstable]` attributes + stability: InternedSet<'tcx, attr::Stability>, + + /// `#[rustc_const_stable]` and `#[rustc_const_unstable]` attributes + const_stability: InternedSet<'tcx, attr::ConstStability>, } impl<'tcx> CtxtInterners<'tcx> { @@ -134,6 +143,8 @@ bound_variable_kinds: Default::default(), layout: Default::default(), adt_def: Default::default(), + stability: Default::default(), + const_stability: Default::default(), } } @@ -141,39 +152,40 @@ #[allow(rustc::usage_of_ty_tykind)] #[inline(never)] fn intern_ty(&self, kind: TyKind<'tcx>) -> Ty<'tcx> { - self.type_ - .intern(kind, |kind| { - let flags = super::flags::FlagComputation::for_kind(&kind); + Ty(Interned::new_unchecked( + self.type_ + .intern(kind, |kind| { + let flags = super::flags::FlagComputation::for_kind(&kind); - let ty_struct = TyS { - kind, - flags: flags.flags, - outer_exclusive_binder: flags.outer_exclusive_binder, - }; + let ty_struct = TyS { + kind, + flags: flags.flags, + outer_exclusive_binder: flags.outer_exclusive_binder, + }; - Interned(self.arena.alloc(ty_struct)) - }) - .0 + InternedInSet(self.arena.alloc(ty_struct)) + }) + .0, + )) } #[inline(never)] - fn intern_predicate( - &self, - kind: Binder<'tcx, PredicateKind<'tcx>>, - ) -> &'tcx PredicateInner<'tcx> { - self.predicate - .intern(kind, |kind| { - let flags = super::flags::FlagComputation::for_predicate(kind); + fn intern_predicate(&self, kind: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { + Predicate(Interned::new_unchecked( + self.predicate + .intern(kind, |kind| { + let flags = super::flags::FlagComputation::for_predicate(kind); - let predicate_struct = PredicateInner { - kind, - flags: flags.flags, - outer_exclusive_binder: flags.outer_exclusive_binder, - }; + let predicate_struct = PredicateS { + kind, + flags: flags.flags, + outer_exclusive_binder: flags.outer_exclusive_binder, + }; - Interned(self.arena.alloc(predicate_struct)) - }) - .0 + InternedInSet(self.arena.alloc(predicate_struct)) + }) + .0, + )) } } @@ -212,12 +224,12 @@ /// `ReStatic` pub re_static: Region<'tcx>, - /// Erased region, used after type-checking + /// Erased region, used outside of type inference. pub re_erased: Region<'tcx>, } pub struct CommonConsts<'tcx> { - pub unit: &'tcx Const<'tcx>, + pub unit: Const<'tcx>, } pub struct LocalTableInContext<'a, V> { @@ -352,7 +364,7 @@ field_indices: ItemLocalMap<usize>, /// Stores the types for various nodes in the AST. Note that this table - /// is not guaranteed to be populated until after typeck. See + /// is not guaranteed to be populated outside inference. See /// typeck::check::fn_ctxt for details. node_types: ItemLocalMap<Ty<'tcx>>, @@ -848,16 +860,16 @@ _ => false, }, - GenericArgKind::Lifetime(r) => match r { + GenericArgKind::Lifetime(r) => match *r { ty::ReLateBound(debruijn, br) => { // We only allow a `ty::INNERMOST` index in substitutions. - assert_eq!(*debruijn, ty::INNERMOST); + assert_eq!(debruijn, ty::INNERMOST); cvar == br.var } _ => false, }, - GenericArgKind::Const(ct) => match ct.val { + GenericArgKind::Const(ct) => match ct.val() { ty::ConstKind::Bound(debruijn, b) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(debruijn, ty::INNERMOST); @@ -918,22 +930,30 @@ impl<'tcx> CommonLifetimes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonLifetimes<'tcx> { - let mk = |r| interners.region.intern(r, |r| Interned(interners.arena.alloc(r))).0; + let mk = |r| { + Region(Interned::new_unchecked( + interners.region.intern(r, |r| InternedInSet(interners.arena.alloc(r))).0, + )) + }; CommonLifetimes { - re_root_empty: mk(RegionKind::ReEmpty(ty::UniverseIndex::ROOT)), - re_static: mk(RegionKind::ReStatic), - re_erased: mk(RegionKind::ReErased), + re_root_empty: mk(ty::ReEmpty(ty::UniverseIndex::ROOT)), + re_static: mk(ty::ReStatic), + re_erased: mk(ty::ReErased), } } } impl<'tcx> CommonConsts<'tcx> { fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> { - let mk_const = |c| interners.const_.intern(c, |c| Interned(interners.arena.alloc(c))).0; + let mk_const = |c| { + Const(Interned::new_unchecked( + interners.const_.intern(c, |c| InternedInSet(interners.arena.alloc(c))).0, + )) + }; CommonConsts { - unit: mk_const(ty::Const { + unit: mk_const(ty::ConstS { val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::ZST)), ty: types.unit, }), @@ -961,6 +981,7 @@ /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html #[derive(Copy, Clone)] #[rustc_diagnostic_item = "TyCtxt"] +#[cfg_attr(not(bootstrap), rustc_pass_by_value)] pub struct TyCtxt<'tcx> { gcx: &'tcx GlobalCtxt<'tcx>, } @@ -1034,12 +1055,6 @@ /// Data layout specification for the current target. pub data_layout: TargetDataLayout, - /// `#[stable]` and `#[unstable]` attributes - stability_interner: ShardedHashMap<&'tcx attr::Stability, ()>, - - /// `#[rustc_const_stable]` and `#[rustc_const_unstable]` attributes - const_stability_interner: ShardedHashMap<&'tcx attr::ConstStability, ()>, - /// Stores memory for globals (statics/consts). pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>, @@ -1058,6 +1073,17 @@ } } + pub fn mir_borrowck_opt_const_arg( + self, + def: ty::WithOptConstParam<LocalDefId>, + ) -> &'tcx BorrowCheckResult<'tcx> { + if let Some(param_did) = def.const_param_did { + self.mir_borrowck_const_arg((def.did, param_did)) + } else { + self.mir_borrowck(def.did) + } + } + pub fn alloc_steal_thir(self, thir: Thir<'tcx>) -> &'tcx Steal<Thir<'tcx>> { self.arena.alloc(Steal::new(thir)) } @@ -1091,16 +1117,6 @@ self.create_memory_alloc(alloc) } - // FIXME(eddyb) move to `direct_interners!`. - pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability { - self.stability_interner.intern(stab, |stab| self.arena.alloc(stab)) - } - - // FIXME(eddyb) move to `direct_interners!`. - pub fn intern_const_stability(self, stab: attr::ConstStability) -> &'tcx attr::ConstStability { - self.const_stability_interner.intern(stab, |stab| self.arena.alloc(stab)) - } - /// Returns a range of the start/end indices specified with the /// `rustc_layout_scalar_valid_range` attribute. // FIXME(eddyb) this is an awkward spot for this method, maybe move it? @@ -1184,8 +1200,6 @@ evaluation_cache: Default::default(), crate_name: Symbol::intern(crate_name), data_layout, - stability_interner: Default::default(), - const_stability_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames), } @@ -1209,12 +1223,26 @@ self.mk_ty(Error(DelaySpanBugEmitted(()))) } - /// Like `err` but for constants. + /// Like [TyCtxt::ty_error] but for constants. #[track_caller] - pub fn const_error(self, ty: Ty<'tcx>) -> &'tcx Const<'tcx> { - self.sess - .delay_span_bug(DUMMY_SP, "ty::ConstKind::Error constructed but no error reported."); - self.mk_const(ty::Const { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty }) + pub fn const_error(self, ty: Ty<'tcx>) -> Const<'tcx> { + self.const_error_with_message( + ty, + DUMMY_SP, + "ty::ConstKind::Error constructed but no error reported", + ) + } + + /// Like [TyCtxt::ty_error_with_message] but for constants. + #[track_caller] + pub fn const_error_with_message<S: Into<MultiSpan>>( + self, + ty: Ty<'tcx>, + span: S, + msg: &str, + ) -> Const<'tcx> { + self.sess.delay_span_bug(span, msg); + self.mk_const(ty::ConstS { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty }) } pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool { @@ -1307,7 +1335,7 @@ /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation /// session, if it still exists. This is used during incremental compilation to /// turn a deserialized `DefPathHash` into its current `DefId`. - pub fn def_path_hash_to_def_id(self, hash: DefPathHash) -> DefId { + pub fn def_path_hash_to_def_id(self, hash: DefPathHash, err: &mut dyn FnMut() -> !) -> DefId { debug!("def_path_hash_to_def_id({:?})", hash); let stable_crate_id = hash.stable_crate_id(); @@ -1315,7 +1343,10 @@ // If this is a DefPathHash from the local crate, we can look up the // DefId in the tcx's `Definitions`. if stable_crate_id == self.sess.local_stable_crate_id() { - self.untracked_resolutions.definitions.local_def_path_hash_to_def_id(hash).to_def_id() + self.untracked_resolutions + .definitions + .local_def_path_hash_to_def_id(hash, err) + .to_def_id() } else { // If this is a DefPathHash from an upstream crate, let the CrateStore map // it to a DefId. @@ -1461,8 +1492,7 @@ _ => return None, // not a free region }; - let hir_id = self.hir().local_def_id_to_hir_id(suitable_region_binding_scope); - let is_impl_item = match self.hir().find(hir_id) { + let is_impl_item = match self.hir().find_by_def_id(suitable_region_binding_scope) { Some(Node::Item(..) | Node::TraitItem(..)) => false, Some(Node::ImplItem(..)) => { self.is_bound_region_in_impl_item(suitable_region_binding_scope) @@ -1495,8 +1525,7 @@ pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> { // `type_of()` will fail on these (#55796, #86483), so only allow `fn`s or closures. - let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); - match self.hir().get(hir_id) { + match self.hir().get_by_def_id(scope_def_id) { Node::Item(&hir::Item { kind: ItemKind::Fn(..), .. }) => {} Node::TraitItem(&hir::TraitItem { kind: TraitItemKind::Fn(..), .. }) => {} Node::ImplItem(&hir::ImplItem { kind: ImplItemKind::Fn(..), .. }) => {} @@ -1510,6 +1539,7 @@ let sig = ret_ty.fn_sig(self); let output = self.erase_late_bound_regions(sig.output()); if output.is_impl_trait() { + let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap(); Some((output, fn_decl.output.span())) } else { @@ -1607,12 +1637,28 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted>; } +// Deprecated: we are in the process of converting all uses to `nop_lift`. +macro_rules! nop_lift_old { + ($set:ident; $ty:ty => $lifted:ty) => { + impl<'a, 'tcx> Lift<'tcx> for $ty { + type Lifted = $lifted; + fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { + if tcx.interners.$set.contains_pointer_to(&InternedInSet(self)) { + Some(unsafe { mem::transmute(self) }) + } else { + None + } + } + } + }; +} + macro_rules! nop_lift { ($set:ident; $ty:ty => $lifted:ty) => { impl<'a, 'tcx> Lift<'tcx> for $ty { type Lifted = $lifted; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - if tcx.interners.$set.contains_pointer_to(&Interned(self)) { + if tcx.interners.$set.contains_pointer_to(&InternedInSet(self.0.0)) { Some(unsafe { mem::transmute(self) }) } else { None @@ -1630,7 +1676,7 @@ if self.is_empty() { return Some(List::empty()); } - if tcx.interners.$set.contains_pointer_to(&Interned(self)) { + if tcx.interners.$set.contains_pointer_to(&InternedInSet(self)) { Some(unsafe { mem::transmute(self) }) } else { None @@ -1642,9 +1688,9 @@ nop_lift! {type_; Ty<'a> => Ty<'tcx>} nop_lift! {region; Region<'a> => Region<'tcx>} -nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>} -nop_lift! {const_allocation; &'a Allocation => &'tcx Allocation} -nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>} +nop_lift! {const_; Const<'a> => Const<'tcx>} +nop_lift_old! {const_allocation; &'a Allocation => &'tcx Allocation} +nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>} nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>} nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>} @@ -1661,7 +1707,7 @@ pub mod tls { use super::{ptr_eq, GlobalCtxt, TyCtxt}; - use crate::dep_graph::{DepKind, TaskDeps}; + use crate::dep_graph::TaskDepsRef; use crate::ty::query; use rustc_data_structures::sync::{self, Lock}; use rustc_data_structures::thin_vec::ThinVec; @@ -1686,7 +1732,7 @@ /// The current query job, if any. This is updated by `JobOwner::start` in /// `ty::query::plumbing` when executing a query. - pub query: Option<query::QueryJobId<DepKind>>, + pub query: Option<query::QueryJobId>, /// Where to store diagnostics for the current query job, if any. /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query. @@ -1697,13 +1743,19 @@ /// The current dep graph task. This is used to add dependencies to queries /// when executing them. - pub task_deps: Option<&'a Lock<TaskDeps>>, + pub task_deps: TaskDepsRef<'a>, } impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> { pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self { let tcx = TyCtxt { gcx }; - ImplicitCtxt { tcx, query: None, diagnostics: None, layout_depth: 0, task_deps: None } + ImplicitCtxt { + tcx, + query: None, + diagnostics: None, + layout_depth: 0, + task_deps: TaskDepsRef::Ignore, + } } } @@ -1831,7 +1883,7 @@ #[allow(non_snake_case)] mod inner { use crate::ty::{self, TyCtxt}; - use crate::ty::context::Interned; + use crate::ty::context::InternedInSet; #[derive(Copy, Clone)] struct DebugStat { @@ -1854,16 +1906,16 @@ let shards = tcx.interners.type_.lock_shards(); let types = shards.iter().flat_map(|shard| shard.keys()); - for &Interned(t) in types { - let variant = match t.kind() { + for &InternedInSet(t) in types { + let variant = match t.kind { ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Str | ty::Never => continue, ty::Error(_) => /* unimportant */ continue, $(ty::$variant(..) => &mut $variant,)* }; - let lt = t.flags().intersects(ty::TypeFlags::HAS_RE_INFER); - let ty = t.flags().intersects(ty::TypeFlags::HAS_TY_INFER); - let ct = t.flags().intersects(ty::TypeFlags::HAS_CT_INFER); + let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER); + let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER); + let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER); variant.total += 1; total.total += 1; @@ -1929,11 +1981,11 @@ writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?; writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?; - writeln!(fmt, "Stability interner: #{}", self.0.stability_interner.len())?; + writeln!(fmt, "Stability interner: #{}", self.0.interners.stability.len())?; writeln!( fmt, "Const Stability interner: #{}", - self.0.const_stability_interner.len() + self.0.interners.const_stability.len() )?; writeln!( fmt, @@ -1950,122 +2002,180 @@ } } -/// An entry in an interner. -struct Interned<'tcx, T: ?Sized>(&'tcx T); +// This type holds a `T` in the interner. The `T` is stored in the arena and +// this type just holds a pointer to it, but it still effectively owns it. It +// impls `Borrow` so that it can be looked up using the original +// (non-arena-memory-owning) types. +struct InternedInSet<'tcx, T: ?Sized>(&'tcx T); -impl<'tcx, T: 'tcx + ?Sized> Clone for Interned<'tcx, T> { +impl<'tcx, T: 'tcx + ?Sized> Clone for InternedInSet<'tcx, T> { fn clone(&self) -> Self { - Interned(self.0) + InternedInSet(self.0) } } -impl<'tcx, T: 'tcx + ?Sized> Copy for Interned<'tcx, T> {} -impl<'tcx, T: 'tcx + ?Sized> IntoPointer for Interned<'tcx, T> { +impl<'tcx, T: 'tcx + ?Sized> Copy for InternedInSet<'tcx, T> {} + +impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> { fn into_pointer(&self) -> *const () { self.0 as *const _ as *const () } } -// N.B., an `Interned<Ty>` compares and hashes as a `TyKind`. -impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> { - fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool { - self.0.kind() == other.0.kind() - } -} - -impl<'tcx> Eq for Interned<'tcx, TyS<'tcx>> {} - -impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> { - fn hash<H: Hasher>(&self, s: &mut H) { - self.0.kind().hash(s) - } -} #[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Borrow<TyKind<'tcx>> for Interned<'tcx, TyS<'tcx>> { +impl<'tcx> Borrow<TyKind<'tcx>> for InternedInSet<'tcx, TyS<'tcx>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { - &self.0.kind() + &self.0.kind } } -// N.B., an `Interned<PredicateInner>` compares and hashes as a `PredicateKind`. -impl<'tcx> PartialEq for Interned<'tcx, PredicateInner<'tcx>> { - fn eq(&self, other: &Interned<'tcx, PredicateInner<'tcx>>) -> bool { + +impl<'tcx> PartialEq for InternedInSet<'tcx, TyS<'tcx>> { + fn eq(&self, other: &InternedInSet<'tcx, TyS<'tcx>>) -> bool { + // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals + // `x == y`. self.0.kind == other.0.kind } } -impl<'tcx> Eq for Interned<'tcx, PredicateInner<'tcx>> {} +impl<'tcx> Eq for InternedInSet<'tcx, TyS<'tcx>> {} -impl<'tcx> Hash for Interned<'tcx, PredicateInner<'tcx>> { +impl<'tcx> Hash for InternedInSet<'tcx, TyS<'tcx>> { fn hash<H: Hasher>(&self, s: &mut H) { + // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. self.0.kind.hash(s) } } -impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>> for Interned<'tcx, PredicateInner<'tcx>> { +impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>> for InternedInSet<'tcx, PredicateS<'tcx>> { fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { &self.0.kind } } -// N.B., an `Interned<List<T>>` compares and hashes as its elements. -impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, List<T>> { - fn eq(&self, other: &Interned<'tcx, List<T>>) -> bool { - self.0[..] == other.0[..] +impl<'tcx> PartialEq for InternedInSet<'tcx, PredicateS<'tcx>> { + fn eq(&self, other: &InternedInSet<'tcx, PredicateS<'tcx>>) -> bool { + // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals + // `x == y`. + self.0.kind == other.0.kind } } -impl<'tcx, T: Eq> Eq for Interned<'tcx, List<T>> {} +impl<'tcx> Eq for InternedInSet<'tcx, PredicateS<'tcx>> {} -impl<'tcx, T: Hash> Hash for Interned<'tcx, List<T>> { +impl<'tcx> Hash for InternedInSet<'tcx, PredicateS<'tcx>> { fn hash<H: Hasher>(&self, s: &mut H) { - self.0[..].hash(s) + // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. + self.0.kind.hash(s) } } -impl<'tcx, T> Borrow<[T]> for Interned<'tcx, List<T>> { +impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, List<T>> { fn borrow<'a>(&'a self) -> &'a [T] { &self.0[..] } } +impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, List<T>> { + fn eq(&self, other: &InternedInSet<'tcx, List<T>>) -> bool { + // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals + // `x == y`. + self.0[..] == other.0[..] + } +} + +impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, List<T>> {} + +impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, List<T>> { + fn hash<H: Hasher>(&self, s: &mut H) { + // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. + self.0[..].hash(s) + } +} + macro_rules! direct_interners { - ($($name:ident: $method:ident($ty:ty),)+) => { - $(impl<'tcx> PartialEq for Interned<'tcx, $ty> { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - - impl<'tcx> Eq for Interned<'tcx, $ty> {} - - impl<'tcx> Hash for Interned<'tcx, $ty> { - fn hash<H: Hasher>(&self, s: &mut H) { - self.0.hash(s) - } - } - - impl<'tcx> Borrow<$ty> for Interned<'tcx, $ty> { + ($($name:ident: $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => { + $(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> { fn borrow<'a>(&'a self) -> &'a $ty { &self.0 } } + impl<'tcx> PartialEq for InternedInSet<'tcx, $ty> { + fn eq(&self, other: &Self) -> bool { + // The `Borrow` trait requires that `x.borrow() == y.borrow()` + // equals `x == y`. + self.0 == other.0 + } + } + + impl<'tcx> Eq for InternedInSet<'tcx, $ty> {} + + impl<'tcx> Hash for InternedInSet<'tcx, $ty> { + fn hash<H: Hasher>(&self, s: &mut H) { + // The `Borrow` trait requires that `x.borrow().hash(s) == + // x.hash(s)`. + self.0.hash(s) + } + } + impl<'tcx> TyCtxt<'tcx> { - pub fn $method(self, v: $ty) -> &'tcx $ty { - self.interners.$name.intern(v, |v| { - Interned(self.interners.arena.alloc(v)) - }).0 + pub fn $method(self, v: $ty) -> $ret_ty { + $ret_ctor(Interned::new_unchecked(self.interners.$name.intern(v, |v| { + InternedInSet(self.interners.arena.alloc(v)) + }).0)) } })+ } } direct_interners! { - region: mk_region(RegionKind), - const_: mk_const(Const<'tcx>), + region: mk_region(RegionKind): Region -> Region<'tcx>, + const_: mk_const(ConstS<'tcx>): Const -> Const<'tcx>, +} + +macro_rules! direct_interners_old { + ($($name:ident: $method:ident($ty:ty),)+) => { + $(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> { + fn borrow<'a>(&'a self) -> &'a $ty { + &self.0 + } + } + + impl<'tcx> PartialEq for InternedInSet<'tcx, $ty> { + fn eq(&self, other: &Self) -> bool { + // The `Borrow` trait requires that `x.borrow() == y.borrow()` + // equals `x == y`. + self.0 == other.0 + } + } + + impl<'tcx> Eq for InternedInSet<'tcx, $ty> {} + + impl<'tcx> Hash for InternedInSet<'tcx, $ty> { + fn hash<H: Hasher>(&self, s: &mut H) { + // The `Borrow` trait requires that `x.borrow().hash(s) == + // x.hash(s)`. + self.0.hash(s) + } + } + + impl<'tcx> TyCtxt<'tcx> { + pub fn $method(self, v: $ty) -> &'tcx $ty { + self.interners.$name.intern(v, |v| { + InternedInSet(self.interners.arena.alloc(v)) + }).0 + } + })+ + } +} + +// FIXME: eventually these should all be converted to `direct_interners`. +direct_interners_old! { const_allocation: intern_const_alloc(Allocation), layout: intern_layout(Layout), adt_def: intern_adt_def(AdtDef), + stability: intern_stability(attr::Stability), + const_stability: intern_const_stability(attr::ConstStability), } macro_rules! slice_interners { @@ -2073,7 +2183,7 @@ impl<'tcx> TyCtxt<'tcx> { $(pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> { self.interners.$field.intern_ref(v, || { - Interned(List::from_arena(&*self.arena, v)) + InternedInSet(List::from_arena(&*self.arena, v)) }).0 })+ } @@ -2173,8 +2283,7 @@ #[inline] pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { - let inner = self.interners.intern_predicate(binder); - Predicate { inner } + self.interners.intern_predicate(binder) } #[inline] @@ -2385,8 +2494,8 @@ } #[inline] - pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> { - self.mk_const(ty::Const { val: ty::ConstKind::Infer(InferConst::Var(v)), ty }) + pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + self.mk_const(ty::ConstS { val: ty::ConstKind::Infer(InferConst::Var(v)), ty }) } #[inline] @@ -2405,8 +2514,8 @@ } #[inline] - pub fn mk_const_infer(self, ic: InferConst<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> { - self.mk_const(ty::Const { val: ty::ConstKind::Infer(ic), ty }) + pub fn mk_const_infer(self, ic: InferConst<'tcx>, ty: Ty<'tcx>) -> ty::Const<'tcx> { + self.mk_const(ty::ConstS { val: ty::ConstKind::Infer(ic), ty }) } #[inline] @@ -2415,8 +2524,8 @@ } #[inline] - pub fn mk_const_param(self, index: u32, name: Symbol, ty: Ty<'tcx>) -> &'tcx Const<'tcx> { - self.mk_const(ty::Const { val: ty::ConstKind::Param(ParamConst { index, name }), ty }) + pub fn mk_const_param(self, index: u32, name: Symbol, ty: Ty<'tcx>) -> Const<'tcx> { + self.mk_const(ty::ConstS { val: ty::ConstKind::Param(ParamConst { index, name }), ty }) } pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { @@ -2452,7 +2561,7 @@ ) -> Place<'tcx> { self.mk_place_elem( place, - PlaceElem::Downcast(Some(adt_def.variants[variant_index].ident.name), variant_index), + PlaceElem::Downcast(Some(adt_def.variants[variant_index].name), variant_index), ) } @@ -2677,10 +2786,6 @@ .map_or(false, |(owner, set)| owner == id.owner && set.contains(&id.local_id)) } - pub fn object_lifetime_defaults(self, id: HirId) -> Option<Vec<ObjectLifetimeDefault>> { - self.object_lifetime_defaults_map(id.owner) - } - pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> { self.mk_bound_variable_kinds( self.late_bound_vars_map(id.owner) @@ -2692,8 +2797,8 @@ ) } - pub fn lifetime_scope(self, id: HirId) -> Option<LifetimeScopeForPath> { - self.lifetime_scope_map(id.owner).and_then(|mut map| map.remove(&id.local_id)) + pub fn lifetime_scope(self, id: HirId) -> Option<&'tcx LifetimeScopeForPath> { + self.lifetime_scope_map(id.owner).as_ref().and_then(|map| map.get(&id.local_id)) } /// Whether the `def_id` counts as const fn in the current crate, considering all active @@ -2763,8 +2868,33 @@ impl<T, R> InternIteratorElement<T, R> for T { type Output = R; - fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { - f(&iter.collect::<SmallVec<[_; 8]>>()) + fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>( + mut iter: I, + f: F, + ) -> Self::Output { + // This code is hot enough that it's worth specializing for the most + // common length lists, to avoid the overhead of `SmallVec` creation. + // Lengths 0, 1, and 2 typically account for ~95% of cases. If + // `size_hint` is incorrect a panic will occur via an `unwrap` or an + // `assert`. + match iter.size_hint() { + (0, Some(0)) => { + assert!(iter.next().is_none()); + f(&[]) + } + (1, Some(1)) => { + let t0 = iter.next().unwrap(); + assert!(iter.next().is_none()); + f(&[t0]) + } + (2, Some(2)) => { + let t0 = iter.next().unwrap(); + let t1 = iter.next().unwrap(); + assert!(iter.next().is_none()); + f(&[t0, t1]) + } + _ => f(&iter.collect::<SmallVec<[_; 8]>>()), + } } } @@ -2774,6 +2904,7 @@ { type Output = R; fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { + // This code isn't hot. f(&iter.cloned().collect::<SmallVec<[_; 8]>>()) } } @@ -2786,10 +2917,15 @@ ) -> Self::Output { // This code is hot enough that it's worth specializing for the most // common length lists, to avoid the overhead of `SmallVec` creation. - // The match arms are in order of frequency. The 1, 2, and 0 cases are - // typically hit in ~95% of cases. We assume that if the upper and - // lower bounds from `size_hint` agree they are correct. + // Lengths 0, 1, and 2 typically account for ~95% of cases. If + // `size_hint` is incorrect a panic will occur via an `unwrap` or an + // `assert`, unless a failure happens first, in which case the result + // will be an error anyway. Ok(match iter.size_hint() { + (0, Some(0)) => { + assert!(iter.next().is_none()); + f(&[]) + } (1, Some(1)) => { let t0 = iter.next().unwrap()?; assert!(iter.next().is_none()); @@ -2801,10 +2937,6 @@ assert!(iter.next().is_none()); f(&[t0, t1]) } - (0, Some(0)) => { - assert!(iter.next().is_none()); - f(&[]) - } _ => f(&iter.collect::<Result<SmallVec<[_; 8]>, _>>()?), }) } @@ -2817,10 +2949,9 @@ } pub fn provide(providers: &mut ty::query::Providers) { - providers.in_scope_traits_map = - |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map(|owner_info| &owner_info.trait_map); providers.resolutions = |tcx, ()| &tcx.untracked_resolutions; - providers.module_exports = |tcx, id| tcx.resolutions(()).export_map.get(&id).map(|v| &v[..]); + providers.module_reexports = + |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]); providers.crate_name = |tcx, id| { assert_eq!(id, LOCAL_CRATE); tcx.crate_name @@ -2840,7 +2971,7 @@ |tcx, id| tcx.stability().local_deprecation_entry(id.expect_local()); providers.extern_mod_stmt_cnum = |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned(); - providers.output_filenames = |tcx, ()| tcx.output_filenames.clone(); + providers.output_filenames = |tcx, ()| &tcx.output_filenames; providers.features_query = |tcx, ()| tcx.sess.features_untracked(); providers.is_panic_runtime = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE);
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index ee00f6c..64b2edd 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -1,10 +1,10 @@ -//! Diagnostics related methods for `TyS`. +//! Diagnostics related methods for `Ty`. use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::TyKind::*; use crate::ty::{ ConstKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, InferTy, - ProjectionTy, TyCtxt, TyS, TypeAndMut, + ProjectionTy, Term, Ty, TyCtxt, TypeAndMut, }; use rustc_errors::{Applicability, DiagnosticBuilder}; @@ -13,9 +13,9 @@ use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate}; use rustc_span::Span; -impl<'tcx> TyS<'tcx> { - /// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive. - pub fn is_primitive_ty(&self) -> bool { +impl<'tcx> Ty<'tcx> { + /// Similar to `Ty::is_primitive`, but also considers inferred numeric values to be primitive. + pub fn is_primitive_ty(self) -> bool { matches!( self.kind(), Bool | Char @@ -34,7 +34,7 @@ /// Whether the type is succinctly representable as a type instead of just referred to with a /// description in error messages. This is used in the main error message. - pub fn is_simple_ty(&self) -> bool { + pub fn is_simple_ty(self) -> bool { match self.kind() { Bool | Char @@ -58,7 +58,7 @@ /// description in error messages. This is used in the primary span label. Beyond what /// `is_simple_ty` includes, it also accepts ADTs with no type arguments and references to /// ADTs with no type arguments. - pub fn is_simple_text(&self) -> bool { + pub fn is_simple_text(self) -> bool { match self.kind() { Adt(_, substs) => substs.non_erasable_generics().next().is_none(), Ref(_, ty, _) => ty.is_simple_text(), @@ -67,11 +67,11 @@ } /// Whether the type can be safely suggested during error recovery. - pub fn is_suggestable(&self) -> bool { + pub fn is_suggestable(self) -> bool { fn generic_arg_is_suggestible(arg: GenericArg<'_>) -> bool { match arg.unpack() { GenericArgKind::Type(ty) => ty.is_suggestable(), - GenericArgKind::Const(c) => const_is_suggestable(c.val), + GenericArgKind::Const(c) => const_is_suggestable(c.val()), _ => true, } } @@ -105,8 +105,14 @@ ExistentialPredicate::Trait(ExistentialTraitRef { substs, .. }) => { substs.iter().all(generic_arg_is_suggestible) } - ExistentialPredicate::Projection(ExistentialProjection { substs, ty, .. }) => { - ty.is_suggestable() && substs.iter().all(generic_arg_is_suggestible) + ExistentialPredicate::Projection(ExistentialProjection { + substs, term, .. + }) => { + let term_is_suggestable = match term { + Term::Ty(ty) => ty.is_suggestable(), + Term::Const(c) => const_is_suggestable(c.val()), + }; + term_is_suggestable && substs.iter().all(generic_arg_is_suggestible) } _ => true, }), @@ -114,7 +120,7 @@ args.iter().all(generic_arg_is_suggestible) } Slice(ty) | RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => ty.is_suggestable(), - Array(ty, c) => ty.is_suggestable() && const_is_suggestable(c.val), + Array(ty, c) => ty.is_suggestable() && const_is_suggestable(c.val()), _ => true, } } @@ -448,12 +454,6 @@ pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir::map::Map<'tcx>); impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { - type Map = rustc_hir::intravisit::ErasedMap<'v>; - - fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> { - hir::intravisit::NestedVisitorMap::None - } - fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { match ty.kind { hir::TyKind::TraitObject( @@ -482,12 +482,6 @@ pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<'tcx>); impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> { - type Map = rustc_hir::intravisit::ErasedMap<'v>; - - fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> { - hir::intravisit::NestedVisitorMap::None - } - fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) { if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = lt.name
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 0d29075..ef4f77c 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -21,9 +21,7 @@ T: TypeFoldable<'tcx>, { // If there's nothing to erase avoid performing the query at all - if !value - .has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_POTENTIAL_FREE_REGIONS) - { + if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { return value; } debug!("erase_regions({:?})", value);
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index df6e739..2ccfeba 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs
@@ -60,13 +60,13 @@ /// created a cycle (because it appears somewhere within that /// type). CyclicTy(Ty<'tcx>), - CyclicConst(&'tcx ty::Const<'tcx>), + CyclicConst(ty::Const<'tcx>), ProjectionMismatched(ExpectedFound<DefId>), ExistentialMismatch( ExpectedFound<&'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>>, ), ObjectUnsafeCoercion(DefId), - ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), + ConstMismatch(ExpectedFound<ty::Const<'tcx>>), IntrinsicCast, /// Safe `#[target_feature]` functions are not assignable to safe function pointers. @@ -239,8 +239,8 @@ } } -impl<'tcx> ty::TyS<'tcx> { - pub fn sort_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> { +impl<'tcx> Ty<'tcx> { + pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> { match *self.kind() { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => { format!("`{}`", self).into() @@ -255,7 +255,7 @@ } let n = tcx.lift(n).unwrap(); - if let ty::ConstKind::Value(v) = n.val { + if let ty::ConstKind::Value(v) = n.val() { if let Some(n) = v.try_to_machine_usize(tcx) { return format!("array of {} element{}", n, pluralize!(n)).into(); } @@ -306,7 +306,7 @@ } } - pub fn prefix_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> { + pub fn prefix_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> { match *self.kind() { ty::Infer(_) | ty::Error(_) @@ -869,7 +869,7 @@ // When `body_owner` is an `impl` or `trait` item, look in its associated types for // `expected` and point at it. let parent_id = self.hir().get_parent_item(hir_id); - let item = self.hir().find(parent_id); + let item = self.hir().find_by_def_id(parent_id); debug!("expected_projection parent item {:?}", item); match item { Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => { @@ -972,10 +972,10 @@ let (span, sugg) = if has_params { let pos = span.hi() - BytePos(1); let span = Span::new(pos, pos, span.ctxt(), span.parent()); - (span, format!(", {} = {}", assoc.ident, ty)) + (span, format!(", {} = {}", assoc.ident(self), ty)) } else { let item_args = self.format_generic_args(assoc_substs); - (span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident, item_args, ty)) + (span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(self), item_args, ty)) }; db.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect); return true;
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index daf9156..983057b 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -54,12 +54,6 @@ No, } -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub enum StripReferences { - Yes, - No, -} - /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists. /// /// The idea is to get something simple that we can use to quickly decide if two types could unify, @@ -73,8 +67,6 @@ /// When using `SimplifyParams::Yes`, we still return a simplified type for params and projections², /// the reasoning for this can be seen at the places doing this. /// -/// For diagnostics we strip references with `StripReferences::Yes`. This is currently the best -/// way to skip some unhelpful suggestions. /// /// ¹ meaning that if two outermost layers are different, then the whole types are also different. /// ² FIXME(@lcnr): this seems like it can actually end up being unsound with the way it's used during @@ -87,7 +79,6 @@ tcx: TyCtxt<'_>, ty: Ty<'_>, can_simplify_params: SimplifyParams, - strip_references: StripReferences, ) -> Option<SimplifiedType> { match *ty.kind() { ty::Bool => Some(BoolSimplifiedType), @@ -106,16 +97,7 @@ } _ => Some(MarkerTraitObjectSimplifiedType), }, - ty::Ref(_, ty, mutbl) => { - if strip_references == StripReferences::Yes { - // For diagnostics, when recommending similar impls we want to - // recommend impls even when there is a reference mismatch, - // so we treat &T and T equivalently in that case. - simplify_type(tcx, ty, can_simplify_params, strip_references) - } else { - Some(RefSimplifiedType(mutbl)) - } - } + ty::Ref(_, _, mutbl) => Some(RefSimplifiedType(mutbl)), ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)), ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)), ty::GeneratorWitness(ref tys) => {
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 617c522..948a48c 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -1,12 +1,12 @@ use crate::ty::subst::{GenericArg, GenericArgKind}; -use crate::ty::{self, InferConst, Ty, TypeFlags}; +use crate::ty::{self, InferConst, Term, Ty, TypeFlags}; use std::slice; #[derive(Debug)] pub struct FlagComputation { pub flags: TypeFlags, - // see `TyS::outer_exclusive_binder` for details + // see `Ty::outer_exclusive_binder` for details pub outer_exclusive_binder: ty::DebruijnIndex, } @@ -28,7 +28,7 @@ result } - pub fn for_const(c: &ty::Const<'_>) -> TypeFlags { + pub fn for_const(c: ty::Const<'_>) -> TypeFlags { let mut result = FlagComputation::new(); result.add_const(c); result.flags @@ -97,7 +97,7 @@ &ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), &ty::Param(_) => { - self.add_flags(TypeFlags::HAS_KNOWN_TY_PARAM); + self.add_flags(TypeFlags::HAS_TY_PARAM); self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } @@ -241,9 +241,12 @@ self.add_ty(a); self.add_ty(b); } - ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => { + ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { self.add_projection_ty(projection_ty); - self.add_ty(ty); + match term { + Term::Ty(ty) => self.add_ty(ty), + Term::Const(c) => self.add_const(c), + } } ty::PredicateKind::WellFormed(arg) => { self.add_substs(slice::from_ref(&arg)); @@ -267,7 +270,7 @@ fn add_ty(&mut self, ty: Ty<'_>) { self.add_flags(ty.flags()); - self.add_exclusive_binder(ty.outer_exclusive_binder); + self.add_exclusive_binder(ty.outer_exclusive_binder()); } fn add_tys(&mut self, tys: &[Ty<'_>]) { @@ -283,9 +286,9 @@ } } - fn add_const(&mut self, c: &ty::Const<'_>) { - self.add_ty(c.ty); - match c.val { + fn add_const(&mut self, c: ty::Const<'_>) { + self.add_ty(c.ty()); + match c.val() { ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated), ty::ConstKind::Infer(infer) => { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); @@ -298,7 +301,7 @@ self.add_bound_var(debruijn); } ty::ConstKind::Param(_) => { - self.add_flags(TypeFlags::HAS_KNOWN_CT_PARAM); + self.add_flags(TypeFlags::HAS_CT_PARAM); self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } ty::ConstKind::Placeholder(_) => { @@ -311,29 +314,16 @@ } fn add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'_, P>) { - // The generic arguments of unevaluated consts are a bit special, - // see the `rustc-dev-guide` for more information. - // - // FIXME(@lcnr): Actually add a link here. - if let Some(substs) = ct.substs_ { - // If they are available, we treat them as ordinary generic arguments. - self.add_substs(substs); - } else { - // Otherwise, we add `HAS_UNKNOWN_DEFAULT_CONST_SUBSTS` to signify - // that our const may potentially refer to generic parameters. - // - // Note that depending on which generic parameters are actually - // used in this constant, we may not actually refer to any generic - // parameters at all. - self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); - self.add_flags(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS); - } + self.add_substs(ct.substs); self.add_flags(TypeFlags::HAS_CT_PROJECTION); } fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) { self.add_substs(projection.substs); - self.add_ty(projection.ty); + match projection.term { + ty::Term::Ty(ty) => self.add_ty(ty), + ty::Term::Const(ct) => self.add_const(ct), + } } fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) {
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index f5be8b2..4922d07 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -1,38 +1,56 @@ -//! Generalized type folding mechanism. The setup is a bit convoluted -//! but allows for convenient usage. Let T be an instance of some -//! "foldable type" (one which implements `TypeFoldable`) and F be an -//! instance of a "folder" (a type which implements `TypeFolder`). Then -//! the setup is intended to be: +//! A generalized traversal mechanism for complex data structures that contain +//! type information. //! -//! T.fold_with(F) --calls--> F.fold_T(T) --calls--> T.super_fold_with(F) +//! There are two types of traversal. +//! - Folding. This is a modifying traversal. It consumes the data structure, +//! producing a (possibly) modified version of it. Both fallible and +//! infallible versions are available. The name is potentially +//! confusing, because this traversal is more like `Iterator::map` than +//! `Iterator::fold`. +//! - Visiting. This is a read-only traversal of the data structure. //! -//! This way, when you define a new folder F, you can override -//! `fold_T()` to customize the behavior, and invoke `T.super_fold_with()` -//! to get the original behavior. Meanwhile, to actually fold -//! something, you can just write `T.fold_with(F)`, which is -//! convenient. (Note that `fold_with` will also transparently handle -//! things like a `Vec<T>` where T is foldable and so on.) +//! These traversals have limited flexibility. Only a small number of "types of +//! interest" within the complex data structures can receive custom +//! modification (when folding) or custom visitation (when visiting). These are +//! the ones containing the most important type-related information, such as +//! `Ty`, `Predicate`, `Region`, and `Const`. //! -//! In this ideal setup, the only function that actually *does* -//! anything is `T.super_fold_with()`, which traverses the type `T`. -//! Moreover, `T.super_fold_with()` should only ever call `T.fold_with()`. +//! There are two traits involved in each traversal type. +//! - The first trait is `TypeFoldable`, which is implemented once for many +//! types. This includes both (a) types of interest, and (b) all other +//! relevant types, including generic containers like `Vec` and `Option`. It +//! defines a "skeleton" of how they should be traversed, for both folding +//! and visiting. +//! - The second trait is `TypeFolder`/`FallibleTypeFolder` (for +//! infallible/fallible folding traversals) or `TypeVisitor` (for visiting +//! traversals). One of these is implemented for each folder/visitor. This +//! defines how types of interest are handled. //! -//! In some cases, we follow a degenerate pattern where we do not have -//! a `fold_T` method. Instead, `T.fold_with` traverses the structure directly. -//! This is suboptimal because the behavior cannot be overridden, but it's -//! much less work to implement. If you ever *do* need an override that -//! doesn't exist, it's not hard to convert the degenerate pattern into the -//! proper thing. +//! This means each traversal is a mixture of (a) generic traversal operations, +//! and (b) custom fold/visit operations that are specific to the +//! folder/visitor. +//! - The `TypeFoldable` impls handle most of the traversal, and call into +//! `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` when they encounter a +//! type of interest. +//! - A `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` may also call back into +//! a `TypeFoldable` impl, because (a) the types of interest are recursive +//! and can contain other types of interest, and (b) each folder/visitor +//! might provide custom handling only for some types of interest, or only +//! for some variants of each type of interest, and then use default +//! traversal for the remaining cases. //! -//! A `TypeFoldable` T can also be visited by a `TypeVisitor` V using similar setup: -//! -//! T.visit_with(V) --calls--> V.visit_T(T) --calls--> T.super_visit_with(V). -//! -//! These methods return true to indicate that the visitor has found what it is -//! looking for, and does not need to visit anything else. +//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U: +//! TypeFoldable`, and an instance `S(ty, u)`, it would be visited like so: +//! ``` +//! s.visit_with(visitor) calls +//! - s.super_visit_with(visitor) calls +//! - ty.visit_with(visitor) calls +//! - visitor.visit_ty(ty) may call +//! - ty.super_visit_with(visitor) +//! - u.visit_with(visitor) +//! ``` use crate::mir; use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; -use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_data_structures::fx::FxHashSet; @@ -41,42 +59,67 @@ use std::fmt; use std::ops::ControlFlow; -/// This trait is implemented for every type that can be folded. -/// Basically, every type that has a corresponding method in `TypeFolder`. +/// This trait is implemented for every type that can be folded/visited, +/// providing the skeleton of the traversal. /// -/// To implement this conveniently, use the derive macro located in `rustc_macros`. +/// To implement this conveniently, use the derive macro located in +/// `rustc_macros`. pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { - /// Consumers may find this more convenient to use with infallible folders than - /// [`try_super_fold_with`][`TypeFoldable::try_super_fold_with`], to which the - /// provided default definition delegates. Implementors **should not** override - /// this provided default definition, to ensure that the two methods are coherent - /// (provide a definition of `try_super_fold_with` instead). - fn super_fold_with<F: TypeFolder<'tcx, Error = !>>(self, folder: &mut F) -> Self { - self.try_super_fold_with(folder).into_ok() + /// The main entry point for folding. To fold a value `t` with a folder `f` + /// call: `t.try_fold_with(f)`. + /// + /// For types of interest (such as `Ty`), this default is overridden with a + /// method that calls a folder method specifically for that type (such as + /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable` + /// to `TypeFolder`. + /// + /// For other types, this default is used. + fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + self.try_super_fold_with(folder) } - /// Consumers may find this more convenient to use with infallible folders than - /// [`try_fold_with`][`TypeFoldable::try_fold_with`], to which the provided - /// default definition delegates. Implementors **should not** override this - /// provided default definition, to ensure that the two methods are coherent - /// (provide a definition of `try_fold_with` instead). + + /// A convenient alternative to `try_fold_with` for use with infallible + /// folders. Do not override this method, to ensure coherence with + /// `try_fold_with`. fn fold_with<F: TypeFolder<'tcx, Error = !>>(self, folder: &mut F) -> Self { self.try_fold_with(folder).into_ok() } + /// Traverses the type in question, typically by calling `try_fold_with` on + /// each field/element. This is true even for types of interest such as + /// `Ty`. This should only be called within `TypeFolder` methods, when + /// non-custom traversals are desired for types of interest. fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>( self, folder: &mut F, ) -> Result<Self, F::Error>; - fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { - self.try_super_fold_with(folder) + /// A convenient alternative to `try_super_fold_with` for use with + /// infallible folders. Do not override this method, to ensure coherence + /// with `try_super_fold_with`. + fn super_fold_with<F: TypeFolder<'tcx, Error = !>>(self, folder: &mut F) -> Self { + self.try_super_fold_with(folder).into_ok() } - fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>; + /// The entry point for visiting. To visit a value `t` with a visitor `v` + /// call: `t.visit_with(v)`. + /// + /// For types of interest (such as `Ty`), this default is overridden with a + /// method that calls a visitor method specifically for that type (such as + /// `V::visit_ty`). This is where control transfers from `TypeFoldable` to + /// `TypeVisitor`. + /// + /// For other types, this default is used. fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.super_visit_with(visitor) } + /// Traverses the type in question, typically by calling `visit_with` on + /// each field/element. This is true even for types of interest such as + /// `Ty`. This should only be called within `TypeVisitor` methods, when + /// non-custom traversals are desired for types of interest. + fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>; + /// Returns `true` if `self` has any late-bound regions that are either /// bound by `binder` or bound by some binder outside of `binder`. /// If `binder` is `ty::INNERMOST`, this indicates whether @@ -95,15 +138,9 @@ self.has_vars_bound_at_or_above(ty::INNERMOST) } - fn definitely_has_type_flags(&self, tcx: TyCtxt<'tcx>, flags: TypeFlags) -> bool { - self.visit_with(&mut HasTypeFlagsVisitor { tcx: Some(tcx), flags }).break_value() - == Some(FoundFlags) - } - #[instrument(level = "trace")] fn has_type_flags(&self, flags: TypeFlags) -> bool { - self.visit_with(&mut HasTypeFlagsVisitor { tcx: None, flags }).break_value() - == Some(FoundFlags) + self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags) } fn has_projections(&self) -> bool { self.has_type_flags(TypeFlags::HAS_PROJECTION) @@ -114,18 +151,8 @@ fn references_error(&self) -> bool { self.has_type_flags(TypeFlags::HAS_ERROR) } - fn potentially_has_param_types_or_consts(&self) -> bool { - self.has_type_flags( - TypeFlags::HAS_KNOWN_TY_PARAM - | TypeFlags::HAS_KNOWN_CT_PARAM - | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS, - ) - } - fn definitely_has_param_types_or_consts(&self, tcx: TyCtxt<'tcx>) -> bool { - self.definitely_has_type_flags( - tcx, - TypeFlags::HAS_KNOWN_TY_PARAM | TypeFlags::HAS_KNOWN_CT_PARAM, - ) + fn has_param_types_or_consts(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM) } fn has_infer_regions(&self) -> bool { self.has_type_flags(TypeFlags::HAS_RE_INFER) @@ -146,18 +173,13 @@ | TypeFlags::HAS_CT_PLACEHOLDER, ) } - fn potentially_needs_subst(&self) -> bool { - self.has_type_flags( - TypeFlags::KNOWN_NEEDS_SUBST | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS, - ) - } - fn definitely_needs_subst(&self, tcx: TyCtxt<'tcx>) -> bool { - self.definitely_has_type_flags(tcx, TypeFlags::KNOWN_NEEDS_SUBST) + fn needs_subst(&self) -> bool { + self.has_type_flags(TypeFlags::NEEDS_SUBST) } /// "Free" regions in this context means that it has any region /// that is not (a) erased or (b) late-bound. - fn has_free_regions(&self, tcx: TyCtxt<'tcx>) -> bool { - self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS) + fn has_free_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) } fn has_erased_regions(&self) -> bool { @@ -165,25 +187,15 @@ } /// True if there are any un-erased free regions. - fn has_erasable_regions(&self, tcx: TyCtxt<'tcx>) -> bool { - self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS) - } - - /// Indicates whether this value definitely references only 'global' - /// generic parameters that are the same regardless of what fn we are - /// in. This is used for caching. - /// - /// Note that this function is pessimistic and may incorrectly return - /// `false`. - fn is_known_global(&self) -> bool { - !self.has_type_flags(TypeFlags::HAS_POTENTIAL_FREE_LOCAL_NAMES) + fn has_erasable_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) } /// Indicates whether this value references only 'global' /// generic parameters that are the same regardless of what fn we are /// in. This is used for caching. - fn is_global(&self, tcx: TyCtxt<'tcx>) -> bool { - !self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES) + fn is_global(&self) -> bool { + !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES) } /// True if there are any late-bound regions @@ -199,24 +211,13 @@ } } -impl<'tcx> TypeFoldable<'tcx> for hir::Constness { - fn try_super_fold_with<F: TypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { - Ok(self) - } - fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { - ControlFlow::CONTINUE - } -} - -/// The `TypeFolder` trait defines the actual *folding*. There is a -/// method defined for every foldable type. Each of these has a -/// default implementation that does an "identity" fold. Within each -/// identity fold, it should invoke `foo.fold_with(self)` to fold each -/// sub-item. +/// This trait is implemented for every folding traversal. There is a fold +/// method defined for every type of interest. Each such method has a default +/// that does an "identity" fold. /// /// If this folder is fallible (and therefore its [`Error`][`TypeFolder::Error`] -/// associated type is something other than the default, never), -/// [`FallibleTypeFolder`] should be implemented manually; otherwise, +/// associated type is something other than the default `!`) then +/// [`FallibleTypeFolder`] should be implemented manually. Otherwise, /// a blanket implementation of [`FallibleTypeFolder`] will defer to /// the infallible methods of this trait to ensure that the two APIs /// are coherent. @@ -247,7 +248,7 @@ r.super_fold_with(self) } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> + fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> where Self: TypeFolder<'tcx, Error = !>, { @@ -269,11 +270,9 @@ } } -/// The `FallibleTypeFolder` trait defines the actual *folding*. There is a -/// method defined for every foldable type. Each of these has a -/// default implementation that does an "identity" fold. Within each -/// identity fold, it should invoke `foo.try_fold_with(self)` to fold each -/// sub-item. +/// This trait is implemented for every folding traversal. There is a fold +/// method defined for every type of interest. Each such method has a default +/// that does an "identity" fold. /// /// A blanket implementation of this trait (that defers to the relevant /// method of [`TypeFolder`]) is provided for all infallible folders in @@ -294,10 +293,7 @@ r.try_super_fold_with(self) } - fn try_fold_const( - &mut self, - c: &'tcx ty::Const<'tcx>, - ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> { c.try_super_fold_with(self) } @@ -316,8 +312,8 @@ } } -// Blanket implementation of fallible trait for infallible folders -// delegates to infallible methods to prevent incoherence +// This blanket implementation of the fallible trait for infallible folders +// delegates to infallible methods to ensure coherence. impl<'tcx, F> FallibleTypeFolder<'tcx> for F where F: TypeFolder<'tcx, Error = !>, @@ -337,10 +333,7 @@ Ok(self.fold_region(r)) } - fn try_fold_const( - &mut self, - c: &'tcx ty::Const<'tcx>, - ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> { Ok(self.fold_const(c)) } @@ -359,19 +352,11 @@ } } +/// This trait is implemented for every visiting traversal. There is a visit +/// method defined for every type of interest. Each such method has a default +/// that recurses into the type's fields in a non-custom fashion. pub trait TypeVisitor<'tcx>: Sized { type BreakTy = !; - /// Supplies the `tcx` for an unevaluated anonymous constant in case its default substs - /// are not yet supplied. - /// - /// Returning `None` for this method is only recommended if the `TypeVisitor` - /// does not care about default anon const substs, as it ignores generic parameters, - /// and fetching the default substs would cause a query cycle. - /// - /// For visitors which return `None` we completely skip the default substs in `ty::Unevaluated::super_visit_with`. - /// This means that incorrectly returning `None` can very quickly lead to ICE or other critical bugs, so be careful and - /// try to return an actual `tcx` if possible. - fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>>; fn visit_binder<T: TypeFoldable<'tcx>>( &mut self, @@ -388,7 +373,7 @@ r.super_visit_with(self) } - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { c.super_visit_with(self) } @@ -408,7 +393,7 @@ where F: FnMut(Ty<'tcx>) -> Ty<'tcx>, G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>, - H: FnMut(&'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx>, + H: FnMut(ty::Const<'tcx>) -> ty::Const<'tcx>, { pub tcx: TyCtxt<'tcx>, pub ty_op: F, @@ -420,7 +405,7 @@ where F: FnMut(Ty<'tcx>) -> Ty<'tcx>, G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>, - H: FnMut(&'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx>, + H: FnMut(ty::Const<'tcx>) -> ty::Const<'tcx>, { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.tcx @@ -436,7 +421,7 @@ (self.lt_op)(r) } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { let ct = ct.super_fold_with(self); (self.ct_op)(ct) } @@ -488,8 +473,7 @@ value: &impl TypeFoldable<'tcx>, callback: impl FnMut(ty::Region<'tcx>) -> bool, ) -> bool { - struct RegionVisitor<'tcx, F> { - tcx: TyCtxt<'tcx>, + struct RegionVisitor<F> { /// The index of a binder *just outside* the things we have /// traversed. If we encounter a bound region bound by this /// binder or one outer to it, it appears free. Example: @@ -511,16 +495,12 @@ callback: F, } - impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<'tcx, F> + impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F> where F: FnMut(ty::Region<'tcx>) -> bool, { type BreakTy = (); - fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> { - Some(self.tcx) - } - fn visit_binder<T: TypeFoldable<'tcx>>( &mut self, t: &Binder<'tcx, T>, @@ -548,7 +528,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { // We're only interested in types involving regions - if ty.flags().intersects(TypeFlags::HAS_POTENTIAL_FREE_REGIONS) { + if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) { ty.super_visit_with(self) } else { ControlFlow::CONTINUE @@ -556,9 +536,7 @@ } } - value - .visit_with(&mut RegionVisitor { tcx: self, outer_index: ty::INNERMOST, callback }) - .is_break() + value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback }).is_break() } } @@ -642,7 +620,7 @@ fld_r: Option<&'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a)>, fld_t: Option<&'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a)>, - fld_c: Option<&'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx> + 'a)>, + fld_c: Option<&'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a)>, } impl<'a, 'tcx> BoundVarReplacer<'a, 'tcx> { @@ -650,7 +628,7 @@ tcx: TyCtxt<'tcx>, fld_r: Option<&'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a)>, fld_t: Option<&'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a)>, - fld_c: Option<&'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx> + 'a)>, + fld_c: Option<&'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a)>, ) -> Self { BoundVarReplacer { tcx, current_index: ty::INNERMOST, fld_r, fld_t, fld_c } } @@ -676,7 +654,7 @@ ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => { if let Some(fld_t) = self.fld_t.as_mut() { let ty = fld_t(bound_ty); - return ty::fold::shift_vars(self.tcx, &ty, self.current_index.as_u32()); + return ty::fold::shift_vars(self.tcx, ty, self.current_index.as_u32()); } } _ if t.has_vars_bound_at_or_above(self.current_index) => { @@ -709,14 +687,12 @@ r } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - match *ct { - ty::Const { val: ty::ConstKind::Bound(debruijn, bound_const), ty } - if debruijn == self.current_index => - { + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + match ct.val() { + ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => { if let Some(fld_c) = self.fld_c.as_mut() { - let ct = fld_c(bound_const, ty); - return ty::fold::shift_vars(self.tcx, &ct, self.current_index.as_u32()); + let ct = fld_c(bound_const, ct.ty()); + return ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32()); } } _ if ct.has_vars_bound_at_or_above(self.current_index) => { @@ -775,7 +751,7 @@ where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, G: FnMut(ty::BoundTy) -> Ty<'tcx>, - H: FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx>, + H: FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx>, T: TypeFoldable<'tcx>, { if !value.has_escaping_bound_vars() { @@ -800,7 +776,7 @@ where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>, G: FnMut(ty::BoundTy) -> Ty<'tcx>, - H: FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx>, + H: FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx>, T: TypeFoldable<'tcx>, { let mut region_map = BTreeMap::new(); @@ -853,7 +829,7 @@ )) }, |c, ty| { - self.mk_const(ty::Const { + self.mk_const(ty::ConstS { val: ty::ConstKind::Bound( ty::INNERMOST, ty::BoundVar::from_usize(c.as_usize() + bound_vars), @@ -897,7 +873,7 @@ where T: TypeFoldable<'tcx>, { - let mut collector = LateBoundRegionsCollector::new(self, just_constraint); + let mut collector = LateBoundRegionsCollector::new(just_constraint); let result = value.as_ref().skip_binder().visit_with(&mut collector); assert!(result.is_continue()); // should never have stopped early collector.regions @@ -964,11 +940,6 @@ impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> { type BreakTy = (); - fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> { - // Anonymous constants do not contain bound vars in their substs by default. - None - } - fn visit_binder<T: TypeFoldable<'tcx>>( &mut self, t: &Binder<'tcx, T>, @@ -980,7 +951,7 @@ } fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - if t.outer_exclusive_binder < self.binder_index + if t.outer_exclusive_binder() < self.binder_index || !self.visited.insert((self.binder_index, t)) { return ControlFlow::BREAK; @@ -1014,10 +985,10 @@ } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - match r { - ty::ReLateBound(index, br) if *index == self.binder_index => { + match *r { + ty::ReLateBound(index, br) if index == self.binder_index => { if self.bound_vars.len() <= br.var.as_usize() { - bug!("Not enough bound vars: {:?} not found in {:?}", *br, self.bound_vars); + bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars); } let list_var = self.bound_vars[br.var.as_usize()]; match list_var { @@ -1111,13 +1082,16 @@ } } - fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty } = *ct { + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.val() { if self.amount == 0 || debruijn < self.current_index { ct } else { let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_const(ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), ty }) + self.tcx.mk_const(ty::ConstS { + val: ty::ConstKind::Bound(debruijn, bound_ct), + ty: ct.ty(), + }) } } else { ct.super_fold_with(self) @@ -1130,9 +1104,9 @@ region: ty::Region<'tcx>, amount: u32, ) -> ty::Region<'tcx> { - match region { + match *region { ty::ReLateBound(debruijn, br) if amount > 0 => { - tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), *br)) + tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br)) } _ => region, } @@ -1183,11 +1157,6 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { type BreakTy = FoundEscapingVars; - fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> { - // Anonymous constants do not contain bound vars in their substs by default. - None - } - fn visit_binder<T: TypeFoldable<'tcx>>( &mut self, t: &Binder<'tcx, T>, @@ -1205,7 +1174,7 @@ // bound at `outer_index` or above (because // `outer_exclusive_binder` is always 1 higher than the // content in `t`). Therefore, `t` has some escaping vars. - if t.outer_exclusive_binder > self.outer_index { + if t.outer_exclusive_binder() > self.outer_index { ControlFlow::Break(FoundEscapingVars) } else { ControlFlow::CONTINUE @@ -1224,13 +1193,13 @@ } } - fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { + fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { // we don't have a `visit_infer_const` callback, so we have to // hook in here to catch this case (annoying...), but // otherwise we do want to remember to visit the rest of the // const, as it has types/regions embedded in a lot of other // places. - match ct.val { + match ct.val() { ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => { ControlFlow::Break(FoundEscapingVars) } @@ -1240,7 +1209,7 @@ #[inline] fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { - if predicate.inner.outer_exclusive_binder > self.outer_index { + if predicate.outer_exclusive_binder() > self.outer_index { ControlFlow::Break(FoundEscapingVars) } else { ControlFlow::CONTINUE @@ -1252,35 +1221,32 @@ struct FoundFlags; // FIXME: Optimize for checking for infer flags -struct HasTypeFlagsVisitor<'tcx> { - tcx: Option<TyCtxt<'tcx>>, +struct HasTypeFlagsVisitor { flags: ty::TypeFlags, } -impl<'tcx> std::fmt::Debug for HasTypeFlagsVisitor<'tcx> { +impl std::fmt::Debug for HasTypeFlagsVisitor { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.flags.fmt(fmt) } } -impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> { +impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { type BreakTy = FoundFlags; - fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> { - bug!("we shouldn't call this method as we manually look at ct substs"); - } #[inline] #[instrument(level = "trace")] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - let flags = t.flags(); - trace!(t.flags=?t.flags()); - if flags.intersects(self.flags) { + fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> { + debug!( + "HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", + t, + t.flags(), + self.flags + ); + if t.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { - match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) { - true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, t), - _ => ControlFlow::CONTINUE, - } + ControlFlow::CONTINUE } } @@ -1298,16 +1264,13 @@ #[inline] #[instrument(level = "trace")] - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { let flags = FlagComputation::for_const(c); trace!(r.flags=?flags); if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { - match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) { - true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, c), - _ => ControlFlow::CONTINUE, - } + ControlFlow::CONTINUE } } @@ -1319,128 +1282,30 @@ if flags.intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { - match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) { - true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, uv), - _ => ControlFlow::CONTINUE, - } + ControlFlow::CONTINUE } } #[inline] #[instrument(level = "trace")] fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { - let flags = predicate.inner.flags; - trace!(predicate.flags=?flags); - if flags.intersects(self.flags) { + debug!( + "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}", + predicate, + predicate.flags(), + self.flags + ); + if predicate.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { - match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) { - true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, predicate), - _ => ControlFlow::CONTINUE, - } - } - } -} - -struct UnknownConstSubstsVisitor<'tcx> { - tcx: TyCtxt<'tcx>, - flags: ty::TypeFlags, -} - -impl<'tcx> UnknownConstSubstsVisitor<'tcx> { - /// This is fairly cold and we don't want to - /// bloat the size of the `HasTypeFlagsVisitor`. - #[inline(never)] - pub fn search<T: TypeFoldable<'tcx>>( - visitor: &HasTypeFlagsVisitor<'tcx>, - v: T, - ) -> ControlFlow<FoundFlags> { - if visitor.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS) { - v.super_visit_with(&mut UnknownConstSubstsVisitor { - tcx: visitor.tcx.unwrap(), - flags: visitor.flags, - }) - } else { ControlFlow::CONTINUE } } } -impl<'tcx> TypeVisitor<'tcx> for UnknownConstSubstsVisitor<'tcx> { - type BreakTy = FoundFlags; - fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> { - bug!("we shouldn't call this method as we manually look at ct substs"); - } - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { - if t.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) { - t.super_visit_with(self) - } else { - ControlFlow::CONTINUE - } - } - - #[inline] - fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> { - if uv.substs_.is_none() { - self.tcx - .default_anon_const_substs(uv.def.did) - .visit_with(&mut HasTypeFlagsVisitor { tcx: Some(self.tcx), flags: self.flags }) - } else { - ControlFlow::CONTINUE - } - } - - #[inline] - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { - if predicate.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) { - predicate.super_visit_with(self) - } else { - ControlFlow::CONTINUE - } - } -} - -impl<'tcx> TyCtxt<'tcx> { - /// This is a HACK(const_generics) and should probably not be needed. - /// Might however be perf relevant, so who knows. - /// - /// FIXME(@lcnr): explain this function a bit more - pub fn expose_default_const_substs<T: TypeFoldable<'tcx>>(self, v: T) -> T { - v.fold_with(&mut ExposeDefaultConstSubstsFolder { tcx: self }) - } -} - -struct ExposeDefaultConstSubstsFolder<'tcx> { - tcx: TyCtxt<'tcx>, -} - -impl<'tcx> TypeFolder<'tcx> for ExposeDefaultConstSubstsFolder<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if ty.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) { - ty.super_fold_with(self) - } else { - ty - } - } - - fn fold_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { - if pred.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) { - pred.super_fold_with(self) - } else { - pred - } - } -} - /// Collects all the late-bound regions at the innermost binding level /// into a hash set. -struct LateBoundRegionsCollector<'tcx> { - tcx: TyCtxt<'tcx>, +struct LateBoundRegionsCollector { current_index: ty::DebruijnIndex, regions: FxHashSet<ty::BoundRegionKind>, @@ -1454,10 +1319,9 @@ just_constrained: bool, } -impl<'tcx> LateBoundRegionsCollector<'tcx> { - fn new(tcx: TyCtxt<'tcx>, just_constrained: bool) -> Self { +impl LateBoundRegionsCollector { + fn new(just_constrained: bool) -> Self { LateBoundRegionsCollector { - tcx, current_index: ty::INNERMOST, regions: Default::default(), just_constrained, @@ -1465,11 +1329,7 @@ } } -impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector<'tcx> { - fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> { - Some(self.tcx) - } - +impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { fn visit_binder<T: TypeFoldable<'tcx>>( &mut self, t: &Binder<'tcx, T>, @@ -1493,12 +1353,12 @@ t.super_visit_with(self) } - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { // if we are only looking for "constrained" region, we have to // ignore the inputs of an unevaluated const, as they may not appear // in the normalized form if self.just_constrained { - if let ty::ConstKind::Unevaluated(..) = c.val { + if let ty::ConstKind::Unevaluated(..) = c.val() { return ControlFlow::CONTINUE; } }
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 1c3a01e..0bd96f8 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -31,6 +31,13 @@ GenericParamDefKind::Const { .. } => ast::ParamKindOrd::Const, } } + + pub fn is_ty_or_const(&self) -> bool { + match self { + GenericParamDefKind::Lifetime => false, + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => true, + } + } } #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index 9f47ed8..00ce15b 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -6,6 +6,7 @@ use crate::ty; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::HashingControls; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_query_system::ich::StableHashingContext; use std::cell::RefCell; @@ -17,12 +18,12 @@ { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { thread_local! { - static CACHE: RefCell<FxHashMap<(usize, usize), Fingerprint>> = + static CACHE: RefCell<FxHashMap<(usize, usize, HashingControls), Fingerprint>> = RefCell::new(Default::default()); } let hash = CACHE.with(|cache| { - let key = (self.as_ptr() as usize, self.len()); + let key = (self.as_ptr() as usize, self.len(), hcx.hashing_controls()); if let Some(&hash) = cache.borrow().get(&key) { return hash; }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs b/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs index f31c7dd..c4ad698 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs
@@ -1,9 +1,8 @@ use crate::ty::context::TyCtxt; use crate::ty::{DefId, DefIdTree}; -use rustc_hir::CRATE_HIR_ID; +use rustc_span::def_id::CRATE_DEF_ID; use smallvec::SmallVec; use std::mem; -use std::sync::Arc; use DefIdForest::*; @@ -18,14 +17,13 @@ /// We store the minimal set of `DefId`s required to represent the whole set. If A and B are /// `DefId`s in the `DefIdForest`, and A is a parent of B, then only A will be stored. When this is /// used with `type_uninhabited_from`, there will very rarely be more than one `DefId` stored. -#[derive(Clone, HashStable, Debug)] -pub enum DefIdForest { +#[derive(Copy, Clone, HashStable, Debug)] +pub enum DefIdForest<'a> { Empty, Single(DefId), /// This variant is very rare. /// Invariant: >1 elements - /// We use `Arc` because this is used in the output of a query. - Multiple(Arc<[DefId]>), + Multiple(&'a [DefId]), } /// Tests whether a slice of roots contains a given DefId. @@ -34,21 +32,21 @@ slice.iter().any(|root_id| tcx.is_descendant_of(id, *root_id)) } -impl<'tcx> DefIdForest { +impl<'tcx> DefIdForest<'tcx> { /// Creates an empty forest. - pub fn empty() -> DefIdForest { + pub fn empty() -> DefIdForest<'tcx> { DefIdForest::Empty } /// Creates a forest consisting of a single tree representing the entire /// crate. #[inline] - pub fn full(tcx: TyCtxt<'tcx>) -> DefIdForest { - DefIdForest::from_id(tcx.hir().local_def_id(CRATE_HIR_ID).to_def_id()) + pub fn full() -> DefIdForest<'tcx> { + DefIdForest::from_id(CRATE_DEF_ID.to_def_id()) } /// Creates a forest containing a `DefId` and all its descendants. - pub fn from_id(id: DefId) -> DefIdForest { + pub fn from_id(id: DefId) -> DefIdForest<'tcx> { DefIdForest::Single(id) } @@ -61,11 +59,11 @@ } // Only allocates in the rare `Multiple` case. - fn from_slice(root_ids: &[DefId]) -> DefIdForest { - match root_ids { + fn from_vec(tcx: TyCtxt<'tcx>, root_ids: SmallVec<[DefId; 1]>) -> DefIdForest<'tcx> { + match &root_ids[..] { [] => Empty, [id] => Single(*id), - _ => DefIdForest::Multiple(root_ids.into()), + _ => DefIdForest::Multiple(tcx.arena.alloc_from_iter(root_ids)), } } @@ -88,15 +86,15 @@ } /// Calculate the intersection of a collection of forests. - pub fn intersection<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest + pub fn intersection<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest<'tcx> where - I: IntoIterator<Item = DefIdForest>, + I: IntoIterator<Item = DefIdForest<'tcx>>, { let mut iter = iter.into_iter(); let mut ret: SmallVec<[_; 1]> = if let Some(first) = iter.next() { SmallVec::from_slice(first.as_slice()) } else { - return DefIdForest::full(tcx); + return DefIdForest::full(); }; let mut next_ret: SmallVec<[_; 1]> = SmallVec::new(); @@ -114,13 +112,13 @@ mem::swap(&mut next_ret, &mut ret); next_ret.clear(); } - DefIdForest::from_slice(&ret) + DefIdForest::from_vec(tcx, ret) } /// Calculate the union of a collection of forests. - pub fn union<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest + pub fn union<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest<'tcx> where - I: IntoIterator<Item = DefIdForest>, + I: IntoIterator<Item = DefIdForest<'tcx>>, { let mut ret: SmallVec<[_; 1]> = SmallVec::new(); let mut next_ret: SmallVec<[_; 1]> = SmallVec::new(); @@ -142,6 +140,6 @@ mem::swap(&mut next_ret, &mut ret); next_ret.clear(); } - DefIdForest::from_slice(&ret) + DefIdForest::from_vec(tcx, ret) } }
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 77d82ee..f2682b8 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -3,7 +3,7 @@ use crate::ty; use crate::ty::context::TyCtxt; use crate::ty::TyKind::*; -use crate::ty::{AdtDef, FieldDef, Ty, TyS, VariantDef}; +use crate::ty::{AdtDef, FieldDef, Ty, VariantDef}; use crate::ty::{AdtKind, Visibility}; use crate::ty::{DefId, SubstsRef}; @@ -112,7 +112,7 @@ tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, - ) -> DefIdForest { + ) -> DefIdForest<'tcx> { // Non-exhaustive ADTs from other crates are always considered inhabited. if self.is_variant_list_non_exhaustive() && !self.did.is_local() { DefIdForest::empty() @@ -135,7 +135,7 @@ substs: SubstsRef<'tcx>, adt_kind: AdtKind, param_env: ty::ParamEnv<'tcx>, - ) -> DefIdForest { + ) -> DefIdForest<'tcx> { let is_enum = match adt_kind { // For now, `union`s are never considered uninhabited. // The precise semantics of inhabitedness with respect to unions is currently undecided. @@ -163,7 +163,7 @@ substs: SubstsRef<'tcx>, is_enum: bool, param_env: ty::ParamEnv<'tcx>, - ) -> DefIdForest { + ) -> DefIdForest<'tcx> { let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env); // FIXME(canndrew): Currently enum fields are (incorrectly) stored with // `Visibility::Invisible` so we need to override `self.vis` if we're @@ -184,14 +184,14 @@ } } -impl<'tcx> TyS<'tcx> { +impl<'tcx> Ty<'tcx> { /// Calculates the forest of `DefId`s from which this type is visibly uninhabited. fn uninhabited_from( - &'tcx self, + self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - ) -> DefIdForest { - tcx.type_uninhabited_from(param_env.and(self)) + ) -> DefIdForest<'tcx> { + tcx.type_uninhabited_from(param_env.and(self)).clone() } } @@ -199,13 +199,13 @@ pub(crate) fn type_uninhabited_from<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, -) -> DefIdForest { +) -> DefIdForest<'tcx> { let ty = key.value; let param_env = key.param_env; match *ty.kind() { Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env), - Never => DefIdForest::full(tcx), + Never => DefIdForest::full(), Tuple(ref tys) => DefIdForest::union( tcx,
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index eaa7ee8..99c595f 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -101,7 +101,7 @@ /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization. pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { let ty = tcx.type_of(self.def.def_id()); - tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty) + tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty) } /// Finds a crate that contains a monomorphization of this instance that @@ -642,7 +642,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { debug!("fold_ty: ty={:?}", ty); - match ty.kind { + match *ty.kind() { ty::Closure(def_id, substs) => { let polymorphized_substs = polymorphize( self.tcx,
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 196fe7c..6d4178c 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -10,7 +10,7 @@ use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; use rustc_session::{config::OptLevel, DataTypeKind, FieldInfo, SizeKind, VariantInfo}; -use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::call::{ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind, @@ -1310,7 +1310,10 @@ }, }; let mut abi = Abi::Aggregate { sized: true }; - if tag.value.size(dl) == size { + + // Without latter check aligned enums with custom discriminant values + // Would result in ICE see the issue #92464 for more info + if tag.value.size(dl) == size || variants.iter().all(|layout| layout.is_empty()) { abi = Abi::Scalar(tag); } else { // Try to use a ScalarPair for all tagged enums. @@ -1769,9 +1772,7 @@ // Ignore layouts that are done with non-empty environments or // non-monomorphic layouts, as the user only wants to see the stuff // resulting from the final codegen session. - if layout.ty.definitely_has_param_types_or_consts(self.tcx) - || !self.param_env.caller_bounds().is_empty() - { + if layout.ty.has_param_types_or_consts() || !self.param_env.caller_bounds().is_empty() { return; } @@ -1810,7 +1811,7 @@ let adt_kind = adt_def.adt_kind(); let adt_packed = adt_def.repr.pack.is_some(); - let build_variant_info = |n: Option<Ident>, flds: &[Symbol], layout: TyAndLayout<'tcx>| { + let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| { let mut min_size = Size::ZERO; let field_info: Vec<_> = flds .iter() @@ -1845,15 +1846,15 @@ if !adt_def.variants.is_empty() && layout.fields != FieldsShape::Primitive { debug!( "print-type-size `{:#?}` variant {}", - layout, adt_def.variants[index].ident + layout, adt_def.variants[index].name ); let variant_def = &adt_def.variants[index]; - let fields: Vec<_> = variant_def.fields.iter().map(|f| f.ident.name).collect(); + let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect(); record( adt_kind.into(), adt_packed, None, - vec![build_variant_info(Some(variant_def.ident), &fields, layout)], + vec![build_variant_info(Some(variant_def.name), &fields, layout)], ); } else { // (This case arises for *empty* enums; so give it @@ -1872,10 +1873,9 @@ .variants .iter_enumerated() .map(|(i, variant_def)| { - let fields: Vec<_> = - variant_def.fields.iter().map(|f| f.ident.name).collect(); + let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect(); build_variant_info( - Some(variant_def.ident), + Some(variant_def.name), &fields, layout.for_variant(self, i), ) @@ -1937,7 +1937,7 @@ let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env); match tail.kind() { ty::Param(_) | ty::Projection(_) => { - debug_assert!(tail.definitely_has_param_types_or_consts(tcx)); + debug_assert!(tail.has_param_types_or_consts()); Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) }) } _ => bug!( @@ -2776,17 +2776,20 @@ // [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md use SpecAbi::*; match abi { - C { unwind } | Stdcall { unwind } | System { unwind } | Thiscall { unwind } => { + C { unwind } + | System { unwind } + | Cdecl { unwind } + | Stdcall { unwind } + | Fastcall { unwind } + | Vectorcall { unwind } + | Thiscall { unwind } + | Aapcs { unwind } + | Win64 { unwind } + | SysV64 { unwind } => { unwind || (!tcx.features().c_unwind && tcx.sess.panic_strategy() == PanicStrategy::Unwind) } - Cdecl - | Fastcall - | Vectorcall - | Aapcs - | Win64 - | SysV64 - | PtxKernel + PtxKernel | Msp430Interrupt | X86Interrupt | AmdGpuKernel @@ -2813,14 +2816,14 @@ EfiApi => bug!("eficall abi should be selected elsewhere"), Stdcall { .. } => Conv::X86Stdcall, - Fastcall => Conv::X86Fastcall, - Vectorcall => Conv::X86VectorCall, + Fastcall { .. } => Conv::X86Fastcall, + Vectorcall { .. } => Conv::X86VectorCall, Thiscall { .. } => Conv::X86ThisCall, C { .. } => Conv::C, Unadjusted => Conv::C, - Win64 => Conv::X86_64Win64, - SysV64 => Conv::X86_64SysV, - Aapcs => Conv::ArmAapcs, + Win64 { .. } => Conv::X86_64Win64, + SysV64 { .. } => Conv::X86_64SysV, + Aapcs { .. } => Conv::ArmAapcs, CCmseNonSecureCall => Conv::CCmseNonSecureCall, PtxKernel => Conv::PtxKernel, Msp430Interrupt => Conv::Msp430Intr, @@ -2831,12 +2834,12 @@ Wasm => Conv::C, // These API constants ought to be more specific... - Cdecl => Conv::C, + Cdecl { .. } => Conv::C, } } /// Error produced by attempting to compute or adjust a `FnAbi`. -#[derive(Clone, Debug, HashStable)] +#[derive(Copy, Clone, Debug, HashStable)] pub enum FnAbiError<'tcx> { /// Error produced by a `layout_of` call, while computing `FnAbi` initially. Layout(LayoutError<'tcx>), @@ -3048,9 +3051,10 @@ layout: TyAndLayout<'tcx>, offset: Size, is_return: bool| { - // Booleans are always an i1 that needs to be zero-extended. + // Booleans are always a noundef i1 that needs to be zero-extended. if scalar.is_bool() { attrs.ext(ArgExtension::Zext); + attrs.set(ArgAttribute::NoUndef); return; } @@ -3075,6 +3079,11 @@ _ => pointee.size, }; + // `Box`, `&T`, and `&mut T` cannot be undef. + // Note that this only applies to the value of the pointer itself; + // this attribute doesn't make it UB for the pointed-to data to be undef. + attrs.set(ArgAttribute::NoUndef); + // `Box` pointer parameters never alias because ownership is transferred // `&mut` pointer parameters never alias other parameters, // or mutable global data
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 78ccfbd..f0b7f2a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -19,7 +19,8 @@ pub use generics::*; pub use vtable::*; -use crate::hir::exports::ExportMap; +use crate::metadata::ModChild; +use crate::middle::privacy::AccessLevels; use crate::mir::{Body, GeneratorLayout}; use crate::traits::{self, Reveal}; use crate::ty; @@ -27,7 +28,8 @@ use crate::ty::util::Discr; use rustc_ast as ast; use rustc_attr as attr; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; @@ -41,11 +43,9 @@ use rustc_span::{sym, Span}; use rustc_target::abi::Align; -use std::cmp::Ordering; -use std::collections::BTreeMap; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use std::ops::ControlFlow; -use std::{fmt, ptr, str}; +use std::{fmt, str}; pub use crate::ty::diagnostics::*; pub use rustc_type_ir::InferTy::*; @@ -56,10 +56,12 @@ pub use self::closure::{ is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo, CapturedPlace, ClosureKind, MinCaptureInformationMap, MinCaptureList, - RootVariableMinCaptureList, UpvarBorrow, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, - UpvarPath, CAPTURE_STRUCT_LOCAL, + RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath, + CAPTURE_STRUCT_LOCAL, }; -pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Unevaluated, ValTree}; +pub use self::consts::{ + Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, Unevaluated, ValTree, +}; pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt, @@ -118,27 +120,31 @@ // Data types +pub type RegisteredTools = FxHashSet<Ident>; + #[derive(Debug)] pub struct ResolverOutputs { pub definitions: rustc_hir::definitions::Definitions, pub cstore: Box<CrateStoreDyn>, pub visibilities: FxHashMap<LocalDefId, Visibility>, + pub access_levels: AccessLevels, pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>, pub maybe_unused_trait_imports: FxHashSet<LocalDefId>, pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, - pub export_map: ExportMap, + pub reexport_map: FxHashMap<LocalDefId, Vec<ModChild>>, pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>, /// Extern prelude entries. The value is `true` if the entry was introduced /// via `extern crate` item and not `--extern` option or compiler built-in. pub extern_prelude: FxHashMap<Symbol, bool>, pub main_def: Option<MainDefinition>, - pub trait_impls: BTreeMap<DefId, Vec<LocalDefId>>, + pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>, /// A list of proc macro LocalDefIds, written out in the order in which /// they are declared in the static array generated by proc_macro_harness. pub proc_macros: Vec<LocalDefId>, /// Mapping from ident span to path span for paths that don't exist as written, but that /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. pub confused_type_with_std_module: FxHashMap<Span, Span>, + pub registered_tools: RegisteredTools, } #[derive(Clone, Copy, Debug)] @@ -374,15 +380,32 @@ pub pos: usize, } +/// Represents a type. +/// +/// IMPORTANT: +/// - This is a very "dumb" struct (with no derives and no `impls`). +/// - Values of this type are always interned and thus unique, and are stored +/// as an `Interned<TyS>`. +/// - `Ty` (which contains a reference to a `Interned<TyS>`) or `Interned<TyS>` +/// should be used everywhere instead of `TyS`. In particular, `Ty` has most +/// of the relevant methods. +#[derive(PartialEq, Eq, PartialOrd, Ord)] #[allow(rustc::usage_of_ty_tykind)] -pub struct TyS<'tcx> { +crate struct TyS<'tcx> { /// This field shouldn't be used directly and may be removed in the future. - /// Use `TyS::kind()` instead. + /// Use `Ty::kind()` instead. kind: TyKind<'tcx>, + + /// This field provides fast access to information that is also contained + /// in `kind`. + /// /// This field shouldn't be used directly and may be removed in the future. - /// Use `TyS::flags()` instead. + /// Use `Ty::flags()` instead. flags: TypeFlags, + /// This field provides fast access to information that is also contained + /// in `kind`. + /// /// This is a kind of confusing thing: it stores the smallest /// binder such that /// @@ -403,51 +426,27 @@ outer_exclusive_binder: ty::DebruijnIndex, } -impl<'tcx> TyS<'tcx> { - /// A constructor used only for internal testing. - #[allow(rustc::usage_of_ty_tykind)] - pub fn make_for_test( - kind: TyKind<'tcx>, - flags: TypeFlags, - outer_exclusive_binder: ty::DebruijnIndex, - ) -> TyS<'tcx> { - TyS { kind, flags, outer_exclusive_binder } - } -} - // `TyS` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(TyS<'_>, 40); -impl<'tcx> Ord for TyS<'tcx> { - fn cmp(&self, other: &TyS<'tcx>) -> Ordering { - self.kind().cmp(other.kind()) - } -} +/// Use this rather than `TyS`, whenever possible. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[rustc_diagnostic_item = "Ty"] +#[cfg_attr(not(bootstrap), rustc_pass_by_value)] +pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>); -impl<'tcx> PartialOrd for TyS<'tcx> { - fn partial_cmp(&self, other: &TyS<'tcx>) -> Option<Ordering> { - Some(self.kind().cmp(other.kind())) - } -} +// Statics only used for internal testing. +pub static BOOL_TY: Ty<'static> = Ty(Interned::new_unchecked(&BOOL_TYS)); +static BOOL_TYS: TyS<'static> = TyS { + kind: ty::Bool, + flags: TypeFlags::empty(), + outer_exclusive_binder: DebruijnIndex::from_usize(0), +}; -impl<'tcx> PartialEq for TyS<'tcx> { - #[inline] - fn eq(&self, other: &TyS<'tcx>) -> bool { - ptr::eq(self, other) - } -} -impl<'tcx> Eq for TyS<'tcx> {} - -impl<'tcx> Hash for TyS<'tcx> { - fn hash<H: Hasher>(&self, s: &mut H) { - (self as *const TyS<'_>).hash(s) - } -} - -impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> { +impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Ty<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let ty::TyS { + let TyS { ref kind, // The other fields just provide fast access to information that is @@ -455,15 +454,12 @@ flags: _, outer_exclusive_binder: _, - } = *self; + } = self.0.0; kind.hash_stable(hcx, hasher); } } -#[rustc_diagnostic_item = "Ty"] -pub type Ty<'tcx> = &'tcx TyS<'tcx>; - impl ty::EarlyBoundRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). @@ -472,51 +468,50 @@ } } +/// Represents a predicate. +/// +/// See comments on `TyS`, which apply here too (albeit for +/// `PredicateS`/`Predicate` rather than `TyS`/`Ty`). #[derive(Debug)] -crate struct PredicateInner<'tcx> { +crate struct PredicateS<'tcx> { kind: Binder<'tcx, PredicateKind<'tcx>>, flags: TypeFlags, /// See the comment for the corresponding field of [TyS]. outer_exclusive_binder: ty::DebruijnIndex, } +// This type is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PredicateInner<'_>, 48); +static_assert_size!(PredicateS<'_>, 56); -#[derive(Clone, Copy, Lift)] -pub struct Predicate<'tcx> { - inner: &'tcx PredicateInner<'tcx>, -} - -impl<'tcx> PartialEq for Predicate<'tcx> { - fn eq(&self, other: &Self) -> bool { - // `self.kind` is always interned. - ptr::eq(self.inner, other.inner) - } -} - -impl Hash for Predicate<'_> { - fn hash<H: Hasher>(&self, s: &mut H) { - (self.inner as *const PredicateInner<'_>).hash(s) - } -} - -impl<'tcx> Eq for Predicate<'tcx> {} +/// Use this rather than `PredicateS`, whenever possible. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(not(bootstrap), rustc_pass_by_value)] +pub struct Predicate<'tcx>(Interned<'tcx, PredicateS<'tcx>>); impl<'tcx> Predicate<'tcx> { /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. #[inline] pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { - self.inner.kind + self.0.kind + } + + #[inline(always)] + pub fn flags(self) -> TypeFlags { + self.0.flags + } + + #[inline(always)] + pub fn outer_exclusive_binder(self) -> DebruijnIndex { + self.0.outer_exclusive_binder } /// Flips the polarity of a Predicate. /// /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. - pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> { + pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> { let kind = self - .inner - .kind + .kind() .map_bound(|kind| match kind { PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) => { Some(PredicateKind::Trait(TraitPredicate { @@ -536,14 +531,14 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let PredicateInner { + let PredicateS { ref kind, // The other fields just provide fast access to information that is // also contained in `kind`, so no need to hash them. flags: _, outer_exclusive_binder: _, - } = self.inner; + } = self.0.0; kind.hash_stable(hcx, hasher); } @@ -599,7 +594,7 @@ ConstEvaluatable(ty::Unevaluated<'tcx, ()>), /// Constants must be equal. The first component is the const that is expected. - ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>), + ConstEquate(Const<'tcx>, Const<'tcx>), /// Represents a type found in the environment that we can use for implied bounds. /// @@ -743,6 +738,17 @@ *param_env = param_env.with_constness(self.constness.and(param_env.constness())) } } + + /// Remap the constness of this predicate before emitting it for diagnostics. + pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { + // this is different to `remap_constness` that callees want to print this predicate + // in case of selection errors. `T: ~const Drop` bounds cannot end up here when the + // param_env is not const because we it is always satisfied in non-const contexts. + if let hir::Constness::NotConst = param_env.constness() { + self.constness = ty::BoundConstness::NotConst; + } + } + pub fn def_id(self) -> DefId { self.trait_ref.def_id } @@ -750,6 +756,11 @@ pub fn self_ty(self) -> Ty<'tcx> { self.trait_ref.self_ty() } + + #[inline] + pub fn is_const_if_const(self) -> bool { + self.constness == BoundConstness::ConstIfConst + } } impl<'tcx> PolyTraitPredicate<'tcx> { @@ -761,6 +772,19 @@ pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound(|trait_ref| trait_ref.self_ty()) } + + /// Remap the constness of this predicate before emitting it for diagnostics. + pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { + *self = self.map_bound(|mut p| { + p.remap_constness_diag(param_env); + p + }); + } + + #[inline] + pub fn is_const_if_const(self) -> bool { + self.skip_binder().is_const_if_const() + } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] @@ -792,6 +816,34 @@ } pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable)] +pub enum Term<'tcx> { + Ty(Ty<'tcx>), + Const(Const<'tcx>), +} + +impl<'tcx> From<Ty<'tcx>> for Term<'tcx> { + fn from(ty: Ty<'tcx>) -> Self { + Term::Ty(ty) + } +} + +impl<'tcx> From<Const<'tcx>> for Term<'tcx> { + fn from(c: Const<'tcx>) -> Self { + Term::Const(c) + } +} + +impl<'tcx> Term<'tcx> { + pub fn ty(&self) -> Option<Ty<'tcx>> { + if let Term::Ty(ty) = self { Some(*ty) } else { None } + } + pub fn ct(&self) -> Option<Const<'tcx>> { + if let Term::Const(c) = self { Some(*c) } else { None } + } +} + /// This kind of predicate has no *direct* correspondent in the /// syntax, but it roughly corresponds to the syntactic forms: /// @@ -808,7 +860,7 @@ #[derive(HashStable, TypeFoldable)] pub struct ProjectionPredicate<'tcx> { pub projection_ty: ProjectionTy<'tcx>, - pub ty: Ty<'tcx>, + pub term: Term<'tcx>, } pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; @@ -833,8 +885,8 @@ self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) } - pub fn ty(&self) -> Binder<'tcx, Ty<'tcx>> { - self.map_bound(|predicate| predicate.ty) + pub fn term(&self) -> Binder<'tcx, Term<'tcx>> { + self.map_bound(|predicate| predicate.term) } /// The `DefId` of the `TraitItem` for the associated type. @@ -1321,6 +1373,11 @@ self.packed.tag().constness } + #[inline] + pub fn is_const(self) -> bool { + self.packed.tag().constness == hir::Constness::Const + } + /// Construct a trait environment with no where-clauses in scope /// where the values of all `impl Trait` and other hidden types /// are revealed. This is suitable for monomorphized, post-typeck @@ -1415,7 +1472,7 @@ Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, Reveal::All => { - if value.is_known_global() { + if value.is_global() { ParamEnvAnd { param_env: self.without_caller_bounds(), value } } else { ParamEnvAnd { param_env: self, value } @@ -1436,6 +1493,7 @@ polarity: ty::ImplPolarity::Positive, }) } + #[inline] pub fn without_const(self) -> PolyTraitPredicate<'tcx> { self.with_constness(BoundConstness::NotConst) @@ -1502,8 +1560,7 @@ /// If this variant is a struct variant, then this is `None`. pub ctor_def_id: Option<DefId>, /// Variant or struct name. - #[stable_hasher(project(name))] - pub ident: Ident, + pub name: Symbol, /// Discriminant of this variant. pub discr: VariantDiscr, /// Fields of this variant. @@ -1532,7 +1589,7 @@ /// If someone speeds up attribute loading to not be a performance concern, they can /// remove this hack and use the constructor `DefId` everywhere. pub fn new( - ident: Ident, + name: Symbol, variant_did: Option<DefId>, ctor_def_id: Option<DefId>, discr: VariantDiscr, @@ -1544,9 +1601,9 @@ is_field_list_non_exhaustive: bool, ) -> Self { debug!( - "VariantDef::new(ident = {:?}, variant_did = {:?}, ctor_def_id = {:?}, discr = {:?}, + "VariantDef::new(name = {:?}, variant_did = {:?}, ctor_def_id = {:?}, discr = {:?}, fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})", - ident, variant_did, ctor_def_id, discr, fields, ctor_kind, adt_kind, parent_did, + name, variant_did, ctor_def_id, discr, fields, ctor_kind, adt_kind, parent_did, ); let mut flags = VariantFlags::NO_VARIANT_FLAGS; @@ -1561,7 +1618,7 @@ VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor_def_id, - ident, + name, discr, fields, ctor_kind, @@ -1580,6 +1637,11 @@ pub fn is_recovered(&self) -> bool { self.flags.intersects(VariantFlags::IS_RECOVERED) } + + /// Computes the `Ident` of this variant by looking up the `Span` + pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { + Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) + } } #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] @@ -1598,8 +1660,7 @@ #[derive(Debug, HashStable, TyEncodable, TyDecodable)] pub struct FieldDef { pub did: DefId, - #[stable_hasher(project(name))] - pub ident: Ident, + pub name: Symbol, pub vis: Visibility, } @@ -1774,6 +1835,11 @@ pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> { tcx.type_of(self.did).subst(tcx, subst) } + + /// Computes the `Ident` of this variant by looking up the `Span` + pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { + Ident::new(self.name, tcx.def_ident_span(self.did).unwrap()) + } } pub type Attributes<'tcx> = &'tcx [ast::Attribute]; @@ -1890,7 +1956,10 @@ } pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> { - variant.fields.iter().position(|field| self.hygienic_eq(ident, field.ident, variant.def_id)) + variant + .fields + .iter() + .position(|field| self.hygienic_eq(ident, field.ident(self), variant.def_id)) } /// Returns `true` if the impls are the same polarity and the trait either @@ -2069,8 +2138,7 @@ /// with the name of the crate containing the impl. pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> { if let Some(impl_did) = impl_did.as_local() { - let hir_id = self.hir().local_def_id_to_hir_id(impl_did); - Ok(self.hir().span(hir_id)) + Ok(self.def_span(impl_did)) } else { Err(self.crate_name(impl_did.krate)) } @@ -2117,7 +2185,7 @@ /// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<LocalDefId> { let def_id = def_id.as_local()?; - if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { + if let Node::Item(item) = tcx.hir().get_by_def_id(def_id) { if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { return match opaque_ty.origin { hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 84ab42a..808be44 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -34,8 +34,8 @@ /// Erase the regions in `value` and then fully normalize all the /// types found within. The result will also have regions erased. /// - /// This is appropriate to use only after type-check: it assumes - /// that normalization will succeed, for example. + /// This should only be used outside of type inference. For example, + /// it assumes that normalization will succeed. pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T where T: TypeFoldable<'tcx>, @@ -192,7 +192,7 @@ self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty() } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const() } @@ -244,13 +244,10 @@ } } - fn try_fold_const( - &mut self, - c: &'tcx ty::Const<'tcx>, - ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> { match self.try_normalize_generic_arg_after_erasing_regions(c.into()) { Ok(t) => Ok(t.expect_const()), - Err(_) => Err(NormalizationError::Const(*c)), + Err(_) => Err(NormalizationError::Const(c)), } }
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 94127a1..94cea50 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -66,7 +66,7 @@ predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, ) -> Result<Self::DynExistential, Self::Error>; - fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error>; + fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error>; fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error>; @@ -321,19 +321,11 @@ characteristic_def_id_of_type_cached(ty, &mut SsoHashSet::new()) } -impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::RegionKind { - type Output = P::Region; - type Error = P::Error; - fn print(&self, cx: P) -> Result<Self::Output, Self::Error> { - cx.print_region(self) - } -} - impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'_> { type Output = P::Region; type Error = P::Error; fn print(&self, cx: P) -> Result<Self::Output, Self::Error> { - cx.print_region(self) + cx.print_region(*self) } } @@ -341,7 +333,7 @@ type Output = P::Type; type Error = P::Error; fn print(&self, cx: P) -> Result<Self::Output, Self::Error> { - cx.print_type(self) + cx.print_type(*self) } } @@ -355,10 +347,10 @@ } } -impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::Const<'tcx> { +impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> { type Output = P::Const; type Error = P::Error; fn print(&self, cx: P) -> Result<Self::Output, Self::Error> { - cx.print_const(self) + cx.print_const(*self) } }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 47a9234..bf7370c 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,8 +1,9 @@ use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; -use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::ieee::{Double, Single}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::intern::Interned; use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; @@ -130,11 +131,13 @@ /// /// Regions not selected by the region highlight mode are presently /// unaffected. -#[derive(Copy, Clone, Default)] -pub struct RegionHighlightMode { +#[derive(Copy, Clone)] +pub struct RegionHighlightMode<'tcx> { + tcx: TyCtxt<'tcx>, + /// If enabled, when we see the selected region, use "`'N`" /// instead of the ordinary behavior. - highlight_regions: [Option<(ty::RegionKind, usize)>; 3], + highlight_regions: [Option<(ty::Region<'tcx>, usize)>; 3], /// If enabled, when printing a "free region" that originated from /// the given `ty::BoundRegionKind`, print it as "`'1`". Free regions that would ordinarily @@ -146,12 +149,20 @@ highlight_bound_region: Option<(ty::BoundRegionKind, usize)>, } -impl RegionHighlightMode { +impl<'tcx> RegionHighlightMode<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>) -> Self { + Self { + tcx, + highlight_regions: Default::default(), + highlight_bound_region: Default::default(), + } + } + /// If `region` and `number` are both `Some`, invokes /// `highlighting_region`. pub fn maybe_highlighting_region( &mut self, - region: Option<ty::Region<'_>>, + region: Option<ty::Region<'tcx>>, number: Option<usize>, ) { if let Some(k) = region { @@ -162,24 +173,24 @@ } /// Highlights the region inference variable `vid` as `'N`. - pub fn highlighting_region(&mut self, region: ty::Region<'_>, number: usize) { + pub fn highlighting_region(&mut self, region: ty::Region<'tcx>, number: usize) { let num_slots = self.highlight_regions.len(); let first_avail_slot = self.highlight_regions.iter_mut().find(|s| s.is_none()).unwrap_or_else(|| { bug!("can only highlight {} placeholders at a time", num_slots,) }); - *first_avail_slot = Some((*region, number)); + *first_avail_slot = Some((region, number)); } /// Convenience wrapper for `highlighting_region`. pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) { - self.highlighting_region(&ty::ReVar(vid), number) + self.highlighting_region(self.tcx.mk_region(ty::ReVar(vid)), number) } /// Returns `Some(n)` with the number to use for the given region, if any. fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> { self.highlight_regions.iter().find_map(|h| match h { - Some((r, n)) if r == region => Some(*n), + Some((r, n)) if *r == region => Some(*n), _ => None, }) } @@ -458,7 +469,7 @@ // that's public and whose identifier isn't `_`. let reexport = self .tcx() - .item_children(visible_parent) + .module_children(visible_parent) .iter() .filter(|child| child.res.opt_def_id() == Some(def_id)) .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore) @@ -595,7 +606,7 @@ ty::Infer(infer_ty) => { let verbose = self.tcx().sess.verbose(); if let ty::TyVar(ty_vid) = infer_ty { - if let Some(name) = self.infer_ty_name(ty_vid) { + if let Some(name) = self.ty_infer_name(ty_vid) { p!(write("{}", name)) } else { if verbose { @@ -671,8 +682,7 @@ p!("generator"); // FIXME(eddyb) should use `def_span`. if let Some(did) = did.as_local() { - let hir_id = self.tcx().hir().local_def_id_to_hir_id(did); - let span = self.tcx().hir().span(hir_id); + let span = self.tcx().def_span(did); p!(write( "@{}", // This may end up in stderr diagnostics but it may also be emitted @@ -708,11 +718,10 @@ p!(write("closure")); // FIXME(eddyb) should use `def_span`. if let Some(did) = did.as_local() { - let hir_id = self.tcx().hir().local_def_id_to_hir_id(did); if self.tcx().sess.opts.debugging_opts.span_free_formats { p!("@", print_def_path(did.to_def_id(), substs)); } else { - let span = self.tcx().hir().span(hir_id); + let span = self.tcx().def_span(did); p!(write( "@{}", // This may end up in stderr diagnostics but it may also be emitted @@ -745,14 +754,14 @@ p!("[", print(ty), "; "); if self.tcx().sess.verbose() { p!(write("{:?}", sz)); - } else if let ty::ConstKind::Unevaluated(..) = sz.val { + } else if let ty::ConstKind::Unevaluated(..) = sz.val() { // Do not try to evaluate unevaluated constants. If we are const evaluating an // array length anon const, rustc will (with debug assertions) print the // constant's path. Which will end up here again. p!("_"); - } else if let Some(n) = sz.val.try_to_bits(self.tcx().data_layout.pointer_size) { + } else if let Some(n) = sz.val().try_to_bits(self.tcx().data_layout.pointer_size) { p!(write("{}", n)); - } else if let ty::ConstKind::Param(param) = sz.val { + } else if let ty::ConstKind::Param(param) = sz.val() { p!(write("{}", param)); } else { p!("_"); @@ -801,7 +810,7 @@ let trait_ref = proj_ref.required_poly_trait_ref(self.tcx()); // Projection type entry -- the def-id for naming, and the ty. - let proj_ty = (proj_ref.projection_def_id(), proj_ref.ty()); + let proj_ty = (proj_ref.projection_def_id(), proj_ref.term()); self.insert_trait_and_projection( trait_ref, @@ -852,8 +861,10 @@ } p!(")"); - if !return_ty.skip_binder().is_unit() { - p!("-> ", print(return_ty)); + if let Term::Ty(ty) = return_ty.skip_binder() { + if !ty.is_unit() { + p!("-> ", print(return_ty)); + } } p!(write("{}", if paren_needed { ")" } else { "" })); @@ -904,23 +915,28 @@ first = false; } - for (assoc_item_def_id, ty) in assoc_items { + for (assoc_item_def_id, term) in assoc_items { if !first { p!(", "); } - p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).ident)); + p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).name)); - // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks - match ty.skip_binder().kind() { - ty::Projection(ty::ProjectionTy { item_def_id, .. }) - if Some(*item_def_id) == self.tcx().lang_items().generator_return() => - { - p!("[async output]") + match term.skip_binder() { + Term::Ty(ty) => { + // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks + if matches!( + ty.kind(), ty::Projection(ty::ProjectionTy { item_def_id, .. }) + if Some(*item_def_id) == self.tcx().lang_items().generator_return() + ) { + p!("[async output]") + } else { + p!(print(ty)) + } } - _ => { - p!(print(ty)) + Term::Const(c) => { + p!(print(c)); } - } + }; first = false; } @@ -945,8 +961,11 @@ fn insert_trait_and_projection( &mut self, trait_ref: ty::PolyTraitRef<'tcx>, - proj_ty: Option<(DefId, ty::Binder<'tcx, Ty<'tcx>>)>, - traits: &mut BTreeMap<ty::PolyTraitRef<'tcx>, BTreeMap<DefId, ty::Binder<'tcx, Ty<'tcx>>>>, + proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>, + traits: &mut BTreeMap< + ty::PolyTraitRef<'tcx>, + BTreeMap<DefId, ty::Binder<'tcx, Term<'tcx>>>, + >, fn_traits: &mut BTreeMap<ty::PolyTraitRef<'tcx>, OpaqueFnEntry<'tcx>>, ) { let trait_def_id = trait_ref.def_id(); @@ -996,7 +1015,11 @@ } } - fn infer_ty_name(&self, _: ty::TyVid) -> Option<String> { + fn ty_infer_name(&self, _: ty::TyVid) -> Option<String> { + None + } + + fn const_infer_name(&self, _: ty::ConstVid<'tcx>) -> Option<String> { None } @@ -1021,7 +1044,11 @@ let mut projections = predicates.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect(); - p!(pretty_fn_sig(&tys, false, proj.skip_binder().ty)); + p!(pretty_fn_sig( + &tys, + false, + proj.skip_binder().term.ty().expect("Return type was a const") + )); resugared = true; } } @@ -1041,7 +1068,7 @@ // Don't print `'_` if there's no unerased regions. let print_regions = args.iter().any(|arg| match arg.unpack() { - GenericArgKind::Lifetime(r) => *r != ty::ReErased, + GenericArgKind::Lifetime(r) => !r.is_erased(), _ => false, }); let mut args = args.iter().cloned().filter(|arg| match arg.unpack() { @@ -1125,13 +1152,13 @@ fn pretty_print_const( mut self, - ct: &'tcx ty::Const<'tcx>, + ct: ty::Const<'tcx>, print_ty: bool, ) -> Result<Self::Const, Self::Error> { define_scoped_cx!(self); if self.tcx().sess.verbose() { - p!(write("Const({:?}: {:?})", ct.val, ct.ty)); + p!(write("Const({:?}: {:?})", ct.val(), ct.ty())); return Ok(self); } @@ -1143,7 +1170,7 @@ write!(this, "_")?; Ok(this) }, - |this| this.print_type(ct.ty), + |this| this.print_type(ct.ty()), ": ", )?; } else { @@ -1152,37 +1179,45 @@ }}; } - match ct.val { - ty::ConstKind::Unevaluated(uv) => { - if let Some(promoted) = uv.promoted { - let substs = uv.substs_.unwrap(); - p!(print_value_path(uv.def.did, substs)); - p!(write("::{:?}", promoted)); - } else { - let tcx = self.tcx(); - match tcx.def_kind(uv.def.did) { - DefKind::Static | DefKind::Const | DefKind::AssocConst => { - p!(print_value_path(uv.def.did, uv.substs(tcx))) - } - _ => { - if uv.def.is_local() { - let span = tcx.def_span(uv.def.did); - if let Ok(snip) = tcx.sess.source_map().span_to_snippet(span) { - p!(write("{}", snip)) - } else { - print_underscore!() - } + match ct.val() { + ty::ConstKind::Unevaluated(ty::Unevaluated { + def, + substs, + promoted: Some(promoted), + }) => { + p!(print_value_path(def.did, substs)); + p!(write("::{:?}", promoted)); + } + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) => { + match self.tcx().def_kind(def.did) { + DefKind::Static | DefKind::Const | DefKind::AssocConst => { + p!(print_value_path(def.did, substs)) + } + _ => { + if def.is_local() { + let span = self.tcx().def_span(def.did); + if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { + p!(write("{}", snip)) } else { print_underscore!() } + } else { + print_underscore!() } } } } - ty::ConstKind::Infer(..) => print_underscore!(), + ty::ConstKind::Infer(infer_ct) => { + match infer_ct { + ty::InferConst::Var(ct_vid) + if let Some(name) = self.const_infer_name(ct_vid) => + p!(write("{}", name)), + _ => print_underscore!(), + } + } ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)), ty::ConstKind::Value(value) => { - return self.pretty_print_const_value(value, ct.ty, print_ty); + return self.pretty_print_const_value(value, ct.ty(), print_ty); } ty::ConstKind::Bound(debruijn, bound_var) => { @@ -1219,16 +1254,23 @@ // Byte strings (&[u8; N]) ty::Ref( _, - ty::TyS { - kind: - ty::Array( - ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. }, - ty::Const { - val: ty::ConstKind::Value(ConstValue::Scalar(int)), .. - }, - ), - .. - }, + Ty(Interned( + ty::TyS { + kind: + ty::Array( + Ty(Interned(ty::TyS { kind: ty::Uint(ty::UintTy::U8), .. }, _)), + ty::Const(Interned( + ty::ConstS { + val: ty::ConstKind::Value(ConstValue::Scalar(int)), + .. + }, + _, + )), + ), + .. + }, + _, + )), _, ) => match self.tcx().get_global_alloc(alloc_id) { Some(GlobalAlloc::Memory(alloc)) => { @@ -1386,7 +1428,7 @@ // Byte/string slices, printed as (byte) string literals. ( ConstValue::Slice { data, start, end }, - ty::Ref(_, ty::TyS { kind: ty::Slice(t), .. }, _), + ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Slice(t), .. }, _)), _), ) if *t == u8_type => { // The `inspect` here is okay since we checked the bounds, and there are // no relocations (we have an active slice reference here). We don't use @@ -1396,7 +1438,7 @@ } ( ConstValue::Slice { data, start, end }, - ty::Ref(_, ty::TyS { kind: ty::Str, .. }, _), + ty::Ref(_, Ty(Interned(ty::TyS { kind: ty::Str, .. }, _)), _), ) => { // The `inspect` here is okay since we checked the bounds, and there are no // relocations (we have an active `str` reference here). We don't use this @@ -1407,7 +1449,7 @@ Ok(self) } (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { - let n = n.val.try_to_bits(self.tcx().data_layout.pointer_size).unwrap(); + let n = n.val().try_to_bits(self.tcx().data_layout.pointer_size).unwrap(); // cast is ok because we already checked for pointer size (32 or 64 bit) above let range = AllocRange { start: offset, size: Size::from_bytes(n) }; @@ -1419,7 +1461,7 @@ // Aggregates, printed as array/tuple/struct/variant construction syntax. // - // NB: the `potentially_has_param_types_or_consts` check ensures that we can use + // NB: the `has_param_types_or_consts` check ensures that we can use // the `destructure_const` query with an empty `ty::ParamEnv` without // introducing ICEs (e.g. via `layout_of`) from missing bounds. // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized` @@ -1427,13 +1469,19 @@ // // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the // correct `ty::ParamEnv` to allow printing *all* constant values. - (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) - if !ty.potentially_has_param_types_or_consts() => - { - let contents = self.tcx().destructure_const( + (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => { + let Some(contents) = self.tcx().try_destructure_const( ty::ParamEnv::reveal_all() - .and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })), - ); + .and(self.tcx().mk_const(ty::ConstS { val: ty::ConstKind::Value(ct), ty })), + ) else { + // Fall back to debug pretty printing for invalid constants. + p!(write("{:?}", ct)); + if print_ty { + p!(": ", print(ty)); + } + return Ok(self); + }; + let fields = contents.fields.iter().copied(); match *ty.kind() { @@ -1475,7 +1523,7 @@ if !first { p!(", "); } - p!(write("{}: ", field_def.ident), print(field)); + p!(write("{}: ", field_def.name), print(field)); first = false; } p!(" }}"); @@ -1520,9 +1568,10 @@ binder_depth: usize, printed_type_count: usize, - pub region_highlight_mode: RegionHighlightMode, + pub region_highlight_mode: RegionHighlightMode<'tcx>, - pub name_resolver: Option<Box<&'a dyn Fn(ty::TyVid) -> Option<String>>>, + pub ty_infer_name_resolver: Option<Box<dyn Fn(ty::TyVid) -> Option<String> + 'a>>, + pub const_infer_name_resolver: Option<Box<dyn Fn(ty::ConstVid<'tcx>) -> Option<String> + 'a>>, } impl<'a, 'tcx, F> Deref for FmtPrinter<'a, 'tcx, F> { @@ -1550,8 +1599,9 @@ region_index: 0, binder_depth: 0, printed_type_count: 0, - region_highlight_mode: RegionHighlightMode::default(), - name_resolver: None, + region_highlight_mode: RegionHighlightMode::new(tcx), + ty_infer_name_resolver: None, + const_infer_name_resolver: None, })) } } @@ -1691,7 +1741,7 @@ self.pretty_print_dyn_existential(predicates) } - fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> { + fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> { self.pretty_print_const(ct, true) } @@ -1784,10 +1834,11 @@ self = print_prefix(self)?; // Don't print `'_` if there's no unerased regions. - let print_regions = args.iter().any(|arg| match arg.unpack() { - GenericArgKind::Lifetime(r) => *r != ty::ReErased, - _ => false, - }); + let print_regions = self.tcx.sess.verbose() + || args.iter().any(|arg| match arg.unpack() { + GenericArgKind::Lifetime(r) => !r.is_erased(), + _ => false, + }); let args = args.iter().cloned().filter(|arg| match arg.unpack() { GenericArgKind::Lifetime(_) => print_regions, _ => true, @@ -1805,8 +1856,12 @@ } impl<'tcx, F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { - fn infer_ty_name(&self, id: ty::TyVid) -> Option<String> { - self.0.name_resolver.as_ref().and_then(|func| func(id)) + fn ty_infer_name(&self, id: ty::TyVid) -> Option<String> { + self.0.ty_infer_name_resolver.as_ref().and_then(|func| func(id)) + } + + fn const_infer_name(&self, id: ty::ConstVid<'tcx>) -> Option<String> { + self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id)) } fn print_value_path( @@ -2044,7 +2099,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { let name = &mut self.name; let region = match *r { - ty::ReLateBound(_, br) => self.region_map.entry(br).or_insert_with(|| name(br)), + ty::ReLateBound(_, br) => *self.region_map.entry(br).or_insert_with(|| name(br)), ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => { // If this is an anonymous placeholder, don't rename. Otherwise, in some // async fns, we get a `for<'r> Send` bound @@ -2053,7 +2108,7 @@ _ => { // Index doesn't matter, since this is just for naming and these never get bound let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind }; - self.region_map.entry(br).or_insert_with(|| name(br)) + *self.region_map.entry(br).or_insert_with(|| name(br)) } } } @@ -2246,7 +2301,6 @@ T: TypeFoldable<'tcx>, { struct LateBoundRegionNameCollector<'a, 'tcx> { - tcx: TyCtxt<'tcx>, used_region_names: &'a mut FxHashSet<Symbol>, type_collector: SsoHashSet<Ty<'tcx>>, } @@ -2254,13 +2308,9 @@ impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> { type BreakTy = (); - fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> { - Some(self.tcx) - } - #[instrument(skip(self), level = "trace")] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - trace!("address: {:p}", r); + trace!("address: {:p}", r.0.0); if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r { self.used_region_names.insert(name); } else if let ty::RePlaceholder(ty::PlaceholderRegion { @@ -2288,7 +2338,6 @@ self.used_region_names.clear(); let mut collector = LateBoundRegionNameCollector { - tcx: self.tcx, used_region_names: &mut self.used_region_names, type_collector: SsoHashSet::new(), }; @@ -2358,7 +2407,7 @@ } // HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting. -impl fmt::Display for ty::RegionKind { +impl<'tcx> fmt::Display for ty::Region<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { self.print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?; @@ -2407,10 +2456,33 @@ } } +#[derive(Copy, Clone, TypeFoldable, Lift)] +pub struct TraitPredPrintModifiersAndPath<'tcx>(ty::TraitPredicate<'tcx>); + +impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl<'tcx> ty::TraitPredicate<'tcx> { + pub fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> { + TraitPredPrintModifiersAndPath(self) + } +} + +impl<'tcx> ty::PolyTraitPredicate<'tcx> { + pub fn print_modifiers_and_trait_path( + self, + ) -> ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>> { + self.map_bound(TraitPredPrintModifiersAndPath) + } +} + forward_display_to_print! { Ty<'tcx>, &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, - &'tcx ty::Const<'tcx>, + ty::Const<'tcx>, // HACK(eddyb) these are exhaustive instead of generic, // because `for<'tcx>` isn't possible yet. @@ -2421,6 +2493,7 @@ ty::Binder<'tcx, TraitRefPrintOnlyTraitName<'tcx>>, ty::Binder<'tcx, ty::FnSig<'tcx>>, ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, + ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>>, ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>, ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>, ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>, @@ -2449,8 +2522,8 @@ } ty::ExistentialProjection<'tcx> { - let name = cx.tcx().associated_item(self.item_def_id).ident; - p!(write("{} = ", name), print(self.ty)) + let name = cx.tcx().associated_item(self.item_def_id).name; + p!(write("{} = ", name), print(self.term)) } ty::ExistentialPredicate<'tcx> { @@ -2485,6 +2558,18 @@ p!(print_def_path(self.0.def_id, &[])); } + TraitPredPrintModifiersAndPath<'tcx> { + if let ty::BoundConstness::ConstIfConst = self.0.constness { + p!("~const ") + } + + if let ty::ImplPolarity::Negative = self.0.polarity { + p!("!") + } + + p!(print(self.0.trait_ref.print_only_trait_path())); + } + ty::ParamTy { p!(write("{}", self.name)) } @@ -2502,12 +2587,22 @@ } ty::TraitPredicate<'tcx> { - p!(print(self.trait_ref.self_ty()), ": ", - print(self.trait_ref.print_only_trait_path())) + p!(print(self.trait_ref.self_ty()), ": "); + if let ty::BoundConstness::ConstIfConst = self.constness { + p!("~const "); + } + p!(print(self.trait_ref.print_only_trait_path())) } ty::ProjectionPredicate<'tcx> { - p!(print(self.projection_ty), " == ", print(self.ty)) + p!(print(self.projection_ty), " == ", print(self.term)) + } + + ty::Term<'tcx> { + match self { + ty::Term::Ty(ty) => p!(print(ty)), + ty::Term::Const(c) => p!(print(c)), + } } ty::ProjectionTy<'tcx> { @@ -2547,7 +2642,7 @@ write("` implements the trait `{}`", kind)) } ty::PredicateKind::ConstEvaluatable(uv) => { - p!("the constant `", print_value_path(uv.def.did, uv.substs_.map_or(&[], |x| x)), "` can be evaluated") + p!("the constant `", print_value_path(uv.def.did, uv.substs), "` can be evaluated") } ty::PredicateKind::ConstEquate(c1, c2) => { p!("the constant `", print(c1), "` equals `", print(c2), "`") @@ -2602,7 +2697,7 @@ // Iterate external crate defs but be mindful about visibility while let Some(def) = queue.pop() { - for child in tcx.item_children(def).iter() { + for child in tcx.module_children(def).iter() { if !child.vis.is_public() { continue; } @@ -2615,7 +2710,9 @@ collect_fn(&child.ident, ns, def_id); } - if seen_defs.insert(def_id) { + if matches!(defkind, DefKind::Mod | DefKind::Enum | DefKind::Trait) + && seen_defs.insert(def_id) + { queue.push(def_id); } } @@ -2715,5 +2812,5 @@ has_fn_once: bool, fn_mut_trait_ref: Option<ty::PolyTraitRef<'tcx>>, fn_trait_ref: Option<ty::PolyTraitRef<'tcx>>, - return_ty: Option<ty::Binder<'tcx, Ty<'tcx>>>, + return_ty: Option<ty::Binder<'tcx, Term<'tcx>>>, }
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 3af1b3a..1688e59 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs
@@ -1,7 +1,7 @@ use crate::dep_graph; -use crate::hir::exports::Export; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintLevelMap; +use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use crate::middle::lib_features::LibFeatures; @@ -56,7 +56,6 @@ use rustc_attr as attr; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; -use std::collections::BTreeMap; use std::ops::Deref; use std::path::PathBuf; use std::sync::Arc; @@ -107,6 +106,12 @@ #[inline(always)] fn noop<T>(_: &T) {} +/// Helper to ensure that queries only return `Copy` types. +#[inline(always)] +fn copy<T: Copy>(x: &T) -> T { + *x +} + macro_rules! query_helper_param_ty { (DefId) => { impl IntoQueryParam<DefId> }; ($K:ty) => { $K }; @@ -244,7 +249,7 @@ let key = key.into_query_param(); opt_remap_env_constness!([$($modifiers)*][key]); - let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, Clone::clone); + let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, copy); let lookup = match cached { Ok(value) => return value, @@ -348,6 +353,13 @@ } } + impl<'a, P: Copy> IntoQueryParam<P> for &'a P { + #[inline(always)] + fn into_query_param(self) -> P { + *self + } + } + impl IntoQueryParam<DefId> for LocalDefId { #[inline(always)] fn into_query_param(self) -> DefId {
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 63ed318..7c57d42 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -7,7 +7,7 @@ use crate::mir::interpret::{get_slice_bytes, ConstValue, GlobalAlloc, Scalar}; use crate::ty::error::{ExpectedFound, TypeError}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, Term, Ty, TyCtxt, TypeFoldable}; use rustc_hir as ast; use rustc_hir::def_id::DefId; use rustc_span::DUMMY_SP; @@ -89,9 +89,9 @@ fn consts( &mut self, - a: &'tcx ty::Const<'tcx>, - b: &'tcx ty::Const<'tcx>, - ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>>; + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ty::Const<'tcx>>; fn binders<T>( &mut self, @@ -149,8 +149,8 @@ Some((ty_def_id, variances)) => { let variance = variances[i]; let variance_info = if variance == ty::Invariant { - let ty = - cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst)); + let ty = *cached_ty + .get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst)); ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() } } else { ty::VarianceDiagInfo::default() @@ -291,11 +291,11 @@ b.item_def_id, ))) } else { - let ty = relation.relate_with_variance( + let term = relation.relate_with_variance( ty::Invariant, ty::VarianceDiagInfo::default(), - a.ty, - b.ty, + a.term, + b.term, )?; let substs = relation.relate_with_variance( ty::Invariant, @@ -303,7 +303,7 @@ a.substs, b.substs, )?; - Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty }) + Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term }) } } } @@ -545,16 +545,16 @@ /// it. pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, - a: &'tcx ty::Const<'tcx>, - b: &'tcx ty::Const<'tcx>, -) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, +) -> RelateResult<'tcx, ty::Const<'tcx>> { debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b); let tcx = relation.tcx(); // FIXME(oli-obk): once const generics can have generic types, this assertion // will likely get triggered. Move to `normalize_erasing_regions` at that point. - let a_ty = tcx.erase_regions(a.ty); - let b_ty = tcx.erase_regions(b.ty); + let a_ty = tcx.erase_regions(a.ty()); + let b_ty = tcx.erase_regions(b.ty()); if a_ty != b_ty { relation.tcx().sess.delay_span_bug( DUMMY_SP, @@ -562,14 +562,14 @@ ); } - let eagerly_eval = |x: &'tcx ty::Const<'tcx>| x.eval(tcx, relation.param_env()); + let eagerly_eval = |x: ty::Const<'tcx>| x.eval(tcx, relation.param_env()); let a = eagerly_eval(a); let b = eagerly_eval(b); // Currently, the values that can be unified are primitive types, // and those that derive both `PartialEq` and `Eq`, corresponding // to structural-match types. - let is_match = match (a.val, b.val) { + let is_match = match (a.val(), b.val()) { (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => { // The caller should handle these cases! bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b) @@ -599,16 +599,16 @@ let substs = relation.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), - au.substs(tcx), - bu.substs(tcx), + au.substs, + bu.substs, )?; - return Ok(tcx.mk_const(ty::Const { + return Ok(tcx.mk_const(ty::ConstS { val: ty::ConstKind::Unevaluated(ty::Unevaluated { def: au.def, - substs_: Some(substs), + substs, promoted: au.promoted, }), - ty: a.ty, + ty: a.ty(), })); } _ => false, @@ -621,8 +621,8 @@ a_val: ConstValue<'tcx>, b_val: ConstValue<'tcx>, // FIXME(oli-obk): these arguments should go away with valtrees - a: &'tcx ty::Const<'tcx>, - b: &'tcx ty::Const<'tcx>, + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, // FIXME(oli-obk): this should just be `bool` with valtrees ) -> RelateResult<'tcx, bool> { let tcx = relation.tcx(); @@ -648,9 +648,9 @@ } (ConstValue::ByRef { alloc: alloc_a, .. }, ConstValue::ByRef { alloc: alloc_b, .. }) - if a.ty.is_ref() || b.ty.is_ref() => + if a.ty().is_ref() || b.ty().is_ref() => { - if a.ty.is_ref() && b.ty.is_ref() { + if a.ty().is_ref() && b.ty().is_ref() { alloc_a == alloc_b } else { false @@ -663,7 +663,7 @@ // Both the variant and each field have to be equal. if a_destructured.variant == b_destructured.variant { for (a_field, b_field) in iter::zip(a_destructured.fields, b_destructured.fields) { - relation.consts(a_field, b_field)?; + relation.consts(*a_field, *b_field)?; } true @@ -756,12 +756,12 @@ } } -impl<'tcx> Relate<'tcx> for &'tcx ty::Const<'tcx> { +impl<'tcx> Relate<'tcx> for ty::Const<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, - a: &'tcx ty::Const<'tcx>, - b: &'tcx ty::Const<'tcx>, - ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ty::Const<'tcx>> { relation.consts(a, b) } } @@ -833,6 +833,20 @@ } } +impl<'tcx> Relate<'tcx> for ty::Term<'tcx> { + fn relate<R: TypeRelation<'tcx>>( + relation: &mut R, + a: Self, + b: Self, + ) -> RelateResult<'tcx, Self> { + Ok(match (a, b) { + (Term::Ty(a), Term::Ty(b)) => relation.relate(a, b)?.into(), + (Term::Const(a), Term::Const(b)) => relation.relate(a, b)?.into(), + _ => return Err(TypeError::Mismatch), + }) + } +} + impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, @@ -841,7 +855,7 @@ ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> { Ok(ty::ProjectionPredicate { projection_ty: relation.relate(a.projection_ty, b.projection_ty)?, - ty: relation.relate(a.ty, b.ty)?, + term: relation.relate(a.term, b.term)?, }) } }
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 98b1a8b..e4691de 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -6,8 +6,9 @@ use crate::mir::ProjectionKind; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; -use crate::ty::{self, InferConst, Lift, Ty, TyCtxt}; +use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; +use rustc_hir as hir; use rustc_hir::def::Namespace; use rustc_hir::def_id::CRATE_DEF_INDEX; use rustc_index::vec::{Idx, IndexVec}; @@ -47,12 +48,6 @@ } } -impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "UpvarBorrow({:?}, {:?})", self.kind, self.region) - } -} - impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths(|| fmt::Display::fmt(self, f)) @@ -164,7 +159,7 @@ impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.ty) + write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term) } } @@ -191,7 +186,7 @@ write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind) } ty::PredicateKind::ConstEvaluatable(uv) => { - write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs_) + write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs) } ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2), ty::PredicateKind::TypeWellFormedFromEnv(ty) => { @@ -225,7 +220,6 @@ ::rustc_hir::def_id::DefId, ::rustc_hir::def_id::LocalDefId, ::rustc_hir::HirId, - ::rustc_hir::LlvmInlineAsmInner, ::rustc_hir::MatchSource, ::rustc_hir::Mutability, ::rustc_hir::Unsafety, @@ -260,6 +254,7 @@ crate::ty::UniverseIndex, crate::ty::Variance, ::rustc_span::Span, + ::rustc_errors::ErrorReported, } /////////////////////////////////////////////////////////////////////////// @@ -363,6 +358,16 @@ } } +impl<'a, 'tcx> Lift<'tcx> for Term<'a> { + type Lifted = ty::Term<'tcx>; + fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { + Some(match self { + Term::Ty(ty) => Term::Ty(tcx.lift(ty)?), + Term::Const(c) => Term::Const(tcx.lift(c)?), + }) + } +} + impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> { type Lifted = ty::TraitPredicate<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::TraitPredicate<'tcx>> { @@ -410,8 +415,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> { type Lifted = ty::ProjectionPredicate<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::ProjectionPredicate<'tcx>> { - tcx.lift((self.projection_ty, self.ty)) - .map(|(projection_ty, ty)| ty::ProjectionPredicate { projection_ty, ty }) + tcx.lift((self.projection_ty, self.term)) + .map(|(projection_ty, term)| ty::ProjectionPredicate { projection_ty, term }) } } @@ -420,7 +425,7 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { tcx.lift(self.substs).map(|substs| ty::ExistentialProjection { substs, - ty: tcx.lift(self.ty).expect("type must lift when substs do"), + term: tcx.lift(self.term).expect("type must lift when substs do"), item_def_id: self.item_def_id, }) } @@ -659,14 +664,6 @@ /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. -// -// Ideally, each type should invoke `folder.fold_foo(self)` and -// nothing else. In some cases, though, we haven't gotten around to -// adding methods on the `folder` yet, and thus the folding is -// hard-coded here. This is less-flexible, because folders cannot -// override the behavior, but there are a lot of random types and one -// can easily refactor the folding into the TypeFolder trait as -// needed. /// AdtDefs are basically the same as a DefId. impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { @@ -1074,7 +1071,7 @@ } fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - visitor.visit_ty(self) + visitor.visit_ty(*self) } } @@ -1108,12 +1105,12 @@ self, folder: &mut F, ) -> Result<Self, F::Error> { - let new = self.inner.kind.try_fold_with(folder)?; + let new = self.kind().try_fold_with(folder)?; Ok(folder.tcx().reuse_or_mk_predicate(self, new)) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - self.inner.kind.visit_with(visitor) + self.kind().visit_with(visitor) } fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { @@ -1121,11 +1118,11 @@ } fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { - self.inner.outer_exclusive_binder > binder + self.outer_exclusive_binder() > binder } fn has_type_flags(&self, flags: ty::TypeFlags) -> bool { - self.inner.flags.intersects(flags) + self.flags().intersects(flags) } } @@ -1155,15 +1152,15 @@ } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> { fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>( self, folder: &mut F, ) -> Result<Self, F::Error> { - let ty = self.ty.try_fold_with(folder)?; - let val = self.val.try_fold_with(folder)?; - if ty != self.ty || val != self.val { - Ok(folder.tcx().mk_const(ty::Const { ty, val })) + let ty = self.ty().try_fold_with(folder)?; + let val = self.val().try_fold_with(folder)?; + if ty != self.ty() || val != self.val() { + Ok(folder.tcx().mk_const(ty::ConstS { ty, val })) } else { Ok(self) } @@ -1174,12 +1171,12 @@ } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - self.ty.visit_with(visitor)?; - self.val.visit_with(visitor) + self.ty().visit_with(visitor)?; + self.val().visit_with(visitor) } fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - visitor.visit_const(self) + visitor.visit_const(*self) } } @@ -1232,7 +1229,7 @@ ) -> Result<Self, F::Error> { Ok(ty::Unevaluated { def: self.def, - substs_: Some(self.substs(folder.tcx()).try_fold_with(folder)?), + substs: self.substs.try_fold_with(folder)?, promoted: self.promoted, }) } @@ -1242,14 +1239,7 @@ } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - if let Some(tcx) = visitor.tcx_for_anon_const_substs() { - self.substs(tcx).visit_with(visitor) - } else if let Some(substs) = self.substs_ { - substs.visit_with(visitor) - } else { - debug!("ignoring default substs of `{:?}`", self.def); - ControlFlow::CONTINUE - } + self.substs.visit_with(visitor) } } @@ -1260,7 +1250,7 @@ ) -> Result<Self, F::Error> { Ok(ty::Unevaluated { def: self.def, - substs_: Some(self.substs(folder.tcx()).try_fold_with(folder)?), + substs: self.substs.try_fold_with(folder)?, promoted: self.promoted, }) } @@ -1270,13 +1260,16 @@ } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - if let Some(tcx) = visitor.tcx_for_anon_const_substs() { - self.substs(tcx).visit_with(visitor) - } else if let Some(substs) = self.substs_ { - substs.visit_with(visitor) - } else { - debug!("ignoring default substs of `{:?}`", self.def); - ControlFlow::CONTINUE - } + self.substs.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for hir::Constness { + fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> { + Ok(self) + } + + fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> { + ControlFlow::CONTINUE } }
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index c24a1d8..7c6d6ea 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -8,10 +8,13 @@ use crate::ty::fold::ValidateBoundVars; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::InferTy::{self, *}; -use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable}; -use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS}; +use crate::ty::{ + self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitor, +}; +use crate::ty::{DelaySpanBugEmitted, List, ParamEnv}; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; +use rustc_data_structures::intern::Interned; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::vec::Idx; @@ -21,8 +24,9 @@ use rustc_target::spec::abi; use std::borrow::Cow; use std::cmp::Ordering; +use std::fmt; use std::marker::PhantomData; -use std::ops::Range; +use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] @@ -74,10 +78,10 @@ } } -/// Defines the kinds of types. +/// Defines the kinds of types used by the type system. /// -/// N.B., if you change this, you'll probably want to change the corresponding -/// AST structure in `rustc_ast/src/ast.rs` as well. +/// Types written by the user start out as [hir::TyKind](rustc_hir::TyKind) and get +/// converted to this representation using `AstConv::ast_ty_to_ty`. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable, Debug)] #[derive(HashStable)] #[rustc_diagnostic_item = "TyKind"] @@ -100,10 +104,11 @@ /// Algebraic data types (ADT). For example: structures, enumerations and unions. /// - /// InternalSubsts here, possibly against intuition, *may* contain `Param`s. - /// That is, even after substitution it is possible that there are type - /// variables. This happens when the `Adt` corresponds to an ADT - /// definition and not a concrete use of it. + /// For example, the type `List<i32>` would be represented using the `AdtDef` + /// for `struct List<T>` and the substs `[i32]`. + /// + /// Note that generic parameters in fields only get lazily substituted + /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, substs))`. Adt(&'tcx AdtDef, SubstsRef<'tcx>), /// An unsized FFI type that is opaque to Rust. Written as `extern type T`. @@ -112,8 +117,8 @@ /// The pointee of a string slice. Written as `str`. Str, - /// An array with the given length. Written as `[T; n]`. - Array(Ty<'tcx>, &'tcx ty::Const<'tcx>), + /// An array with the given length. Written as `[T; N]`. + Array(Ty<'tcx>, ty::Const<'tcx>), /// The pointee of an array slice. Written as `[T]`. Slice(Ty<'tcx>), @@ -126,11 +131,12 @@ Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability), /// The anonymous type of a function declaration/definition. Each - /// function has a unique type, which is output (for a function - /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. + /// function has a unique type. + /// + /// For the function `fn foo() -> i32 { 3 }` this type would be + /// shown to the user as `fn() -> i32 {foo}`. /// /// For example the type of `bar` here: - /// /// ```rust /// fn foo() -> i32 { 1 } /// let bar = foo; // bar: fn() -> i32 {foo} @@ -139,6 +145,9 @@ /// A pointer to a function. Written as `fn() -> i32`. /// + /// Note that both functions and closures start out as either + /// [FnDef] or [Closure] which can be then be coerced to this variant. + /// /// For example the type of `bar` here: /// /// ```rust @@ -150,23 +159,48 @@ /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. Dynamic(&'tcx List<Binder<'tcx, ExistentialPredicate<'tcx>>>, ty::Region<'tcx>), - /// The anonymous type of a closure. Used to represent the type of - /// `|a| a`. + /// The anonymous type of a closure. Used to represent the type of `|a| a`. + /// + /// Closure substs contain both the - potentially substituted - generic parameters + /// of its parent and some synthetic parameters. See the documentation for + /// [ClosureSubsts] for more details. Closure(DefId, SubstsRef<'tcx>), /// The anonymous type of a generator. Used to represent the type of /// `|a| yield a`. + /// + /// For more info about generator substs, visit the documentation for + /// [GeneratorSubsts]. Generator(DefId, SubstsRef<'tcx>, hir::Movability), /// A type representing the types stored inside a generator. - /// This should only appear in GeneratorInteriors. + /// This should only appear as part of the [GeneratorSubsts]. + /// + /// Note that the captured variables for generators are stored separately + /// using a tuple in the same way as for closures. + /// + /// Unlike upvars, the witness can reference lifetimes from + /// inside of the generator itself. To deal with them in + /// the type of the generator, we convert them to higher ranked + /// lifetimes bound by the witness itself. + /// + /// Looking at the following example, the witness for this generator + /// may end up as something like `for<'a> [Vec<i32>, &'a Vec<i32>]`: + /// + /// ```rust + /// |a| { + /// let x = &vec![3]; + /// yield a; + /// yield x[0]; + /// } + /// ``` GeneratorWitness(Binder<'tcx, &'tcx List<Ty<'tcx>>>), /// The never type `!`. Never, /// A tuple type. For example, `(i32, bool)`. - /// Use `TyS::tuple_fields` to iterate over the field types. + /// Use `Ty::tuple_fields` to iterate over the field types. Tuple(SubstsRef<'tcx>), /// The projection of an associated type. For example, @@ -174,23 +208,44 @@ Projection(ProjectionTy<'tcx>), /// Opaque (`impl Trait`) type found in a return type. + /// /// The `DefId` comes either from /// * the `impl Trait` ast::Ty node, /// * or the `type Foo = impl Trait` declaration - /// The substitutions are for the generics of the function in question. - /// After typeck, the concrete type can be found in the `types` map. + /// + /// For RPIT the substitutions are for the generics of the function, + /// while for TAIT it is used for the generic parameters of the alias. + /// + /// During codegen, `tcx.type_of(def_id)` can be used to get the underlying type. Opaque(DefId, SubstsRef<'tcx>), /// A type parameter; for example, `T` in `fn f<T>(x: T) {}`. Param(ParamTy), - /// Bound type variable, used only when preparing a trait query. + /// Bound type variable, used to represent the `'a` in `for<'a> fn(&'a ())`. + /// + /// For canonical queries, we replace inference variables with bound variables, + /// so e.g. when checking whether `&'_ (): Trait<_>` holds, we canonicalize that to + /// `for<'a, T> &'a (): Trait<T>` and then convert the introduced bound variables + /// back to inference variables in a new inference context when inside of the query. + /// + /// See the `rustc-dev-guide` for more details about + /// [higher-ranked trait bounds][1] and [canonical queries][2]. + /// + /// [1]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html + /// [2]: https://rustc-dev-guide.rust-lang.org/traits/canonical-queries.html Bound(ty::DebruijnIndex, BoundTy), - /// A placeholder type - universally quantified higher-ranked type. + /// A placeholder type, used during higher ranked subtyping to instantiate + /// bound variables. Placeholder(ty::PlaceholderType), /// A type variable used during type checking. + /// + /// Similar to placeholders, inference variables also live in a universe to + /// correctly deal with higher ranked types. Though unlike placeholders, + /// that universe is stored in the `InferCtxt` instead of directly + /// inside of the type. Infer(InferTy), /// A placeholder for a type which could not be computed; this is @@ -231,7 +286,7 @@ /// in scope on the function that defined the closure, /// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This /// is rather hackily encoded via a scalar type. See -/// `TyS::to_opt_closure_kind` for details. +/// `Ty::to_opt_closure_kind` for details. /// - CS represents the *closure signature*, representing as a `fn()` /// type. For example, `fn(u32, u32) -> u32` would mean that the closure /// implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait @@ -1340,7 +1395,24 @@ } } -pub type Region<'tcx> = &'tcx RegionKind; +/// Use this rather than `TyKind`, whenever possible. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] +#[cfg_attr(not(bootstrap), rustc_pass_by_value)] +pub struct Region<'tcx>(pub Interned<'tcx, RegionKind>); + +impl<'tcx> Deref for Region<'tcx> { + type Target = RegionKind; + + fn deref(&self) -> &RegionKind { + &self.0.0 + } +} + +impl<'tcx> fmt::Debug for Region<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self.kind()) + } +} /// Representation of regions. Note that the NLL checker uses a distinct /// representation of regions. For this reason, it internally replaces all the @@ -1348,6 +1420,9 @@ /// to index into internal NLL data structures. See `rustc_const_eval::borrow_check` /// module for more information. /// +/// Note: operations are on the wrapper `Region` type, which is interned, +/// rather than this type. +/// /// ## The Region lattice within a given function /// /// In general, the region lattice looks like @@ -1464,11 +1539,11 @@ /// Static data that has an "infinite" lifetime. Top in the region lattice. ReStatic, - /// A region variable. Should not exist after typeck. + /// A region variable. Should not exist outside of type inference. ReVar(RegionVid), /// A placeholder region -- basically, the higher-ranked version of `ReFree`. - /// Should not exist after typeck. + /// Should not exist outside of type inference. RePlaceholder(ty::PlaceholderRegion), /// Empty lifetime is for data that is never accessed. We tag the @@ -1540,7 +1615,7 @@ pub struct ExistentialProjection<'tcx> { pub item_def_id: DefId, pub substs: SubstsRef<'tcx>, - pub ty: Ty<'tcx>, + pub term: Term<'tcx>, } pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>; @@ -1570,7 +1645,7 @@ item_def_id: self.item_def_id, substs: tcx.mk_substs_trait(self_ty, self.substs), }, - ty: self.ty, + term: self.term, } } @@ -1584,7 +1659,7 @@ Self { item_def_id: projection_predicate.projection_ty.item_def_id, substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]), - ty: projection_predicate.ty, + term: projection_predicate.term, } } } @@ -1604,64 +1679,83 @@ } /// Region utilities -impl RegionKind { +impl<'tcx> Region<'tcx> { + pub fn kind(self) -> RegionKind { + *self.0.0 + } + /// Is this region named by the user? - pub fn has_name(&self) -> bool { + pub fn has_name(self) -> bool { match *self { - RegionKind::ReEarlyBound(ebr) => ebr.has_name(), - RegionKind::ReLateBound(_, br) => br.kind.is_named(), - RegionKind::ReFree(fr) => fr.bound_region.is_named(), - RegionKind::ReStatic => true, - RegionKind::ReVar(..) => false, - RegionKind::RePlaceholder(placeholder) => placeholder.name.is_named(), - RegionKind::ReEmpty(_) => false, - RegionKind::ReErased => false, + ty::ReEarlyBound(ebr) => ebr.has_name(), + ty::ReLateBound(_, br) => br.kind.is_named(), + ty::ReFree(fr) => fr.bound_region.is_named(), + ty::ReStatic => true, + ty::ReVar(..) => false, + ty::RePlaceholder(placeholder) => placeholder.name.is_named(), + ty::ReEmpty(_) => false, + ty::ReErased => false, } } #[inline] - pub fn is_late_bound(&self) -> bool { + pub fn is_static(self) -> bool { + matches!(*self, ty::ReStatic) + } + + #[inline] + pub fn is_erased(self) -> bool { + matches!(*self, ty::ReErased) + } + + #[inline] + pub fn is_late_bound(self) -> bool { matches!(*self, ty::ReLateBound(..)) } #[inline] - pub fn is_placeholder(&self) -> bool { + pub fn is_placeholder(self) -> bool { matches!(*self, ty::RePlaceholder(..)) } #[inline] - pub fn bound_at_or_above_binder(&self, index: ty::DebruijnIndex) -> bool { + pub fn is_empty(self) -> bool { + matches!(*self, ty::ReEmpty(..)) + } + + #[inline] + pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { match *self { ty::ReLateBound(debruijn, _) => debruijn >= index, _ => false, } } - pub fn type_flags(&self) -> TypeFlags { + pub fn type_flags(self) -> TypeFlags { let mut flags = TypeFlags::empty(); match *self { ty::ReVar(..) => { - flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS; - flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_INFER; } ty::RePlaceholder(..) => { - flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS; - flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; } ty::ReEarlyBound(..) => { - flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS; - flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS; - flags = flags | TypeFlags::HAS_KNOWN_RE_PARAM; + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_RE_PARAM; } ty::ReFree { .. } => { - flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS; - flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; } ty::ReEmpty(_) | ty::ReStatic => { - flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_REGIONS; } ty::ReLateBound(..) => { flags = flags | TypeFlags::HAS_RE_LATE_BOUND; @@ -1695,8 +1789,8 @@ /// of the impl, and for all the other highlighted regions, it /// would return the `DefId` of the function. In other cases (not shown), this /// function might return the `DefId` of a closure. - pub fn free_region_binding_scope(&self, tcx: TyCtxt<'_>) -> DefId { - match self { + pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId { + match *self { ty::ReEarlyBound(br) => tcx.parent(br.def_id).unwrap(), ty::ReFree(fr) => fr.scope, _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), @@ -1705,19 +1799,19 @@ } /// Type utilities -impl<'tcx> TyS<'tcx> { +impl<'tcx> Ty<'tcx> { #[inline(always)] - pub fn kind(&self) -> &TyKind<'tcx> { - &self.kind + pub fn kind(self) -> &'tcx TyKind<'tcx> { + &self.0.0.kind } #[inline(always)] - pub fn flags(&self) -> TypeFlags { - self.flags + pub fn flags(self) -> TypeFlags { + self.0.0.flags } #[inline] - pub fn is_unit(&self) -> bool { + pub fn is_unit(self) -> bool { match self.kind() { Tuple(ref tys) => tys.is_empty(), _ => false, @@ -1725,32 +1819,32 @@ } #[inline] - pub fn is_never(&self) -> bool { + pub fn is_never(self) -> bool { matches!(self.kind(), Never) } #[inline] - pub fn is_primitive(&self) -> bool { + pub fn is_primitive(self) -> bool { self.kind().is_primitive() } #[inline] - pub fn is_adt(&self) -> bool { + pub fn is_adt(self) -> bool { matches!(self.kind(), Adt(..)) } #[inline] - pub fn is_ref(&self) -> bool { + pub fn is_ref(self) -> bool { matches!(self.kind(), Ref(..)) } #[inline] - pub fn is_ty_var(&self) -> bool { + pub fn is_ty_var(self) -> bool { matches!(self.kind(), Infer(TyVar(_))) } #[inline] - pub fn ty_vid(&self) -> Option<ty::TyVid> { + pub fn ty_vid(self) -> Option<ty::TyVid> { match self.kind() { &Infer(TyVar(vid)) => Some(vid), _ => None, @@ -1758,28 +1852,28 @@ } #[inline] - pub fn is_ty_infer(&self) -> bool { + pub fn is_ty_infer(self) -> bool { matches!(self.kind(), Infer(_)) } #[inline] - pub fn is_phantom_data(&self) -> bool { + pub fn is_phantom_data(self) -> bool { if let Adt(def, _) = self.kind() { def.is_phantom_data() } else { false } } #[inline] - pub fn is_bool(&self) -> bool { + pub fn is_bool(self) -> bool { *self.kind() == Bool } /// Returns `true` if this type is a `str`. #[inline] - pub fn is_str(&self) -> bool { + pub fn is_str(self) -> bool { *self.kind() == Str } #[inline] - pub fn is_param(&self, index: u32) -> bool { + pub fn is_param(self, index: u32) -> bool { match self.kind() { ty::Param(ref data) => data.index == index, _ => false, @@ -1787,7 +1881,7 @@ } #[inline] - pub fn is_slice(&self) -> bool { + pub fn is_slice(self) -> bool { match self.kind() { RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_) | Str), _ => false, @@ -1795,27 +1889,27 @@ } #[inline] - pub fn is_array(&self) -> bool { + pub fn is_array(self) -> bool { matches!(self.kind(), Array(..)) } #[inline] - pub fn is_simd(&self) -> bool { + pub fn is_simd(self) -> bool { match self.kind() { Adt(def, _) => def.repr.simd(), _ => false, } } - pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + pub fn sequence_element_type(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self.kind() { - Array(ty, _) | Slice(ty) => ty, - Str => tcx.mk_mach_uint(ty::UintTy::U8), + Array(ty, _) | Slice(ty) => *ty, + Str => tcx.types.u8, _ => bug!("`sequence_element_type` called on non-sequence value: {}", self), } } - pub fn simd_size_and_type(&self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { + pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { match self.kind() { Adt(def, substs) => { assert!(def.repr.simd(), "`simd_size_and_type` called on non-SIMD type"); @@ -1830,7 +1924,7 @@ // The way we evaluate the `N` in `[T; N]` here only works since we use // `simd_size_and_type` post-monomorphization. It will probably start to ICE // if we use it in generic code. See the `simd-array-trait` ui test. - (f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, f0_elem_ty) + (f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, *f0_elem_ty) } // Otherwise, the fields of this Adt are the SIMD components (and we assume they // all have the same type). @@ -1842,12 +1936,12 @@ } #[inline] - pub fn is_region_ptr(&self) -> bool { + pub fn is_region_ptr(self) -> bool { matches!(self.kind(), Ref(..)) } #[inline] - pub fn is_mutable_ptr(&self) -> bool { + pub fn is_mutable_ptr(self) -> bool { matches!( self.kind(), RawPtr(TypeAndMut { mutbl: hir::Mutability::Mut, .. }) @@ -1857,7 +1951,7 @@ /// Get the mutability of the reference or `None` when not a reference #[inline] - pub fn ref_mutability(&self) -> Option<hir::Mutability> { + pub fn ref_mutability(self) -> Option<hir::Mutability> { match self.kind() { Ref(_, _, mutability) => Some(*mutability), _ => None, @@ -1865,18 +1959,18 @@ } #[inline] - pub fn is_unsafe_ptr(&self) -> bool { + pub fn is_unsafe_ptr(self) -> bool { matches!(self.kind(), RawPtr(_)) } /// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer). #[inline] - pub fn is_any_ptr(&self) -> bool { + pub fn is_any_ptr(self) -> bool { self.is_region_ptr() || self.is_unsafe_ptr() || self.is_fn_ptr() } #[inline] - pub fn is_box(&self) -> bool { + pub fn is_box(self) -> bool { match self.kind() { Adt(def, _) => def.is_box(), _ => false, @@ -1884,7 +1978,7 @@ } /// Panics if called on any type other than `Box<T>`. - pub fn boxed_ty(&self) -> Ty<'tcx> { + pub fn boxed_ty(self) -> Ty<'tcx> { match self.kind() { Adt(def, substs) if def.is_box() => substs.type_at(0), _ => bug!("`boxed_ty` is called on non-box type {:?}", self), @@ -1895,7 +1989,7 @@ /// (A RawPtr is scalar because it represents a non-managed pointer, so its /// contents are abstract to rustc.) #[inline] - pub fn is_scalar(&self) -> bool { + pub fn is_scalar(self) -> bool { matches!( self.kind(), Bool | Char @@ -1911,99 +2005,117 @@ /// Returns `true` if this type is a floating point type. #[inline] - pub fn is_floating_point(&self) -> bool { + pub fn is_floating_point(self) -> bool { matches!(self.kind(), Float(_) | Infer(FloatVar(_))) } #[inline] - pub fn is_trait(&self) -> bool { + pub fn is_trait(self) -> bool { matches!(self.kind(), Dynamic(..)) } #[inline] - pub fn is_enum(&self) -> bool { + pub fn is_enum(self) -> bool { matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum()) } #[inline] - pub fn is_union(&self) -> bool { + pub fn is_union(self) -> bool { matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union()) } #[inline] - pub fn is_closure(&self) -> bool { + pub fn is_closure(self) -> bool { matches!(self.kind(), Closure(..)) } #[inline] - pub fn is_generator(&self) -> bool { + pub fn is_generator(self) -> bool { matches!(self.kind(), Generator(..)) } #[inline] - pub fn is_integral(&self) -> bool { + pub fn is_integral(self) -> bool { matches!(self.kind(), Infer(IntVar(_)) | Int(_) | Uint(_)) } #[inline] - pub fn is_fresh_ty(&self) -> bool { + pub fn is_fresh_ty(self) -> bool { matches!(self.kind(), Infer(FreshTy(_))) } #[inline] - pub fn is_fresh(&self) -> bool { + pub fn is_fresh(self) -> bool { matches!(self.kind(), Infer(FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_))) } #[inline] - pub fn is_char(&self) -> bool { + pub fn is_char(self) -> bool { matches!(self.kind(), Char) } #[inline] - pub fn is_numeric(&self) -> bool { + pub fn is_numeric(self) -> bool { self.is_integral() || self.is_floating_point() } #[inline] - pub fn is_signed(&self) -> bool { + pub fn is_signed(self) -> bool { matches!(self.kind(), Int(_)) } #[inline] - pub fn is_ptr_sized_integral(&self) -> bool { + pub fn is_ptr_sized_integral(self) -> bool { matches!(self.kind(), Int(ty::IntTy::Isize) | Uint(ty::UintTy::Usize)) } #[inline] - pub fn has_concrete_skeleton(&self) -> bool { + pub fn has_concrete_skeleton(self) -> bool { !matches!(self.kind(), Param(_) | Infer(_) | Error(_)) } + /// Checks whether a type recursively contains another type + /// + /// Example: `Option<()>` contains `()` + pub fn contains(self, other: Ty<'tcx>) -> bool { + struct ContainsTyVisitor<'tcx>(Ty<'tcx>); + + impl<'tcx> TypeVisitor<'tcx> for ContainsTyVisitor<'tcx> { + type BreakTy = (); + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { + if self.0 == t { ControlFlow::BREAK } else { t.super_visit_with(self) } + } + } + + let cf = self.visit_with(&mut ContainsTyVisitor(other)); + cf.is_break() + } + /// Returns the type and mutability of `*ty`. /// /// The parameter `explicit` indicates if this is an *explicit* dereference. /// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly. - pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> { + pub fn builtin_deref(self, explicit: bool) -> Option<TypeAndMut<'tcx>> { match self.kind() { Adt(def, _) if def.is_box() => { Some(TypeAndMut { ty: self.boxed_ty(), mutbl: hir::Mutability::Not }) } - Ref(_, ty, mutbl) => Some(TypeAndMut { ty, mutbl: *mutbl }), + Ref(_, ty, mutbl) => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }), RawPtr(mt) if explicit => Some(*mt), _ => None, } } /// Returns the type of `ty[i]`. - pub fn builtin_index(&self) -> Option<Ty<'tcx>> { + pub fn builtin_index(self) -> Option<Ty<'tcx>> { match self.kind() { - Array(ty, _) | Slice(ty) => Some(ty), + Array(ty, _) | Slice(ty) => Some(*ty), _ => None, } } - pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { + pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { match self.kind() { FnDef(def_id, substs) => tcx.fn_sig(*def_id).subst(tcx, substs), FnPtr(f) => *f, @@ -2019,22 +2131,22 @@ } #[inline] - pub fn is_fn(&self) -> bool { + pub fn is_fn(self) -> bool { matches!(self.kind(), FnDef(..) | FnPtr(_)) } #[inline] - pub fn is_fn_ptr(&self) -> bool { + pub fn is_fn_ptr(self) -> bool { matches!(self.kind(), FnPtr(_)) } #[inline] - pub fn is_impl_trait(&self) -> bool { + pub fn is_impl_trait(self) -> bool { matches!(self.kind(), Opaque(..)) } #[inline] - pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> { + pub fn ty_adt_def(self) -> Option<&'tcx AdtDef> { match self.kind() { Adt(adt, _) => Some(adt), _ => None, @@ -2043,7 +2155,7 @@ /// Iterates over tuple fields. /// Panics when called on anything but a tuple. - pub fn tuple_fields(&self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> { + pub fn tuple_fields(self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> { match self.kind() { Tuple(substs) => substs.iter().map(|field| field.expect_ty()), _ => bug!("tuple_fields called on non-tuple"), @@ -2052,7 +2164,7 @@ /// Get the `i`-th element of a tuple. /// Panics when called on anything but a tuple. - pub fn tuple_element_ty(&self, i: usize) -> Option<Ty<'tcx>> { + pub fn tuple_element_ty(self, i: usize) -> Option<Ty<'tcx>> { match self.kind() { Tuple(substs) => substs.iter().nth(i).map(|field| field.expect_ty()), _ => bug!("tuple_fields called on non-tuple"), @@ -2063,7 +2175,7 @@ // // FIXME: This requires the optimized MIR in the case of generators. #[inline] - pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> { + pub fn variant_range(self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> { match self.kind() { TyKind::Adt(adt, _) => Some(adt.variant_range()), TyKind::Generator(def_id, substs, _) => { @@ -2079,7 +2191,7 @@ // FIXME: This requires the optimized MIR in the case of generators. #[inline] pub fn discriminant_for_variant( - &self, + self, tcx: TyCtxt<'tcx>, variant_index: VariantIdx, ) -> Option<Discr<'tcx>> { @@ -2100,7 +2212,7 @@ } /// Returns the type of the discriminant of this type. - pub fn discriminant_ty(&'tcx self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match self.kind() { ty::Adt(adt, _) if adt.is_enum() => adt.repr.discr_type().to_ty(tcx), ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx), @@ -2143,9 +2255,12 @@ } /// Returns the type of metadata for (potentially fat) pointers to this type. - pub fn ptr_metadata_ty(&'tcx self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - // FIXME: should this normalize? - let tail = tcx.struct_tail_without_normalization(self); + pub fn ptr_metadata_ty( + self, + tcx: TyCtxt<'tcx>, + normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, + ) -> Ty<'tcx> { + let tail = tcx.struct_tail_with_normalize(self, normalize); match tail.kind() { // Sized types ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) @@ -2202,7 +2317,7 @@ /// to represent the closure kind, because it has not yet been /// inferred. Once upvar inference (in `rustc_typeck/src/check/upvar.rs`) /// is complete, that type variable will be unified. - pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> { + pub fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> { match self.kind() { Int(int_ty) => match int_ty { ty::IntTy::I8 => Some(ty::ClosureKind::Fn), @@ -2231,7 +2346,7 @@ /// bound such as `[_]: Copy`. A function with such a bound obviously never /// can be called, but that doesn't mean it shouldn't typecheck. This is why /// this method doesn't return `Option<bool>`. - pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool { + pub fn is_trivially_sized(self, tcx: TyCtxt<'tcx>) -> bool { match self.kind() { ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Uint(_)
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index a711811..7dccef5 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -6,6 +6,7 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; +use rustc_data_structures::intern::Interned; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; @@ -25,10 +26,13 @@ /// To reduce memory usage, a `GenericArg` is an interned pointer, /// with the lowest 2 bits being reserved for a tag to /// indicate the type (`Ty`, `Region`, or `Const`) it points to. +/// +/// Note: the `PartialEq`, `Eq` and `Hash` derives are only valid because `Ty`, +/// `Region` and `Const` are all interned. #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct GenericArg<'tcx> { ptr: NonZeroUsize, - marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::Const<'tcx>)>, + marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>, } const TAG_MASK: usize = 0b11; @@ -40,26 +44,27 @@ pub enum GenericArgKind<'tcx> { Lifetime(ty::Region<'tcx>), Type(Ty<'tcx>), - Const(&'tcx ty::Const<'tcx>), + Const(ty::Const<'tcx>), } impl<'tcx> GenericArgKind<'tcx> { + #[inline] fn pack(self) -> GenericArg<'tcx> { let (tag, ptr) = match self { GenericArgKind::Lifetime(lt) => { // Ensure we can use the tag bits. - assert_eq!(mem::align_of_val(lt) & TAG_MASK, 0); - (REGION_TAG, lt as *const _ as usize) + assert_eq!(mem::align_of_val(lt.0.0) & TAG_MASK, 0); + (REGION_TAG, lt.0.0 as *const ty::RegionKind as usize) } GenericArgKind::Type(ty) => { // Ensure we can use the tag bits. - assert_eq!(mem::align_of_val(ty) & TAG_MASK, 0); - (TYPE_TAG, ty as *const _ as usize) + assert_eq!(mem::align_of_val(ty.0.0) & TAG_MASK, 0); + (TYPE_TAG, ty.0.0 as *const ty::TyS<'tcx> as usize) } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. - assert_eq!(mem::align_of_val(ct) & TAG_MASK, 0); - (CONST_TAG, ct as *const _ as usize) + assert_eq!(mem::align_of_val(ct.0.0) & TAG_MASK, 0); + (CONST_TAG, ct.0.0 as *const ty::ConstS<'tcx> as usize) } }; @@ -90,19 +95,22 @@ } impl<'tcx> From<ty::Region<'tcx>> for GenericArg<'tcx> { + #[inline] fn from(r: ty::Region<'tcx>) -> GenericArg<'tcx> { GenericArgKind::Lifetime(r).pack() } } impl<'tcx> From<Ty<'tcx>> for GenericArg<'tcx> { + #[inline] fn from(ty: Ty<'tcx>) -> GenericArg<'tcx> { GenericArgKind::Type(ty).pack() } } -impl<'tcx> From<&'tcx ty::Const<'tcx>> for GenericArg<'tcx> { - fn from(c: &'tcx ty::Const<'tcx>) -> GenericArg<'tcx> { +impl<'tcx> From<ty::Const<'tcx>> for GenericArg<'tcx> { + #[inline] + fn from(c: ty::Const<'tcx>) -> GenericArg<'tcx> { GenericArgKind::Const(c).pack() } } @@ -111,11 +119,20 @@ #[inline] pub fn unpack(self) -> GenericArgKind<'tcx> { let ptr = self.ptr.get(); + // SAFETY: use of `Interned::new_unchecked` here is ok because these + // pointers were originally created from `Interned` types in `pack()`, + // and this is just going in the other direction. unsafe { match ptr & TAG_MASK { - REGION_TAG => GenericArgKind::Lifetime(&*((ptr & !TAG_MASK) as *const _)), - TYPE_TAG => GenericArgKind::Type(&*((ptr & !TAG_MASK) as *const _)), - CONST_TAG => GenericArgKind::Const(&*((ptr & !TAG_MASK) as *const _)), + REGION_TAG => GenericArgKind::Lifetime(ty::Region(Interned::new_unchecked( + &*((ptr & !TAG_MASK) as *const ty::RegionKind), + ))), + TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( + &*((ptr & !TAG_MASK) as *const ty::TyS<'tcx>), + ))), + CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( + &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), + ))), _ => intrinsics::unreachable(), } } @@ -132,7 +149,7 @@ } /// Unpack the `GenericArg` as a const when it is known certainly to be a const. - pub fn expect_const(self) -> &'tcx ty::Const<'tcx> { + pub fn expect_const(self) -> ty::Const<'tcx> { match self.unpack() { GenericArgKind::Const(c) => c, _ => bug!("expected a const, but found another kind"), @@ -180,8 +197,8 @@ } impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArg<'tcx> { - fn decode(d: &mut D) -> Result<GenericArg<'tcx>, D::Error> { - Ok(GenericArgKind::decode(d)?.pack()) + fn decode(d: &mut D) -> GenericArg<'tcx> { + GenericArgKind::decode(d).pack() } } @@ -275,10 +292,6 @@ } } - pub fn is_noop(&self) -> bool { - self.is_empty() - } - #[inline] pub fn types(&'a self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'a { self.iter() @@ -293,7 +306,7 @@ } #[inline] - pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = &'tcx ty::Const<'tcx>> + 'a { + pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = ty::Const<'tcx>> + 'a { self.iter().filter_map(|k| { if let GenericArgKind::Const(ct) = k.unpack() { Some(ct) } else { None } }) @@ -328,7 +341,7 @@ } #[inline] - pub fn const_at(&self, i: usize) -> &'tcx ty::Const<'tcx> { + pub fn const_at(&self, i: usize) -> ty::Const<'tcx> { if let GenericArgKind::Const(ct) = self[i].unpack() { ct } else { @@ -400,15 +413,7 @@ } } 0 => Ok(self), - _ => { - let params: SmallVec<[_; 8]> = - self.iter().map(|k| k.try_fold_with(folder)).collect::<Result<_, _>>()?; - if params[..] == self[..] { - Ok(self) - } else { - Ok(folder.tcx().intern_substs(¶ms)) - } - } + _ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_substs(v)), } } @@ -505,7 +510,7 @@ } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.potentially_needs_subst() { + if !t.needs_subst() { return t; } @@ -515,8 +520,8 @@ } } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - if let ty::ConstKind::Param(p) = c.val { + fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { + if let ty::ConstKind::Param(p) = c.val() { self.const_for_param(p, c) } else { c.super_fold_with(self) @@ -565,11 +570,7 @@ self.shift_vars_through_binders(ty) } - fn const_for_param( - &self, - p: ParamConst, - source_ct: &'tcx ty::Const<'tcx>, - ) -> &'tcx ty::Const<'tcx> { + fn const_for_param(&self, p: ParamConst, source_ct: ty::Const<'tcx>) -> ty::Const<'tcx> { // Look up the const in the substitutions. It really should be in there. let opt_ct = self.substs.get(p.index as usize).map(|k| k.unpack()); let ct = match opt_ct {
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 34d059f..8f4cc18 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -1,7 +1,7 @@ use crate::traits::specialization_graph; -use crate::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences}; +use crate::ty::fast_reject::{self, SimplifiedType, SimplifyParams}; use crate::ty::fold::TypeFoldable; -use crate::ty::{Ty, TyCtxt}; +use crate::ty::{Ident, Ty, TyCtxt}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::definitions::DefPathHash; @@ -44,6 +44,10 @@ /// The ICH of this trait's DefPath, cached here so it doesn't have to be /// recomputed all the time. pub def_path_hash: DefPathHash, + + /// List of functions from `#[rustc_must_implement_one_of]` attribute one of which + /// must be implemented. + pub must_implement_one_of: Option<Box<[Ident]>>, } /// Whether this trait is treated specially by the standard library @@ -87,6 +91,7 @@ skip_array_during_method_dispatch: bool, specialization_kind: TraitSpecializationKind, def_path_hash: DefPathHash, + must_implement_one_of: Option<Box<[Ident]>>, ) -> TraitDef { TraitDef { def_id, @@ -97,6 +102,7 @@ skip_array_during_method_dispatch, specialization_kind, def_path_hash, + must_implement_one_of, } } @@ -138,6 +144,21 @@ }); } + pub fn non_blanket_impls_for_ty( + self, + def_id: DefId, + self_ty: Ty<'tcx>, + ) -> impl Iterator<Item = DefId> + 'tcx { + let impls = self.trait_impls_of(def_id); + if let Some(simp) = fast_reject::simplify_type(self, self_ty, SimplifyParams::No) { + if let Some(impls) = impls.non_blanket_impls.get(&simp) { + return impls.iter().copied(); + } + } + + [].iter().copied() + } + /// Applies function to every impl that could possibly match the self type `self_ty` and returns /// the first non-none value. pub fn find_map_relevant_impl<T, F: FnMut(DefId) -> Option<T>>( @@ -166,9 +187,7 @@ // whose outer level is not a parameter or projection. Especially for things like // `T: Clone` this is incredibly useful as we would otherwise look at all the impls // of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on. - if let Some(simp) = - fast_reject::simplify_type(self, self_ty, SimplifyParams::Yes, StripReferences::No) - { + if let Some(simp) = fast_reject::simplify_type(self, self_ty, SimplifyParams::Yes) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { if let result @ Some(_) = f(impl_def_id) { @@ -191,7 +210,7 @@ pub fn all_impls(self, def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx { let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(def_id); - blanket_impls.iter().chain(non_blanket_impls.iter().map(|(_, v)| v).flatten()).cloned() + blanket_impls.iter().chain(non_blanket_impls.iter().flat_map(|(_, v)| v)).cloned() } } @@ -228,7 +247,7 @@ } if let Some(simplified_self_ty) = - fast_reject::simplify_type(tcx, impl_self_ty, SimplifyParams::No, StripReferences::No) + fast_reject::simplify_type(tcx, impl_self_ty, SimplifyParams::No) { impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); } else {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 6690655..92d9cb2 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs
@@ -5,16 +5,19 @@ use crate::ty::layout::IntegerExt; use crate::ty::query::TyCtxtAt; use crate::ty::subst::{GenericArgKind, Subst, SubstsRef}; -use crate::ty::TyKind::*; -use crate::ty::{self, DebruijnIndex, DefIdTree, List, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{ + self, Const, DebruijnIndex, DefIdTree, List, ReEarlyBound, Region, Ty, TyCtxt, TyKind::*, + TypeFoldable, +}; use rustc_apfloat::Float as _; use rustc_ast as ast; use rustc_attr::{self as attr, SignedInt, UnsignedInt}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_hir::def::DefKind; +use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_query_system::ich::NodeIdHashingMode; @@ -143,6 +146,37 @@ hasher.finish() } + pub fn res_generics_def_id(self, res: Res) -> Option<DefId> { + match res { + Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => { + Some(self.parent(def_id).and_then(|def_id| self.parent(def_id)).unwrap()) + } + Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => { + Some(self.parent(def_id).unwrap()) + } + // Other `DefKind`s don't have generics and would ICE when calling + // `generics_of`. + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Trait + | DefKind::OpaqueTy + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Fn + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Impl, + def_id, + ) => Some(def_id), + Res::Err => None, + _ => None, + } + } + pub fn has_error_field(self, ty: Ty<'tcx>) -> bool { if let ty::Adt(def, substs) = *ty.kind() { for field in def.all_fields() { @@ -192,7 +226,7 @@ pub fn struct_tail_with_normalize( self, mut ty: Ty<'tcx>, - normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>, + mut normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, ) -> Ty<'tcx> { let recursion_limit = self.recursion_limit(); for iteration in 0.. { @@ -389,15 +423,17 @@ let result = iter::zip(item_substs, impl_substs) .filter(|&(_, k)| { match k.unpack() { - GenericArgKind::Lifetime(&ty::RegionKind::ReEarlyBound(ref ebr)) => { + GenericArgKind::Lifetime(Region(Interned(ReEarlyBound(ref ebr), _))) => { !impl_generics.region_param(ebr, self).pure_wrt_drop } - GenericArgKind::Type(&ty::TyS { kind: ty::Param(ref pt), .. }) => { - !impl_generics.type_param(pt, self).pure_wrt_drop - } - GenericArgKind::Const(&ty::Const { - val: ty::ConstKind::Param(ref pc), .. - }) => !impl_generics.const_param(pc, self).pure_wrt_drop, + GenericArgKind::Type(Ty(Interned( + ty::TyS { kind: ty::Param(ref pt), .. }, + _, + ))) => !impl_generics.type_param(pt, self).pure_wrt_drop, + GenericArgKind::Const(Const(Interned( + ty::ConstS { val: ty::ConstKind::Param(ref pc), .. }, + _, + ))) => !impl_generics.const_param(pc, self).pure_wrt_drop, GenericArgKind::Lifetime(_) | GenericArgKind::Type(_) | GenericArgKind::Const(_) => { @@ -577,7 +613,7 @@ let substs = substs.fold_with(self); if !self.check_recursion || self.seen_opaque_tys.insert(def_id) { let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) { - Some(expanded_ty) => expanded_ty, + Some(expanded_ty) => *expanded_ty, None => { let generic_ty = self.tcx.type_of(def_id); let concrete_ty = generic_ty.subst(self.tcx, substs); @@ -606,7 +642,7 @@ } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Opaque(def_id, substs) = t.kind { + if let ty::Opaque(def_id, substs) = *t.kind() { self.expand_opaque_ty(def_id, substs).unwrap_or(t) } else if t.has_opaque_types() { t.super_fold_with(self) @@ -616,10 +652,10 @@ } } -impl<'tcx> ty::TyS<'tcx> { +impl<'tcx> Ty<'tcx> { /// Returns the maximum value for the given numeric type (including `char`s) /// or returns `None` if the type is not numeric. - pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> { + pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<Const<'tcx>> { let val = match self.kind() { ty::Int(_) | ty::Uint(_) => { let (size, signed) = int_size_and_signed(tcx, self); @@ -634,12 +670,12 @@ }), _ => None, }; - val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self))) + val.map(|v| Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self))) } /// Returns the minimum value for the given numeric type (including `char`s) /// or returns `None` if the type is not numeric. - pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<'tcx>> { + pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<Const<'tcx>> { let val = match self.kind() { ty::Int(_) | ty::Uint(_) => { let (size, signed) = int_size_and_signed(tcx, self); @@ -653,7 +689,7 @@ }), _ => None, }; - val.map(|v| ty::Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self))) + val.map(|v| Const::from_bits(tcx, v, ty::ParamEnv::empty().and(self))) } /// Checks whether values of this type `T` are *moved* or *copied* @@ -664,7 +700,7 @@ /// full requirements for the `Copy` trait (cc #29149) -- this /// winds up being reported as an error during NLL borrow check. pub fn is_copy_modulo_regions( - &'tcx self, + self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> bool { @@ -677,7 +713,7 @@ /// over-approximation in generic contexts, where one can have /// strange rules like `<T as Foo<'static>>::Bar: Sized` that /// actually carry lifetime requirements. - pub fn is_sized(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn is_sized(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { self.is_trivially_sized(tcx_at.tcx) || tcx_at.is_sized_raw(param_env.and(self)) } @@ -688,7 +724,7 @@ /// optimization as well as the rules around static values. Note /// that the `Freeze` trait is not exposed to end users and is /// effectively an implementation detail. - pub fn is_freeze(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn is_freeze(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self)) } @@ -696,7 +732,7 @@ /// /// Returning true means the type is known to be `Freeze`. Returning /// `false` means nothing -- could be `Freeze`, might not be. - fn is_trivially_freeze(&self) -> bool { + fn is_trivially_freeze(self) -> bool { match self.kind() { ty::Int(_) | ty::Uint(_) @@ -710,7 +746,7 @@ | ty::FnDef(..) | ty::Error(_) | ty::FnPtr(_) => true, - ty::Tuple(_) => self.tuple_fields().all(Self::is_trivially_freeze), + ty::Tuple(_) => self.tuple_fields().all(|f| Self::is_trivially_freeze(f)), ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_freeze(), ty::Adt(..) | ty::Bound(..) @@ -728,7 +764,7 @@ } /// Checks whether values of this type `T` implement the `Unpin` trait. - pub fn is_unpin(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn is_unpin(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { self.is_trivially_unpin() || tcx_at.is_unpin_raw(param_env.and(self)) } @@ -736,7 +772,7 @@ /// /// Returning true means the type is known to be `Unpin`. Returning /// `false` means nothing -- could be `Unpin`, might not be. - fn is_trivially_unpin(&self) -> bool { + fn is_trivially_unpin(self) -> bool { match self.kind() { ty::Int(_) | ty::Uint(_) @@ -750,7 +786,7 @@ | ty::FnDef(..) | ty::Error(_) | ty::FnPtr(_) => true, - ty::Tuple(_) => self.tuple_fields().all(Self::is_trivially_unpin), + ty::Tuple(_) => self.tuple_fields().all(|f| Self::is_trivially_unpin(f)), ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_unpin(), ty::Adt(..) | ty::Bound(..) @@ -776,7 +812,7 @@ /// /// Note that this method is used to check eligible types in unions. #[inline] - pub fn needs_drop(&'tcx self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { // Avoid querying in simple cases. match needs_drop_components(self, &tcx.data_layout) { Err(AlwaysRequiresDrop) => true, @@ -809,11 +845,7 @@ /// Note that this method is used to check for change in drop order for /// 2229 drop reorder migration analysis. #[inline] - pub fn has_significant_drop( - &'tcx self, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> bool { + pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { // Avoid querying in simple cases. match needs_drop_components(self, &tcx.data_layout) { Err(AlwaysRequiresDrop) => true, @@ -858,7 +890,7 @@ /// want to know whether a given call to `PartialEq::eq` will proceed structurally all the way /// down, you will need to use a type visitor. #[inline] - pub fn is_structural_eq_shallow(&'tcx self, tcx: TyCtxt<'tcx>) -> bool { + pub fn is_structural_eq_shallow(self, tcx: TyCtxt<'tcx>) -> bool { match self.kind() { // Look for an impl of both `PartialStructuralEq` and `StructuralEq`. Adt(..) => tcx.has_structural_eq_impls(self), @@ -893,19 +925,6 @@ } } - pub fn same_type(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - match (&a.kind(), &b.kind()) { - (&Adt(did_a, substs_a), &Adt(did_b, substs_b)) => { - if did_a != did_b { - return false; - } - - substs_a.types().zip(substs_b.types()).all(|(a, b)| Self::same_type(a, b)) - } - _ => a == b, - } - } - /// Peel off all reference types in this type until there are none left. /// /// This method is idempotent, i.e. `ty.peel_refs().peel_refs() == ty.peel_refs()`. @@ -916,16 +935,16 @@ /// - `&'a mut u8` -> `u8` /// - `&'a &'b u8` -> `u8` /// - `&'a *const &'b u8 -> *const &'b u8` - pub fn peel_refs(&'tcx self) -> Ty<'tcx> { + pub fn peel_refs(self) -> Ty<'tcx> { let mut ty = self; while let Ref(_, inner_ty, _) = ty.kind() { - ty = inner_ty; + ty = *inner_ty; } ty } - pub fn outer_exclusive_binder(&'tcx self) -> DebruijnIndex { - self.outer_exclusive_binder + pub fn outer_exclusive_binder(self) -> DebruijnIndex { + self.0.outer_exclusive_binder } } @@ -1006,11 +1025,11 @@ ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop), - ty::Slice(ty) => needs_drop_components(ty, target_layout), + ty::Slice(ty) => needs_drop_components(*ty, target_layout), ty::Array(elem_ty, size) => { - match needs_drop_components(elem_ty, target_layout) { + match needs_drop_components(*elem_ty, target_layout) { Ok(v) if v.is_empty() => Ok(v), - res => match size.val.try_to_bits(target_layout.pointer_size) { + res => match size.val().try_to_bits(target_layout.pointer_size) { // Arrays of size zero don't need drop, even if their element // type does. Some(0) => Ok(SmallVec::new()), @@ -1041,6 +1060,42 @@ } } +pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { + match *ty.kind() { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Infer(ty::IntVar(_)) + | ty::Infer(ty::FloatVar(_)) + | ty::Str + | ty::RawPtr(_) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Never + | ty::Foreign(_) => true, + + ty::Opaque(..) + | ty::Dynamic(..) + | ty::Error(_) + | ty::Bound(..) + | ty::Param(_) + | ty::Placeholder(_) + | ty::Projection(_) + | ty::Infer(_) => false, + + // Not trivial because they have components, and instead of looking inside, + // we'll just perform trait selection. + ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(_) | ty::Adt(..) => false, + + ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty), + + ty::Tuple(tys) => tys.iter().all(|ty| is_trivially_const_drop(ty.expect_ty())), + } +} + // Does the equivalent of // ``` // let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index ba5775f..ab70c15 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -2,7 +2,7 @@ //! WARNING: this does not keep track of the region depth. use crate::ty::subst::{GenericArg, GenericArgKind}; -use crate::ty::{self, TyCtxt}; +use crate::ty::{self, Ty}; use rustc_data_structures::sso::SsoHashSet; use smallvec::{self, SmallVec}; @@ -11,7 +11,6 @@ type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>; pub struct TypeWalker<'tcx> { - expose_default_const_substs: Option<TyCtxt<'tcx>>, stack: TypeWalkerStack<'tcx>, last_subtree: usize, pub visited: SsoHashSet<GenericArg<'tcx>>, @@ -26,13 +25,8 @@ /// It maintains a set of visited types and /// skips any types that are already there. impl<'tcx> TypeWalker<'tcx> { - fn new(expose_default_const_substs: Option<TyCtxt<'tcx>>, root: GenericArg<'tcx>) -> Self { - Self { - expose_default_const_substs, - stack: smallvec![root], - last_subtree: 1, - visited: SsoHashSet::new(), - } + pub fn new(root: GenericArg<'tcx>) -> Self { + Self { stack: smallvec![root], last_subtree: 1, visited: SsoHashSet::new() } } /// Skips the subtree corresponding to the last type @@ -61,7 +55,7 @@ let next = self.stack.pop()?; self.last_subtree = self.stack.len(); if self.visited.insert(next) { - push_inner(self.expose_default_const_substs, &mut self.stack, next); + push_inner(&mut self.stack, next); debug!("next: stack={:?}", self.stack); return Some(next); } @@ -80,8 +74,8 @@ /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize } /// [isize] => { [isize], isize } /// ``` - pub fn walk(self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> { - TypeWalker::new(Some(tcx), self) + pub fn walk(self) -> TypeWalker<'tcx> { + TypeWalker::new(self) } /// Iterator that walks the immediate children of `self`. Hence @@ -93,21 +87,16 @@ /// and skips any types that are already there. pub fn walk_shallow( self, - tcx: TyCtxt<'tcx>, visited: &mut SsoHashSet<GenericArg<'tcx>>, ) -> impl Iterator<Item = GenericArg<'tcx>> { let mut stack = SmallVec::new(); - push_inner(Some(tcx), &mut stack, self); + push_inner(&mut stack, self); stack.retain(|a| visited.insert(*a)); stack.into_iter() } } -impl<'tcx> super::TyS<'tcx> { - pub fn walk_ignoring_default_const_substs(&'tcx self) -> TypeWalker<'tcx> { - TypeWalker::new(None, self.into()) - } - +impl<'tcx> Ty<'tcx> { /// Iterator that walks `self` and any types reachable from /// `self`, in depth-first order. Note that just walks the types /// that appear in `self`, it does not descend into the fields of @@ -118,8 +107,8 @@ /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize } /// [isize] => { [isize], isize } /// ``` - pub fn walk(&'tcx self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> { - TypeWalker::new(Some(tcx), self.into()) + pub fn walk(self) -> TypeWalker<'tcx> { + TypeWalker::new(self.into()) } } @@ -129,11 +118,7 @@ /// known to be significant to any code, but it seems like the /// natural order one would expect (basically, the order of the /// types as they are written). -fn push_inner<'tcx>( - expose_default_const_substs: Option<TyCtxt<'tcx>>, - stack: &mut TypeWalkerStack<'tcx>, - parent: GenericArg<'tcx>, -) { +fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) { match parent.unpack() { GenericArgKind::Type(parent_ty) => match *parent_ty.kind() { ty::Bool @@ -172,7 +157,7 @@ stack.extend(obj.iter().rev().flat_map(|predicate| { let (substs, opt_ty) = match predicate.skip_binder() { ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), - ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.ty)), + ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.term)), ty::ExistentialPredicate::AutoTrait(_) => // Empty iterator { @@ -180,7 +165,10 @@ } }; - substs.iter().rev().chain(opt_ty.map(|ty| ty.into())) + substs.iter().rev().chain(opt_ty.map(|term| match term { + ty::Term::Ty(ty) => ty.into(), + ty::Term::Const(ct) => ct.into(), + })) })); } ty::Adt(_, substs) @@ -201,8 +189,8 @@ }, GenericArgKind::Lifetime(_) => {} GenericArgKind::Const(parent_ct) => { - stack.push(parent_ct.ty.into()); - match parent_ct.val { + stack.push(parent_ct.ty().into()); + match parent_ct.val() { ty::ConstKind::Infer(_) | ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) @@ -211,11 +199,7 @@ | ty::ConstKind::Error(_) => {} ty::ConstKind::Unevaluated(ct) => { - if let Some(tcx) = expose_default_const_substs { - stack.extend(ct.substs(tcx).iter().rev()); - } else if let Some(substs) = ct.substs_ { - stack.extend(substs.iter().rev()); - } + stack.extend(ct.substs.iter().rev()); } } }