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 95d7273..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..49f8465 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());
}
}
}