summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle')
-rw-r--r--compiler/rustc_middle/Cargo.toml4
-rw-r--r--compiler/rustc_middle/messages.ftl (renamed from compiler/rustc_middle/locales/en-US.ftl)4
-rw-r--r--compiler/rustc_middle/src/arena.rs7
-rw-r--r--compiler/rustc_middle/src/dep_graph/mod.rs4
-rw-r--r--compiler/rustc_middle/src/error.rs8
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs54
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs37
-rw-r--r--compiler/rustc_middle/src/hir/place.rs4
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs24
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs37
-rw-r--r--compiler/rustc_middle/src/lib.rs4
-rw-r--r--compiler/rustc_middle/src/macros.rs2
-rw-r--r--compiler/rustc_middle/src/metadata.rs28
-rw-r--r--compiler/rustc_middle/src/middle/exported_symbols.rs5
-rw-r--r--compiler/rustc_middle/src/middle/mod.rs2
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs18
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs2
-rw-r--r--compiler/rustc_middle/src/mir/basic_blocks.rs6
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs28
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs330
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/init_mask/tests.rs195
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/tests.rs19
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs3
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs214
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs4
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs68
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs1
-rw-r--r--compiler/rustc_middle/src/mir/query.rs26
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs4
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs151
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs34
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs186
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs16
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs51
-rw-r--r--compiler/rustc_middle/src/query/erase.rs336
-rw-r--r--compiler/rustc_middle/src/query/keys.rs297
-rw-r--r--compiler/rustc_middle/src/query/mod.rs69
-rw-r--r--compiler/rustc_middle/src/thir.rs68
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs1
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs38
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs107
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs8
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs3
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs12
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs7
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs8
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs19
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs16
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs105
-rw-r--r--compiler/rustc_middle/src/ty/context/tls.rs59
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs10
-rw-r--r--compiler/rustc_middle/src/ty/error.rs8
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs104
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs2
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs23
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs2
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs55
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs115
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs219
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs35
-rw-r--r--compiler/rustc_middle/src/ty/query.rs140
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs32
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs15
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs201
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs4
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs81
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs16
-rw-r--r--compiler/rustc_middle/src/ty/util.rs100
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs3
-rw-r--r--compiler/rustc_middle/src/values.rs2
75 files changed, 2554 insertions, 1355 deletions
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index a2b78cc29..5b2ec9029 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -26,8 +26,8 @@ rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_query_system = { path = "../rustc_query_system" }
-rustc-rayon-core = { version = "0.4.0", optional = true }
-rustc-rayon = { version = "0.4.0", optional = true }
+rustc-rayon-core = { version = "0.5.0", optional = true }
+rustc-rayon = { version = "0.5.0", optional = true }
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_middle/locales/en-US.ftl b/compiler/rustc_middle/messages.ftl
index 4f4e5c6a2..bd9d89dee 100644
--- a/compiler/rustc_middle/locales/en-US.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -16,6 +16,10 @@ middle_limit_invalid =
`limit` must be a non-negative integer
.label = {$error_str}
+middle_recursion_limit_reached =
+ reached the recursion limit finding the struct tail for `{$ty}`
+ .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]`
+
middle_const_eval_non_int =
constant evaluation of enum discriminant resulted in non-integer
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 62e44b629..dd1e254f4 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -36,7 +36,7 @@ macro_rules! arena_types {
)>,
[] output_filenames: std::sync::Arc<rustc_session::config::OutputFilenames>,
[] metadata_loader: rustc_data_structures::steal::Steal<Box<rustc_session::cstore::MetadataLoaderDyn>>,
- [] crate_for_resolver: rustc_data_structures::steal::Steal<rustc_ast::ast::Crate>,
+ [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>,
[] resolutions: rustc_middle::ty::ResolverGlobalCtxt,
[decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
[decode] code_region: rustc_middle::mir::coverage::CodeRegion,
@@ -94,7 +94,8 @@ macro_rules! arena_types {
[] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation,
[] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>,
[decode] attribute: rustc_ast::Attribute,
- [] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>,
+ [] name_set: rustc_data_structures::unord::UnordSet<rustc_span::symbol::Symbol>,
+ [] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::symbol::Symbol>,
[] hir_id_set: rustc_hir::HirIdSet,
// Interned types
@@ -107,6 +108,7 @@ macro_rules! arena_types {
// (during lowering) and the `librustc_middle` arena (for decoding MIR)
[decode] asm_template: rustc_ast::InlineAsmTemplatePiece,
[decode] used_trait_imports: rustc_data_structures::unord::UnordSet<rustc_hir::def_id::LocalDefId>,
+ [decode] registered_tools: rustc_middle::ty::RegisteredTools,
[decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet<rustc_hir::ItemLocalId>,
[decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>,
@@ -117,6 +119,7 @@ macro_rules! arena_types {
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
[decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
[] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>),
+ [] mod_child: rustc_middle::metadata::ModChild,
]);
)
}
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index 84510fe21..0ddbe7d1c 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -94,7 +94,7 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
}
#[inline]
- fn dep_kind_info(&self, dep_kind: DepKind) -> &DepKindStruct<'tcx> {
- &self.query_kinds[dep_kind as usize]
+ fn dep_kind_info(&self, dk: DepKind) -> &DepKindStruct<'tcx> {
+ &self.query_kinds[dk as usize]
}
}
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 5e94da8cb..dc4aa1864 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -50,6 +50,14 @@ pub struct LimitInvalid<'a> {
}
#[derive(Diagnostic)]
+#[diag(middle_recursion_limit_reached)]
+#[help]
+pub struct RecursionLimitReached<'tcx> {
+ pub ty: Ty<'tcx>,
+ pub suggested_limit: rustc_session::Limit,
+}
+
+#[derive(Diagnostic)]
#[diag(middle_const_eval_non_int)]
pub struct ConstEvalNonIntError {
#[primary_span]
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 4b5bacac8..e551c76f8 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1,13 +1,14 @@
use crate::hir::{ModuleItems, Owner};
-use crate::ty::{DefIdTree, TyCtxt};
+use crate::query::LocalCrate;
+use crate::ty::TyCtxt;
use rustc_ast as ast;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::*;
use rustc_index::vec::Idx;
@@ -73,18 +74,17 @@ impl<'hir> Iterator for ParentHirIterator<'hir> {
if self.current_id == CRATE_HIR_ID {
return None;
}
- loop {
- // There are nodes that do not have entries, so we need to skip them.
- let parent_id = self.map.parent_id(self.current_id);
- if parent_id == self.current_id {
- self.current_id = CRATE_HIR_ID;
- return None;
- }
+ // There are nodes that do not have entries, so we need to skip them.
+ let parent_id = self.map.parent_id(self.current_id);
- self.current_id = parent_id;
- return Some(parent_id);
+ if parent_id == self.current_id {
+ self.current_id = CRATE_HIR_ID;
+ return None;
}
+
+ self.current_id = parent_id;
+ return Some(parent_id);
}
}
@@ -179,7 +179,19 @@ impl<'hir> Map<'hir> {
/// Do not call this function directly. The query should be called.
pub(super) 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)? {
+ let node = match self.find(hir_id) {
+ Some(node) => node,
+ None => match self.def_key(local_def_id).disambiguated_data.data {
+ // FIXME: Some anonymous constants do not have corresponding HIR nodes,
+ // so many local queries will panic on their def ids. `None` is currently
+ // returned here instead of `DefKind::{Anon,Inline}Const` to avoid such panics.
+ // Ideally all def ids should have `DefKind`s, we need to create the missing
+ // HIR nodes or feed relevant query results to achieve that.
+ DefPathData::AnonConst => return None,
+ _ => bug!("no HIR node for def id {local_def_id:?}"),
+ },
+ };
+ let def_kind = match node {
Node::Item(item) => match item.kind {
ItemKind::Static(_, mt, _) => DefKind::Static(mt),
ItemKind::Const(..) => DefKind::Const,
@@ -187,7 +199,7 @@ impl<'hir> Map<'hir> {
ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind),
ItemKind::Mod(..) => DefKind::Mod,
ItemKind::OpaqueTy(ref opaque) => {
- if opaque.in_trait {
+ if opaque.in_trait && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() {
DefKind::ImplTraitPlaceholder
} else {
DefKind::OpaqueTy
@@ -266,7 +278,10 @@ impl<'hir> Map<'hir> {
| Node::Param(_)
| Node::Arm(_)
| Node::Lifetime(_)
- | Node::Block(_) => return None,
+ | Node::Block(_) => span_bug!(
+ self.span(hir_id),
+ "unexpected node with def id {local_def_id:?}: {node:?}"
+ ),
};
Some(def_kind)
}
@@ -316,7 +331,7 @@ impl<'hir> Map<'hir> {
/// 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))
+ self.find(self.tcx.opt_local_def_id_to_hir_id(id)?)
}
/// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
@@ -333,7 +348,7 @@ impl<'hir> Map<'hir> {
}
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)))
+ id.as_local().and_then(|id| self.find(self.tcx.opt_local_def_id_to_hir_id(id)?))
}
pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> {
@@ -1131,10 +1146,9 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
}
}
-pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
- debug_assert_eq!(crate_num, LOCAL_CRATE);
+pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
let krate = tcx.hir_crate(());
- let hir_body_hash = krate.hir_hash;
+ let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash");
let upstream_crates = upstream_crates(tcx);
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index c9da711e5..7770a5e47 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -7,8 +7,7 @@ pub mod nested_filter;
pub mod place;
use crate::ty::query::Providers;
-use crate::ty::{DefIdTree, ImplSubject, TyCtxt};
-use rustc_data_structures::fingerprint::Fingerprint;
+use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -24,14 +23,15 @@ use rustc_span::{ExpnId, DUMMY_SP};
#[derive(Copy, Clone, Debug)]
pub struct Owner<'tcx> {
node: OwnerNode<'tcx>,
- hash_without_bodies: Fingerprint,
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Owner<'tcx> {
#[inline]
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
- let Owner { node: _, hash_without_bodies } = self;
- hash_without_bodies.hash_stable(hcx, hasher)
+ // Perform a shallow hash instead using the deep hash saved in `OwnerNodes`. This lets us
+ // differentiate queries that depend on the full HIR tree from those that only depend on
+ // the item signature.
+ hcx.without_hir_bodies(|hcx| self.node.hash_stable(hcx, hasher));
}
}
@@ -104,11 +104,11 @@ impl<'tcx> TyCtxt<'tcx> {
self.parent_module_from_def_id(id.owner.def_id)
}
- pub fn impl_subject(self, def_id: DefId) -> ImplSubject<'tcx> {
- self.impl_trait_ref(def_id)
- .map(|t| t.subst_identity())
- .map(ImplSubject::Trait)
- .unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id).subst_identity()))
+ pub fn impl_subject(self, def_id: DefId) -> EarlyBinder<ImplSubject<'tcx>> {
+ match self.impl_trait_ref(def_id) {
+ Some(t) => t.map_bound(ImplSubject::Trait),
+ None => self.type_of(def_id).map_bound(ImplSubject::Inherent),
+ }
}
}
@@ -123,7 +123,7 @@ pub fn provide(providers: &mut Providers) {
providers.hir_owner = |tcx, id| {
let owner = tcx.hir_crate(()).owners.get(id.def_id)?.as_owner()?;
let node = owner.node();
- Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies })
+ Some(Owner { node })
};
providers.opt_local_def_id_to_hir_id = |tcx, id| {
let owner = tcx.hir_crate(()).owners[id].map(|_| ());
@@ -147,18 +147,18 @@ pub fn provide(providers: &mut Providers) {
tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
};
providers.def_span = |tcx, def_id| {
- let def_id = def_id.expect_local();
+ let def_id = def_id;
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
tcx.hir().opt_span(hir_id).unwrap_or(DUMMY_SP)
};
providers.def_ident_span = |tcx, def_id| {
- let def_id = def_id.expect_local();
+ let def_id = def_id;
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
tcx.hir().opt_ident_span(hir_id)
};
providers.fn_arg_names = |tcx, id| {
let hir = tcx.hir();
- let def_id = id.expect_local();
+ let def_id = id;
let hir_id = hir.local_def_id_to_hir_id(def_id);
if let Some(body_id) = hir.maybe_body_owned_by(def_id) {
tcx.arena.alloc_from_iter(hir.body_param_names(body_id))
@@ -176,13 +176,10 @@ pub fn provide(providers: &mut Providers) {
span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
}
};
- providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
- providers.opt_rpitit_info = |_, _| None;
+ providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id);
providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
- providers.expn_that_defined = |tcx, id| {
- let id = id.expect_local();
- tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root())
- };
+ providers.expn_that_defined =
+ |tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root());
providers.in_scope_traits_map = |tcx, id| {
tcx.hir_crate(()).owners[id.def_id].as_owner().map(|owner_info| &owner_info.trait_map)
};
diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs
index 83d3b0100..80b4c964c 100644
--- a/compiler/rustc_middle/src/hir/place.rs
+++ b/compiler/rustc_middle/src/hir/place.rs
@@ -2,7 +2,7 @@ use crate::ty;
use crate::ty::Ty;
use rustc_hir::HirId;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{FieldIdx, VariantIdx};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
@@ -27,7 +27,7 @@ pub enum ProjectionKind {
/// the field. The field is identified by which variant
/// it appears in along with a field index. The variant
/// is used for enums.
- Field(u32, VariantIdx),
+ Field(FieldIdx, VariantIdx),
/// Some index like `B[x]`, where `B` is the base
/// expression. We don't preserve the index `x` because
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 7f8fc1774..b5b712c36 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -35,9 +35,9 @@ use std::ops::Index;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct Canonical<'tcx, V> {
+ pub value: V,
pub max_universe: ty::UniverseIndex,
pub variables: CanonicalVarInfos<'tcx>,
- pub value: V,
}
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
@@ -80,6 +80,18 @@ impl CanonicalVarValues<'_> {
}
})
}
+
+ pub fn is_identity_modulo_regions(&self) -> bool {
+ self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
+ ty::GenericArgKind::Lifetime(_) => true,
+ ty::GenericArgKind::Type(ty) => {
+ matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
+ }
+ ty::GenericArgKind::Const(ct) => {
+ matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
+ }
+ })
+ }
}
/// When we canonicalize a value to form a query, we wind up replacing
@@ -149,15 +161,15 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
}
}
- pub fn expect_anon_placeholder(self) -> u32 {
+ pub fn expect_placeholder_index(self) -> usize {
match self.kind {
CanonicalVarKind::Ty(_)
| CanonicalVarKind::Region(_)
| CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
- CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.name.expect_anon(),
- CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.name.expect_anon(),
- CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.name.as_u32(),
+ CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(),
+ CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(),
+ CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.as_usize(),
}
}
}
@@ -411,7 +423,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(i),
- kind: ty::BrAnon(i as u32, None),
+ kind: ty::BrAnon(None),
};
tcx.mk_re_late_bound(ty::INNERMOST, br).into()
}
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index 41d8c7ffd..a873854f0 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -1,4 +1,4 @@
-use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{self, Region, Ty, TyCtxt};
use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue};
use rustc_span::def_id::DefId;
use rustc_span::symbol::Symbol;
@@ -11,7 +11,20 @@ pub trait ToType {
}
#[derive(PartialEq, Copy, Clone, Debug)]
-pub struct UnifiedRegion<'tcx>(pub Option<ty::Region<'tcx>>);
+pub struct UnifiedRegion<'tcx> {
+ value: Option<ty::Region<'tcx>>,
+}
+
+impl<'tcx> UnifiedRegion<'tcx> {
+ pub fn new(value: Option<Region<'tcx>>) -> Self {
+ Self { value }
+ }
+
+ /// The caller is responsible for checking universe compatibility before using this value.
+ pub fn get_value_ignoring_universes(self) -> Option<Region<'tcx>> {
+ self.value
+ }
+}
#[derive(PartialEq, Copy, Clone, Debug)]
pub struct RegionVidKey<'tcx> {
@@ -44,11 +57,27 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
type Error = NoError;
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
- Ok(match (value1.0, value2.0) {
+ // We pick the value of the least universe because it is compatible with more variables.
+ // This is *not* necessary for soundness, but it allows more region variables to be
+ // resolved to the said value.
+ #[cold]
+ fn min_universe<'tcx>(r1: Region<'tcx>, r2: Region<'tcx>) -> Region<'tcx> {
+ cmp::min_by_key(r1, r2, |r| match r.kind() {
+ ty::ReStatic
+ | ty::ReErased
+ | ty::ReFree(..)
+ | ty::ReEarlyBound(..)
+ | ty::ReError(_) => ty::UniverseIndex::ROOT,
+ ty::RePlaceholder(placeholder) => placeholder.universe,
+ ty::ReVar(..) | ty::ReLateBound(..) => bug!("not a universal region"),
+ })
+ }
+
+ Ok(match (value1.value, value2.value) {
// Here we can just pick one value, because the full constraints graph
// will be handled later. Ideally, we might want a `MultipleValues`
// variant or something. For now though, this is fine.
- (Some(_), Some(_)) => *value1,
+ (Some(val1), Some(val2)) => Self { value: Some(min_universe(val1, val2)) },
(Some(_), _) => *value1,
(_, Some(_)) => *value2,
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index c33b9d84e..b4edb02f6 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -33,13 +33,13 @@
#![feature(generators)]
#![feature(get_mut_unchecked)]
#![feature(if_let_guard)]
+#![feature(inline_const)]
#![feature(iter_from_generator)]
#![feature(local_key_cell_methods)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(extern_types)]
#![feature(new_uninit)]
-#![feature(once_cell)]
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(trusted_len)]
@@ -109,4 +109,4 @@ pub mod util {
// Allows macros to refer to this crate as `::rustc_middle`
extern crate self as rustc_middle;
-fluent_messages! { "../locales/en-US.ftl" }
+fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index a8d71ce03..89014f62d 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -1,6 +1,6 @@
/// A macro for triggering an ICE.
/// Calling `bug` instead of panicking will result in a nicer error message and should
-/// therefore be prefered over `panic`/`unreachable` or others.
+/// therefore be preferred over `panic`/`unreachable` or others.
///
/// If you have a span available, you should use [`span_bug`] instead.
///
diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs
index 5ff014c78..f3170e0ec 100644
--- a/compiler/rustc_middle/src/metadata.rs
+++ b/compiler/rustc_middle/src/metadata.rs
@@ -5,13 +5,34 @@ use rustc_macros::HashStable;
use rustc_span::def_id::DefId;
use rustc_span::symbol::Ident;
use rustc_span::Span;
+use smallvec::SmallVec;
+
+/// A simplified version of `ImportKind` from resolve.
+/// `DefId`s here correspond to `use` and `extern crate` items themselves, not their targets.
+#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, HashStable)]
+pub enum Reexport {
+ Single(DefId),
+ Glob(DefId),
+ ExternCrate(DefId),
+ MacroUse,
+ MacroExport,
+}
+
+impl Reexport {
+ pub fn id(self) -> Option<DefId> {
+ match self {
+ Reexport::Single(id) | Reexport::Glob(id) | Reexport::ExternCrate(id) => Some(id),
+ Reexport::MacroUse | Reexport::MacroExport => None,
+ }
+ }
+}
/// 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)]
+#[derive(Debug, TyEncodable, TyDecodable, HashStable)]
pub struct ModChild {
/// Name of the item.
pub ident: Ident,
@@ -22,6 +43,7 @@ pub struct ModChild {
pub vis: ty::Visibility<DefId>,
/// Span of the item.
pub span: Span,
- /// A proper `macro_rules` item (not a reexport).
- pub macro_rules: bool,
+ /// Reexport chain linking this module child to its original reexported item.
+ /// Empty if the module child is a proper item.
+ pub reexport_chain: SmallVec<[Reexport; 2]>,
}
diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs
index 631fd09ec..c0c0fd07b 100644
--- a/compiler/rustc_middle/src/middle/exported_symbols.rs
+++ b/compiler/rustc_middle/src/middle/exported_symbols.rs
@@ -43,6 +43,7 @@ pub enum ExportedSymbol<'tcx> {
NonGeneric(DefId),
Generic(DefId, SubstsRef<'tcx>),
DropGlue(Ty<'tcx>),
+ ThreadLocalShim(DefId),
NoDefId(ty::SymbolName<'tcx>),
}
@@ -58,6 +59,10 @@ impl<'tcx> ExportedSymbol<'tcx> {
ExportedSymbol::DropGlue(ty) => {
tcx.symbol_name(ty::Instance::resolve_drop_in_place(tcx, ty))
}
+ ExportedSymbol::ThreadLocalShim(def_id) => tcx.symbol_name(ty::Instance {
+ def: ty::InstanceDef::ThreadLocalShim(def_id),
+ substs: ty::InternalSubsts::empty(),
+ }),
ExportedSymbol::NoDefId(symbol_name) => symbol_name,
}
}
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 0b6774f1b..9c25f3009 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -19,7 +19,7 @@ pub mod lib_features {
.stable
.iter()
.map(|(f, (s, _))| (*f, Some(*s)))
- .chain(self.unstable.iter().map(|(f, _)| (*f, None)))
+ .chain(self.unstable.keys().map(|f| (*f, None)))
.collect();
all_features.sort_unstable_by(|a, b| a.0.as_str().partial_cmp(b.0.as_str()).unwrap());
all_features
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 893bf54b8..967fed687 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -1,12 +1,12 @@
//! A pass that checks to make sure private fields and methods aren't used
//! outside their scopes. This pass will also generate a set of exported items
//! which are available for use externally when compiled as a library.
-use crate::ty::{DefIdTree, TyCtxt, Visibility};
+use crate::ty::{TyCtxt, Visibility};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
-use rustc_span::def_id::LocalDefId;
+use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID};
use std::hash::Hash;
/// Represents the levels of effective visibility an item can have.
@@ -107,12 +107,16 @@ impl EffectiveVisibilities {
})
}
+ pub fn update_root(&mut self) {
+ self.map.insert(CRATE_DEF_ID, EffectiveVisibility::from_vis(Visibility::Public));
+ }
+
// FIXME: Share code with `fn update`.
pub fn update_eff_vis(
&mut self,
def_id: LocalDefId,
eff_vis: &EffectiveVisibility,
- tree: impl DefIdTree,
+ tcx: TyCtxt<'_>,
) {
use std::collections::hash_map::Entry;
match self.map.entry(def_id) {
@@ -122,7 +126,7 @@ impl EffectiveVisibilities {
let vis_at_level = eff_vis.at_level(l);
let old_vis_at_level = old_eff_vis.at_level_mut(l);
if vis_at_level != old_vis_at_level
- && vis_at_level.is_at_least(*old_vis_at_level, tree)
+ && vis_at_level.is_at_least(*old_vis_at_level, tcx)
{
*old_vis_at_level = *vis_at_level
}
@@ -219,7 +223,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
lazy_private_vis: impl FnOnce() -> Visibility,
inherited_effective_vis: EffectiveVisibility,
level: Level,
- tree: impl DefIdTree,
+ tcx: TyCtxt<'_>,
) -> bool {
let mut changed = false;
let mut current_effective_vis = self
@@ -240,7 +244,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
&& level != l)
{
calculated_effective_vis =
- if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) {
+ if nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
inherited_effective_vis_at_level
} else {
nominal_vis
@@ -249,7 +253,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
// effective visibility can't be decreased at next update call for the
// same id
if *current_effective_vis_at_level != calculated_effective_vis
- && calculated_effective_vis.is_at_least(*current_effective_vis_at_level, tree)
+ && calculated_effective_vis.is_at_least(*current_effective_vis_at_level, tcx)
{
changed = true;
*current_effective_vis_at_level = calculated_effective_vis;
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 354c84e22..b61f7806b 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -3,7 +3,7 @@
pub use self::StabilityLevel::*;
-use crate::ty::{self, DefIdTree, TyCtxt};
+use crate::ty::{self, TyCtxt};
use rustc_ast::NodeId;
use rustc_attr::{self as attr, ConstStability, DefaultBodyStability, Deprecation, Stability};
use rustc_data_structures::fx::FxHashMap;
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index b93871769..3fb468379 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::graph;
use rustc_data_structures::graph::dominators::{dominators, Dominators};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::OnceCell;
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::{IndexSlice, IndexVec};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use smallvec::SmallVec;
@@ -124,10 +124,10 @@ impl<'tcx> BasicBlocks<'tcx> {
}
impl<'tcx> std::ops::Deref for BasicBlocks<'tcx> {
- type Target = IndexVec<BasicBlock, BasicBlockData<'tcx>>;
+ type Target = IndexSlice<BasicBlock, BasicBlockData<'tcx>>;
#[inline]
- fn deref(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
+ fn deref(&self) -> &IndexSlice<BasicBlock, BasicBlockData<'tcx>> {
&self.basic_blocks
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 48375ed30..1a8e48264 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -2,8 +2,6 @@
mod init_mask;
mod provenance_map;
-#[cfg(test)]
-mod tests;
use std::borrow::Cow;
use std::fmt;
@@ -111,26 +109,34 @@ const MAX_HASHED_BUFFER_LEN: usize = 2 * MAX_BYTES_TO_HASH;
// large.
impl hash::Hash for Allocation {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ let Self {
+ bytes,
+ provenance,
+ init_mask,
+ align,
+ mutability,
+ extra: (), // don't bother hashing ()
+ } = self;
+
// Partially hash the `bytes` buffer when it is large. To limit collisions with common
// prefixes and suffixes, we hash the length and some slices of the buffer.
- let byte_count = self.bytes.len();
+ let byte_count = bytes.len();
if byte_count > MAX_HASHED_BUFFER_LEN {
// Hash the buffer's length.
byte_count.hash(state);
// And its head and tail.
- self.bytes[..MAX_BYTES_TO_HASH].hash(state);
- self.bytes[byte_count - MAX_BYTES_TO_HASH..].hash(state);
+ bytes[..MAX_BYTES_TO_HASH].hash(state);
+ bytes[byte_count - MAX_BYTES_TO_HASH..].hash(state);
} else {
- self.bytes.hash(state);
+ bytes.hash(state);
}
// Hash the other fields as usual.
- self.provenance.hash(state);
- self.init_mask.hash(state);
- self.align.hash(state);
- self.mutability.hash(state);
- self.extra.hash(state);
+ provenance.hash(state);
+ init_mask.hash(state);
+ align.hash(state);
+ mutability.hash(state);
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
index 82e9a961a..dcb56a175 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
@@ -1,3 +1,6 @@
+#[cfg(test)]
+mod tests;
+
use std::hash;
use std::iter;
use std::ops::Range;
@@ -10,20 +13,185 @@ type Block = u64;
/// A bitmask where each bit refers to the byte with the same index. If the bit is `true`, the byte
/// is initialized. If it is `false` the byte is uninitialized.
-// Note: for performance reasons when interning, some of the `InitMask` fields can be partially
-// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
-#[derive(Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable)]
-#[derive(HashStable)]
+/// The actual bits are only materialized when needed, and we try to keep this data lazy as long as
+/// possible. Currently, if all the blocks have the same value, then the mask represents either a
+/// fully initialized or fully uninitialized const allocation, so we can only store that single
+/// value.
+#[derive(Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
pub struct InitMask {
- blocks: Vec<Block>,
+ blocks: InitMaskBlocks,
len: Size,
}
+#[derive(Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
+enum InitMaskBlocks {
+ Lazy {
+ /// Whether the lazy init mask is fully initialized or uninitialized.
+ state: bool,
+ },
+ Materialized(InitMaskMaterialized),
+}
+
+impl InitMask {
+ pub fn new(size: Size, state: bool) -> Self {
+ // Blocks start lazily allocated, until we have to materialize them.
+ let blocks = InitMaskBlocks::Lazy { state };
+ InitMask { len: size, blocks }
+ }
+
+ /// Checks whether the `range` is entirely initialized.
+ ///
+ /// Returns `Ok(())` if it's initialized. Otherwise returns a range of byte
+ /// indexes for the first contiguous span of the uninitialized access.
+ #[inline]
+ pub fn is_range_initialized(&self, range: AllocRange) -> Result<(), AllocRange> {
+ let end = range.end();
+ if end > self.len {
+ return Err(AllocRange::from(self.len..end));
+ }
+
+ match self.blocks {
+ InitMaskBlocks::Lazy { state } => {
+ // Lazily allocated blocks represent the full mask, and cover the requested range by
+ // definition.
+ if state { Ok(()) } else { Err(range) }
+ }
+ InitMaskBlocks::Materialized(ref blocks) => {
+ blocks.is_range_initialized(range.start, end)
+ }
+ }
+ }
+
+ /// Sets a specified range to a value. If the range is out-of-bounds, the mask will grow to
+ /// accommodate it entirely.
+ pub fn set_range(&mut self, range: AllocRange, new_state: bool) {
+ let start = range.start;
+ let end = range.end();
+
+ let is_full_overwrite = start == Size::ZERO && end >= self.len;
+
+ // Optimize the cases of a full init/uninit state, while handling growth if needed.
+ match self.blocks {
+ InitMaskBlocks::Lazy { ref mut state } if is_full_overwrite => {
+ // This is fully overwriting the mask, and we'll still have a single initialization
+ // state: the blocks can stay lazy.
+ *state = new_state;
+ self.len = end;
+ }
+ InitMaskBlocks::Materialized(_) if is_full_overwrite => {
+ // This is also fully overwriting materialized blocks with a single initialization
+ // state: we'll have no need for these blocks anymore and can make them lazy.
+ self.blocks = InitMaskBlocks::Lazy { state: new_state };
+ self.len = end;
+ }
+ InitMaskBlocks::Lazy { state } if state == new_state => {
+ // Here we're partially overwriting the mask but the initialization state doesn't
+ // change: the blocks can stay lazy.
+ if end > self.len {
+ self.len = end;
+ }
+ }
+ _ => {
+ // Otherwise, we have a partial overwrite that can result in a mix of initialization
+ // states, so we'll need materialized blocks.
+ let len = self.len;
+ let blocks = self.materialize_blocks();
+
+ // There are 3 cases of interest here, if we have:
+ //
+ // [--------]
+ // ^ ^
+ // 0 len
+ //
+ // 1) the range to set can be in-bounds:
+ //
+ // xxxx = [start, end]
+ // [--------]
+ // ^ ^
+ // 0 len
+ //
+ // Here, we'll simply set the single `start` to `end` range.
+ //
+ // 2) the range to set can be partially out-of-bounds:
+ //
+ // xxxx = [start, end]
+ // [--------]
+ // ^ ^
+ // 0 len
+ //
+ // We have 2 subranges to handle:
+ // - we'll set the existing `start` to `len` range.
+ // - we'll grow and set the `len` to `end` range.
+ //
+ // 3) the range to set can be fully out-of-bounds:
+ //
+ // ---xxxx = [start, end]
+ // [--------]
+ // ^ ^
+ // 0 len
+ //
+ // Since we're growing the mask to a single `new_state` value, we consider the gap
+ // from `len` to `start` to be part of the range, and have a single subrange to
+ // handle: we'll grow and set the `len` to `end` range.
+ //
+ // Note that we have to materialize, set blocks, and grow the mask. We could
+ // therefore slightly optimize things in situations where these writes overlap.
+ // However, as of writing this, growing the mask doesn't happen in practice yet, so
+ // we don't do this micro-optimization.
+
+ if end <= len {
+ // Handle case 1.
+ blocks.set_range_inbounds(start, end, new_state);
+ } else {
+ if start < len {
+ // Handle the first subrange of case 2.
+ blocks.set_range_inbounds(start, len, new_state);
+ }
+
+ // Handle the second subrange of case 2, and case 3.
+ blocks.grow(len, end - len, new_state); // `Size` operation
+ self.len = end;
+ }
+ }
+ }
+ }
+
+ /// Materializes this mask's blocks when the mask is lazy.
+ #[inline]
+ fn materialize_blocks(&mut self) -> &mut InitMaskMaterialized {
+ if let InitMaskBlocks::Lazy { state } = self.blocks {
+ self.blocks = InitMaskBlocks::Materialized(InitMaskMaterialized::new(self.len, state));
+ }
+
+ let InitMaskBlocks::Materialized(ref mut blocks) = self.blocks else {
+ bug!("initmask blocks must be materialized here")
+ };
+ blocks
+ }
+
+ /// Returns the initialization state at the specified in-bounds index.
+ #[inline]
+ pub fn get(&self, idx: Size) -> bool {
+ match self.blocks {
+ InitMaskBlocks::Lazy { state } => state,
+ InitMaskBlocks::Materialized(ref blocks) => blocks.get(idx),
+ }
+ }
+}
+
+/// The actual materialized blocks of the bitmask, when we can't keep the `InitMask` lazy.
+// Note: for performance reasons when interning, some of the fields can be partially
+// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
+#[derive(Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, HashStable)]
+struct InitMaskMaterialized {
+ blocks: Vec<Block>,
+}
+
// Const allocations are only hashed for interning. However, they can be large, making the hashing
// expensive especially since it uses `FxHash`: it's better suited to short keys, not potentially
// big buffers like the allocation's init mask. We can partially hash some fields when they're
// large.
-impl hash::Hash for InitMask {
+impl hash::Hash for InitMaskMaterialized {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
const MAX_BLOCKS_TO_HASH: usize = super::MAX_BYTES_TO_HASH / std::mem::size_of::<Block>();
const MAX_BLOCKS_LEN: usize = super::MAX_HASHED_BUFFER_LEN / std::mem::size_of::<Block>();
@@ -41,18 +209,15 @@ impl hash::Hash for InitMask {
} else {
self.blocks.hash(state);
}
-
- // Hash the other fields as usual.
- self.len.hash(state);
}
}
-impl InitMask {
+impl InitMaskMaterialized {
pub const BLOCK_SIZE: u64 = 64;
- pub fn new(size: Size, state: bool) -> Self {
- let mut m = InitMask { blocks: vec![], len: Size::ZERO };
- m.grow(size, state);
+ fn new(size: Size, state: bool) -> Self {
+ let mut m = InitMaskMaterialized { blocks: vec![] };
+ m.grow(Size::ZERO, size, state);
m
}
@@ -62,8 +227,8 @@ impl InitMask {
// Each bit in a `Block` represents the initialization state of one byte of an allocation,
// so we use `.bytes()` here.
let bits = bits.bytes();
- let a = bits / InitMask::BLOCK_SIZE;
- let b = bits % InitMask::BLOCK_SIZE;
+ let a = bits / Self::BLOCK_SIZE;
+ let b = bits % Self::BLOCK_SIZE;
(usize::try_from(a).unwrap(), usize::try_from(b).unwrap())
}
@@ -71,7 +236,7 @@ impl InitMask {
fn size_from_bit_index(block: impl TryInto<u64>, bit: impl TryInto<u64>) -> Size {
let block = block.try_into().ok().unwrap();
let bit = bit.try_into().ok().unwrap();
- Size::from_bytes(block * InitMask::BLOCK_SIZE + bit)
+ Size::from_bytes(block * Self::BLOCK_SIZE + bit)
}
/// Checks whether the `range` is entirely initialized.
@@ -79,13 +244,8 @@ impl InitMask {
/// Returns `Ok(())` if it's initialized. Otherwise returns a range of byte
/// indexes for the first contiguous span of the uninitialized access.
#[inline]
- pub fn is_range_initialized(&self, range: AllocRange) -> Result<(), AllocRange> {
- let end = range.end();
- if end > self.len {
- return Err(AllocRange::from(self.len..end));
- }
-
- let uninit_start = self.find_bit(range.start, end, false);
+ fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), AllocRange> {
+ let uninit_start = self.find_bit(start, end, false);
match uninit_start {
Some(uninit_start) => {
@@ -96,81 +256,80 @@ impl InitMask {
}
}
- pub fn set_range(&mut self, range: AllocRange, new_state: bool) {
- let end = range.end();
- let len = self.len;
- if end > len {
- self.grow(end - len, new_state);
- }
- self.set_range_inbounds(range.start, end, new_state);
- }
-
fn set_range_inbounds(&mut self, start: Size, end: Size, new_state: bool) {
- let (blocka, bita) = Self::bit_index(start);
- let (blockb, bitb) = Self::bit_index(end);
- if blocka == blockb {
- // First set all bits except the first `bita`,
- // then unset the last `64 - bitb` bits.
- let range = if bitb == 0 {
- u64::MAX << bita
+ let (block_a, bit_a) = Self::bit_index(start);
+ let (block_b, bit_b) = Self::bit_index(end);
+ if block_a == block_b {
+ // First set all bits except the first `bit_a`,
+ // then unset the last `64 - bit_b` bits.
+ let range = if bit_b == 0 {
+ u64::MAX << bit_a
} else {
- (u64::MAX << bita) & (u64::MAX >> (64 - bitb))
+ (u64::MAX << bit_a) & (u64::MAX >> (64 - bit_b))
};
if new_state {
- self.blocks[blocka] |= range;
+ self.blocks[block_a] |= range;
} else {
- self.blocks[blocka] &= !range;
+ self.blocks[block_a] &= !range;
}
return;
}
// across block boundaries
if new_state {
- // Set `bita..64` to `1`.
- self.blocks[blocka] |= u64::MAX << bita;
- // Set `0..bitb` to `1`.
- if bitb != 0 {
- self.blocks[blockb] |= u64::MAX >> (64 - bitb);
+ // Set `bit_a..64` to `1`.
+ self.blocks[block_a] |= u64::MAX << bit_a;
+ // Set `0..bit_b` to `1`.
+ if bit_b != 0 {
+ self.blocks[block_b] |= u64::MAX >> (64 - bit_b);
}
// Fill in all the other blocks (much faster than one bit at a time).
- for block in (blocka + 1)..blockb {
+ for block in (block_a + 1)..block_b {
self.blocks[block] = u64::MAX;
}
} else {
- // Set `bita..64` to `0`.
- self.blocks[blocka] &= !(u64::MAX << bita);
- // Set `0..bitb` to `0`.
- if bitb != 0 {
- self.blocks[blockb] &= !(u64::MAX >> (64 - bitb));
+ // Set `bit_a..64` to `0`.
+ self.blocks[block_a] &= !(u64::MAX << bit_a);
+ // Set `0..bit_b` to `0`.
+ if bit_b != 0 {
+ self.blocks[block_b] &= !(u64::MAX >> (64 - bit_b));
}
// Fill in all the other blocks (much faster than one bit at a time).
- for block in (blocka + 1)..blockb {
+ for block in (block_a + 1)..block_b {
self.blocks[block] = 0;
}
}
}
#[inline]
- pub fn get(&self, i: Size) -> bool {
+ fn get(&self, i: Size) -> bool {
let (block, bit) = Self::bit_index(i);
(self.blocks[block] & (1 << bit)) != 0
}
- fn grow(&mut self, amount: Size, new_state: bool) {
+ fn grow(&mut self, len: Size, amount: Size, new_state: bool) {
if amount.bytes() == 0 {
return;
}
let unused_trailing_bits =
- u64::try_from(self.blocks.len()).unwrap() * Self::BLOCK_SIZE - self.len.bytes();
+ u64::try_from(self.blocks.len()).unwrap() * Self::BLOCK_SIZE - len.bytes();
+
+ // If there's not enough capacity in the currently allocated blocks, allocate some more.
if amount.bytes() > unused_trailing_bits {
let additional_blocks = amount.bytes() / Self::BLOCK_SIZE + 1;
- self.blocks.extend(
- // FIXME(oli-obk): optimize this by repeating `new_state as Block`.
- iter::repeat(0).take(usize::try_from(additional_blocks).unwrap()),
- );
+
+ // We allocate the blocks to the correct value for the requested init state, so we won't
+ // have to manually set them with another write.
+ let block = if new_state { u64::MAX } else { 0 };
+ self.blocks
+ .extend(iter::repeat(block).take(usize::try_from(additional_blocks).unwrap()));
+ }
+
+ // New blocks have already been set here, so we only need to set the unused trailing bits,
+ // if any.
+ if unused_trailing_bits > 0 {
+ let in_bounds_tail = Size::from_bytes(unused_trailing_bits);
+ self.set_range_inbounds(len, len + in_bounds_tail, new_state); // `Size` operation
}
- let start = self.len;
- self.len += amount;
- self.set_range_inbounds(start, start + amount, new_state); // `Size` operation
}
/// Returns the index of the first bit in `start..end` (end-exclusive) that is equal to is_init.
@@ -188,7 +347,7 @@ impl InitMask {
/// ```
/// Also, if not stated, assume that `is_init = true`, that is, we are searching for the first 1 bit.
fn find_bit_fast(
- init_mask: &InitMask,
+ init_mask: &InitMaskMaterialized,
start: Size,
end: Size,
is_init: bool,
@@ -223,7 +382,7 @@ impl InitMask {
None
} else {
let bit = bits.trailing_zeros();
- Some(InitMask::size_from_bit_index(block, bit))
+ Some(InitMaskMaterialized::size_from_bit_index(block, bit))
}
}
@@ -253,9 +412,9 @@ impl InitMask {
// This provides the desired behavior of searching blocks 0 and 1 for (a),
// and searching only block 0 for (b).
// There is no concern of overflows since we checked for `start >= end` above.
- let (start_block, start_bit) = InitMask::bit_index(start);
+ let (start_block, start_bit) = InitMaskMaterialized::bit_index(start);
let end_inclusive = Size::from_bytes(end.bytes() - 1);
- let (end_block_inclusive, _) = InitMask::bit_index(end_inclusive);
+ let (end_block_inclusive, _) = InitMaskMaterialized::bit_index(end_inclusive);
// Handle first block: need to skip `start_bit` bits.
//
@@ -340,7 +499,7 @@ impl InitMask {
#[cfg_attr(not(debug_assertions), allow(dead_code))]
fn find_bit_slow(
- init_mask: &InitMask,
+ init_mask: &InitMaskMaterialized,
start: Size,
end: Size,
is_init: bool,
@@ -436,10 +595,19 @@ impl<'a> Iterator for InitChunkIter<'a> {
return None;
}
- let end_of_chunk =
- self.init_mask.find_bit(self.start, self.end, !self.is_init).unwrap_or(self.end);
+ let end_of_chunk = match self.init_mask.blocks {
+ InitMaskBlocks::Lazy { .. } => {
+ // If we're iterating over the chunks of lazy blocks, we just emit a single
+ // full-size chunk.
+ self.end
+ }
+ InitMaskBlocks::Materialized(ref blocks) => {
+ let end_of_chunk =
+ blocks.find_bit(self.start, self.end, !self.is_init).unwrap_or(self.end);
+ end_of_chunk
+ }
+ };
let range = self.start..end_of_chunk;
-
let ret =
Some(if self.is_init { InitChunk::Init(range) } else { InitChunk::Uninit(range) });
@@ -504,17 +672,19 @@ impl InitMask {
/// Applies multiple instances of the run-length encoding to the initialization mask.
pub fn apply_copy(&mut self, defined: InitCopy, range: AllocRange, repeat: u64) {
- // An optimization where we can just overwrite an entire range of initialization
- // bits if they are going to be uniformly `1` or `0`.
+ // An optimization where we can just overwrite an entire range of initialization bits if
+ // they are going to be uniformly `1` or `0`. If this happens to be a full-range overwrite,
+ // we won't need materialized blocks either.
if defined.ranges.len() <= 1 {
- self.set_range_inbounds(
- range.start,
- range.start + range.size * repeat, // `Size` operations
- defined.initial,
- );
+ let start = range.start;
+ let end = range.start + range.size * repeat; // `Size` operations
+ self.set_range(AllocRange::from(start..end), defined.initial);
return;
}
+ // We're about to do one or more partial writes, so we ensure the blocks are materialized.
+ let blocks = self.materialize_blocks();
+
for mut j in 0..repeat {
j *= range.size.bytes();
j += range.start.bytes();
@@ -522,7 +692,7 @@ impl InitMask {
for range in &defined.ranges {
let old_j = j;
j += range;
- self.set_range_inbounds(Size::from_bytes(old_j), Size::from_bytes(j), cur);
+ blocks.set_range_inbounds(Size::from_bytes(old_j), Size::from_bytes(j), cur);
cur = !cur;
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask/tests.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask/tests.rs
new file mode 100644
index 000000000..1a7934bc2
--- /dev/null
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask/tests.rs
@@ -0,0 +1,195 @@
+use super::*;
+use crate::mir::interpret::alloc_range;
+
+#[test]
+fn uninit_mask() {
+ let mut mask = InitMask::new(Size::from_bytes(500), false);
+ assert!(!mask.get(Size::from_bytes(499)));
+ mask.set_range(alloc_range(Size::from_bytes(499), Size::from_bytes(1)), true);
+ assert!(mask.get(Size::from_bytes(499)));
+ mask.set_range((100..256).into(), true);
+ for i in 0..100 {
+ assert!(!mask.get(Size::from_bytes(i)), "{i} should not be set");
+ }
+ for i in 100..256 {
+ assert!(mask.get(Size::from_bytes(i)), "{i} should be set");
+ }
+ for i in 256..499 {
+ assert!(!mask.get(Size::from_bytes(i)), "{i} should not be set");
+ }
+}
+
+/// Returns the number of materialized blocks for this mask.
+fn materialized_block_count(mask: &InitMask) -> usize {
+ match mask.blocks {
+ InitMaskBlocks::Lazy { .. } => 0,
+ InitMaskBlocks::Materialized(ref blocks) => blocks.blocks.len(),
+ }
+}
+
+#[test]
+fn materialize_mask_within_range() {
+ // To have spare bits, we use a mask size smaller than its block size of 64.
+ let mut mask = InitMask::new(Size::from_bytes(16), false);
+ assert_eq!(materialized_block_count(&mask), 0);
+
+ // Forces materialization, but doesn't require growth. This is case #1 documented in the
+ // `set_range` method.
+ mask.set_range((8..16).into(), true);
+ assert_eq!(materialized_block_count(&mask), 1);
+
+ for i in 0..8 {
+ assert!(!mask.get(Size::from_bytes(i)), "{i} should not be set");
+ }
+ for i in 8..16 {
+ assert!(mask.get(Size::from_bytes(i)), "{i} should be set");
+ }
+}
+
+#[test]
+fn grow_within_unused_bits_with_full_overwrite() {
+ // To have spare bits, we use a mask size smaller than its block size of 64.
+ let mut mask = InitMask::new(Size::from_bytes(16), true);
+ for i in 0..16 {
+ assert!(mask.get(Size::from_bytes(i)), "{i} should be set");
+ }
+
+ // Grow without requiring an additional block. Full overwrite.
+ // This can be fully handled without materialization.
+ let range = (0..32).into();
+ mask.set_range(range, true);
+
+ for i in 0..32 {
+ assert!(mask.get(Size::from_bytes(i)), "{i} should be set");
+ }
+
+ assert_eq!(materialized_block_count(&mask), 0);
+}
+
+// This test checks that an initmask's spare capacity is correctly used when growing within block
+// capacity. This can be fully handled without materialization.
+#[test]
+fn grow_same_state_within_unused_bits() {
+ // To have spare bits, we use a mask size smaller than its block size of 64.
+ let mut mask = InitMask::new(Size::from_bytes(16), true);
+ for i in 0..16 {
+ assert!(mask.get(Size::from_bytes(i)), "{i} should be set");
+ }
+
+ // Grow without requiring an additional block. The gap between the current length and the
+ // range's beginning should be set to the same value as the range.
+ let range = (24..32).into();
+ mask.set_range(range, true);
+
+ // We want to make sure the unused bits in the first block are correct
+ for i in 16..24 {
+ assert!(mask.get(Size::from_bytes(i)), "{i} should be set");
+ }
+
+ for i in 24..32 {
+ assert!(mask.get(Size::from_bytes(i)), "{i} should be set");
+ }
+
+ assert_eq!(1, mask.range_as_init_chunks((0..32).into()).count());
+ assert_eq!(materialized_block_count(&mask), 0);
+}
+
+// This is the same test as `grow_same_state_within_unused_bits` but with both init and uninit
+// states: this forces materialization; otherwise the mask could stay lazy even when needing to
+// grow.
+#[test]
+fn grow_mixed_state_within_unused_bits() {
+ // To have spare bits, we use a mask size smaller than its block size of 64.
+ let mut mask = InitMask::new(Size::from_bytes(16), true);
+ for i in 0..16 {
+ assert!(mask.get(Size::from_bytes(i)), "{i} should be set");
+ }
+
+ // Grow without requiring an additional block. The gap between the current length and the
+ // range's beginning should be set to the same value as the range. Note: since this is fully
+ // out-of-bounds of the current mask, this is case #3 described in the `set_range` method.
+ let range = (24..32).into();
+ mask.set_range(range, false);
+
+ // We want to make sure the unused bits in the first block are correct
+ for i in 16..24 {
+ assert!(!mask.get(Size::from_bytes(i)), "{i} should not be set");
+ }
+
+ for i in 24..32 {
+ assert!(!mask.get(Size::from_bytes(i)), "{i} should not be set");
+ }
+
+ assert_eq!(1, mask.range_as_init_chunks((0..16).into()).count());
+ assert_eq!(2, mask.range_as_init_chunks((0..32).into()).count());
+ assert_eq!(materialized_block_count(&mask), 1);
+}
+
+// This is similar to `grow_mixed_state_within_unused_bits` to force materialization, but the range
+// to set partially overlaps the mask, so this requires a different growth + write pattern in the
+// mask.
+#[test]
+fn grow_within_unused_bits_with_overlap() {
+ // To have spare bits, we use a mask size smaller than its block size of 64.
+ let mut mask = InitMask::new(Size::from_bytes(16), true);
+ for i in 0..16 {
+ assert!(mask.get(Size::from_bytes(i)), "{i} should be set");
+ }
+
+ // Grow without requiring an additional block, but leave no gap after the current len. Note:
+ // since this is partially out-of-bounds of the current mask, this is case #2 described in the
+ // `set_range` method.
+ let range = (8..24).into();
+ mask.set_range(range, false);
+
+ // We want to make sure the unused bits in the first block are correct
+ for i in 8..24 {
+ assert!(!mask.get(Size::from_bytes(i)), "{i} should not be set");
+ }
+
+ assert_eq!(1, mask.range_as_init_chunks((0..8).into()).count());
+ assert_eq!(2, mask.range_as_init_chunks((0..24).into()).count());
+ assert_eq!(materialized_block_count(&mask), 1);
+}
+
+// Force materialization before a full overwrite: the mask can now become lazy.
+#[test]
+fn grow_mixed_state_within_unused_bits_and_full_overwrite() {
+ // To have spare bits, we use a mask size smaller than its block size of 64.
+ let mut mask = InitMask::new(Size::from_bytes(16), true);
+ let range = (0..16).into();
+ assert!(mask.is_range_initialized(range).is_ok());
+
+ // Force materialization.
+ let range = (8..24).into();
+ mask.set_range(range, false);
+ assert!(mask.is_range_initialized(range).is_err());
+ assert_eq!(materialized_block_count(&mask), 1);
+
+ // Full overwrite, lazy blocks would be enough from now on.
+ let range = (0..32).into();
+ mask.set_range(range, true);
+ assert!(mask.is_range_initialized(range).is_ok());
+
+ assert_eq!(1, mask.range_as_init_chunks((0..32).into()).count());
+ assert_eq!(materialized_block_count(&mask), 0);
+}
+
+// Check that growth outside the current capacity can still be lazy: if the init state doesn't
+// change, we don't need materialized blocks.
+#[test]
+fn grow_same_state_outside_capacity() {
+ // To have spare bits, we use a mask size smaller than its block size of 64.
+ let mut mask = InitMask::new(Size::from_bytes(16), true);
+ for i in 0..16 {
+ assert!(mask.get(Size::from_bytes(i)), "{i} should be set");
+ }
+ assert_eq!(materialized_block_count(&mask), 0);
+
+ // Grow to 10 blocks with the same init state.
+ let range = (24..640).into();
+ mask.set_range(range, true);
+
+ assert_eq!(1, mask.range_as_init_chunks((0..640).into()).count());
+ assert_eq!(materialized_block_count(&mask), 0);
+}
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index ddd3f3943..318f93e12 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -14,7 +14,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
#[derive(HashStable)]
pub struct ProvenanceMap<Prov = AllocId> {
/// Provenance in this map applies from the given offset for an entire pointer-size worth of
- /// bytes. Two entires in this map are always at least a pointer size apart.
+ /// bytes. Two entries in this map are always at least a pointer size apart.
ptrs: SortedMap<Size, Prov>,
/// Provenance in this map only applies to the given single byte.
/// This map is disjoint from the previous. It will always be empty when
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/tests.rs b/compiler/rustc_middle/src/mir/interpret/allocation/tests.rs
deleted file mode 100644
index c9c3c50c5..000000000
--- a/compiler/rustc_middle/src/mir/interpret/allocation/tests.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use super::*;
-
-#[test]
-fn uninit_mask() {
- let mut mask = InitMask::new(Size::from_bytes(500), false);
- assert!(!mask.get(Size::from_bytes(499)));
- mask.set_range(alloc_range(Size::from_bytes(499), Size::from_bytes(1)), true);
- assert!(mask.get(Size::from_bytes(499)));
- mask.set_range((100..256).into(), true);
- for i in 0..100 {
- assert!(!mask.get(Size::from_bytes(i)), "{i} should not be set");
- }
- for i in 100..256 {
- assert!(mask.get(Size::from_bytes(i)), "{i} should be set");
- }
- for i in 256..499 {
- assert!(!mask.get(Size::from_bytes(i)), "{i} should not be set");
- }
-}
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 1766d7a66..1f8b650e3 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -263,7 +263,8 @@ impl AllocDecodingState {
}
pub fn new(data_offsets: Vec<u32>) -> Self {
- let decoding_state = vec![Lock::new(State::Empty); data_offsets.len()];
+ let decoding_state =
+ std::iter::repeat_with(|| Lock::new(State::Empty)).take(data_offsets.len()).collect();
Self { decoding_state, data_offsets }
}
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 99cdb769d..2ea8602af 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -10,7 +10,7 @@ use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
-use crate::ty::{self, DefIdTree, List, Ty, TyCtxt};
+use crate::ty::{self, List, Ty, TyCtxt};
use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
@@ -21,13 +21,13 @@ use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::{self, GeneratorKind, ImplicitSelfKind};
use rustc_hir::{self as hir, HirId};
use rustc_session::Session;
-use rustc_target::abi::{Size, VariantIdx};
+use rustc_target::abi::{FieldIdx, Size, VariantIdx};
use polonius_engine::Atom;
pub use rustc_ast::Mutability;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::dominators::Dominators;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::{Idx, IndexSlice, IndexVec};
use rustc_serialize::{Decodable, Encodable};
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
@@ -70,12 +70,19 @@ pub use self::pretty::{
};
/// Types for locals
-pub type LocalDecls<'tcx> = IndexVec<Local, LocalDecl<'tcx>>;
+pub type LocalDecls<'tcx> = IndexSlice<Local, LocalDecl<'tcx>>;
pub trait HasLocalDecls<'tcx> {
fn local_decls(&self) -> &LocalDecls<'tcx>;
}
+impl<'tcx> HasLocalDecls<'tcx> for IndexVec<Local, LocalDecl<'tcx>> {
+ #[inline]
+ fn local_decls(&self) -> &LocalDecls<'tcx> {
+ self
+ }
+}
+
impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> {
#[inline]
fn local_decls(&self) -> &LocalDecls<'tcx> {
@@ -250,7 +257,7 @@ pub struct Body<'tcx> {
/// The first local is the return value pointer, followed by `arg_count`
/// locals for the function arguments, followed by any user-declared
/// variables and temporaries.
- pub local_decls: LocalDecls<'tcx>,
+ pub local_decls: IndexVec<Local, LocalDecl<'tcx>>,
/// User type annotations.
pub user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
@@ -311,7 +318,7 @@ impl<'tcx> Body<'tcx> {
source: MirSource<'tcx>,
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
- local_decls: LocalDecls<'tcx>,
+ local_decls: IndexVec<Local, LocalDecl<'tcx>>,
user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
arg_count: usize,
var_debug_info: Vec<VarDebugInfo<'tcx>>,
@@ -401,8 +408,6 @@ impl<'tcx> Body<'tcx> {
LocalKind::ReturnPointer
} else if index < self.arg_count + 1 {
LocalKind::Arg
- } else if self.local_decls[local].is_user_variable() {
- LocalKind::Var
} else {
LocalKind::Temp
}
@@ -572,6 +577,13 @@ impl<T> ClearCrossCrate<T> {
}
}
+ pub fn as_mut(&mut self) -> ClearCrossCrate<&mut T> {
+ match self {
+ ClearCrossCrate::Clear => ClearCrossCrate::Clear,
+ ClearCrossCrate::Set(v) => ClearCrossCrate::Set(v),
+ }
+ }
+
pub fn assert_crate_local(self) -> T {
match self {
ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"),
@@ -661,9 +673,7 @@ impl Atom for Local {
/// Classifies locals into categories. See `Body::local_kind`.
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
pub enum LocalKind {
- /// User-declared variable binding.
- Var,
- /// Compiler-introduced temporary.
+ /// User-declared variable binding or compiler-introduced temporary.
Temp,
/// Function argument.
Arg,
@@ -760,7 +770,7 @@ pub struct LocalDecl<'tcx> {
pub mutability: Mutability,
// FIXME(matthewjasper) Don't store in this in `Body`
- pub local_info: Option<Box<LocalInfo<'tcx>>>,
+ pub local_info: ClearCrossCrate<Box<LocalInfo<'tcx>>>,
/// `true` if this is an internal local.
///
@@ -778,13 +788,6 @@ pub struct LocalDecl<'tcx> {
/// generator.
pub internal: bool,
- /// If this local is a temporary and `is_block_tail` is `Some`,
- /// then it is a temporary created for evaluation of some
- /// subexpression of some block's tail expression (with no
- /// intervening statement context).
- // FIXME(matthewjasper) Don't store in this in `Body`
- pub is_block_tail: Option<BlockTailInfo>,
-
/// The type of this local.
pub ty: Ty<'tcx>,
@@ -890,7 +893,7 @@ pub enum LocalInfo<'tcx> {
/// The `BindingForm` is solely used for local diagnostics when generating
/// warnings/errors when compiling the current crate, and therefore it need
/// not be visible across crates.
- User(ClearCrossCrate<BindingForm<'tcx>>),
+ User(BindingForm<'tcx>),
/// A temporary created that references the static with the given `DefId`.
StaticRef { def_id: DefId, is_thread_local: bool },
/// A temporary created that references the const with the given `DefId`
@@ -898,13 +901,23 @@ pub enum LocalInfo<'tcx> {
/// A temporary created during the creation of an aggregate
/// (e.g. a temporary for `foo` in `MyStruct { my_field: foo }`)
AggregateTemp,
+ /// A temporary created for evaluation of some subexpression of some block's tail expression
+ /// (with no intervening statement context).
+ // FIXME(matthewjasper) Don't store in this in `Body`
+ BlockTailTemp(BlockTailInfo),
/// A temporary created during the pass `Derefer` to avoid it's retagging
DerefTemp,
/// A temporary created for borrow checking.
FakeBorrow,
+ /// A local without anything interesting about it.
+ Boring,
}
impl<'tcx> LocalDecl<'tcx> {
+ pub fn local_info(&self) -> &LocalInfo<'tcx> {
+ &self.local_info.as_ref().assert_crate_local()
+ }
+
/// Returns `true` only if local is a binding that can itself be
/// made mutable via the addition of the `mut` keyword, namely
/// something like the occurrences of `x` in:
@@ -913,15 +926,15 @@ impl<'tcx> LocalDecl<'tcx> {
/// - or `match ... { C(x) => ... }`
pub fn can_be_made_mutable(&self) -> bool {
matches!(
- self.local_info,
- Some(box LocalInfo::User(ClearCrossCrate::Set(
+ self.local_info(),
+ LocalInfo::User(
BindingForm::Var(VarBindingForm {
binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _,
opt_match_place: _,
pat_span: _,
}) | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
- )))
+ )
)
}
@@ -930,15 +943,15 @@ impl<'tcx> LocalDecl<'tcx> {
/// mutable bindings, but the inverse does not necessarily hold).
pub fn is_nonref_binding(&self) -> bool {
matches!(
- self.local_info,
- Some(box LocalInfo::User(ClearCrossCrate::Set(
+ self.local_info(),
+ LocalInfo::User(
BindingForm::Var(VarBindingForm {
binding_mode: ty::BindingMode::BindByValue(_),
opt_ty_info: _,
opt_match_place: _,
pat_span: _,
}) | BindingForm::ImplicitSelf(_),
- )))
+ )
)
}
@@ -946,38 +959,35 @@ impl<'tcx> LocalDecl<'tcx> {
/// parameter declared by the user.
#[inline]
pub fn is_user_variable(&self) -> bool {
- matches!(self.local_info, Some(box LocalInfo::User(_)))
+ matches!(self.local_info(), LocalInfo::User(_))
}
/// Returns `true` if this is a reference to a variable bound in a `match`
/// expression that is used to access said variable for the guard of the
/// match arm.
pub fn is_ref_for_guard(&self) -> bool {
- matches!(
- self.local_info,
- Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)))
- )
+ matches!(self.local_info(), LocalInfo::User(BindingForm::RefForGuard))
}
/// Returns `Some` if this is a reference to a static item that is used to
/// access that static.
pub fn is_ref_to_static(&self) -> bool {
- matches!(self.local_info, Some(box LocalInfo::StaticRef { .. }))
+ matches!(self.local_info(), LocalInfo::StaticRef { .. })
}
/// Returns `Some` if this is a reference to a thread-local static item that is used to
/// access that static.
pub fn is_ref_to_thread_local(&self) -> bool {
- match self.local_info {
- Some(box LocalInfo::StaticRef { is_thread_local, .. }) => is_thread_local,
+ match self.local_info() {
+ LocalInfo::StaticRef { is_thread_local, .. } => *is_thread_local,
_ => false,
}
}
/// Returns `true` if this is a DerefTemp
pub fn is_deref_temp(&self) -> bool {
- match self.local_info {
- Some(box LocalInfo::DerefTemp) => return true,
+ match self.local_info() {
+ LocalInfo::DerefTemp => return true,
_ => (),
}
return false;
@@ -1001,9 +1011,8 @@ impl<'tcx> LocalDecl<'tcx> {
pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
LocalDecl {
mutability: Mutability::Mut,
- local_info: None,
+ local_info: ClearCrossCrate::Set(Box::new(LocalInfo::Boring)),
internal: false,
- is_block_tail: None,
ty,
user_ty: None,
source_info,
@@ -1023,20 +1032,11 @@ impl<'tcx> LocalDecl<'tcx> {
self.mutability = Mutability::Not;
self
}
-
- /// Converts `self` into same `LocalDecl` except tagged as internal temporary.
- #[inline]
- pub fn block_tail(mut self, info: BlockTailInfo) -> Self {
- assert!(self.is_block_tail.is_none());
- self.is_block_tail = Some(info);
- self
- }
}
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub enum VarDebugInfoContents<'tcx> {
- /// NOTE(eddyb) There's an unenforced invariant that this `Place` is
- /// based on a `Local`, not a `Static`, and contains no indexing.
+ /// This `Place` only contains projection which satisfy `can_use_in_debuginfo`.
Place(Place<'tcx>),
Const(Constant<'tcx>),
/// The user variable's data is split across several fragments,
@@ -1046,6 +1046,7 @@ pub enum VarDebugInfoContents<'tcx> {
/// the underlying debuginfo feature this relies on.
Composite {
/// Type of the original user variable.
+ /// This cannot contain a union or an enum.
ty: Ty<'tcx>,
/// All the parts of the original user variable, which ended
/// up in disjoint places, due to optimizations.
@@ -1074,17 +1075,16 @@ pub struct VarDebugInfoFragment<'tcx> {
/// Where in the composite user variable this fragment is,
/// represented as a "projection" into the composite variable.
/// At lower levels, this corresponds to a byte/bit range.
- // NOTE(eddyb) there's an unenforced invariant that this contains
- // only `Field`s, and not into `enum` variants or `union`s.
- // FIXME(eddyb) support this for `enum`s by either using DWARF's
+ ///
+ /// This can only contain `PlaceElem::Field`.
+ // FIXME support this for `enum`s by either using DWARF's
// more advanced control-flow features (unsupported by LLVM?)
// to match on the discriminant, or by using custom type debuginfo
// with non-overlapping variants for the composite variable.
pub projection: Vec<PlaceElem<'tcx>>,
/// Where the data for this fragment can be found.
- // NOTE(eddyb) There's an unenforced invariant that this `Place` is
- // contains no indexing (with a non-constant index).
+ /// This `Place` only contains projection which satisfy `can_use_in_debuginfo`.
pub contents: Place<'tcx>,
}
@@ -1115,6 +1115,11 @@ pub struct VarDebugInfo<'tcx> {
/// Where the data for this user variable is to be found.
pub value: VarDebugInfoContents<'tcx>,
+
+ /// When present, indicates what argument number this variable is in the function that it
+ /// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
+ /// argument number in the original function before it was inlined.
+ pub argument_index: Option<u16>,
}
///////////////////////////////////////////////////////////////////////////
@@ -1274,9 +1279,16 @@ impl<'tcx> BasicBlockData<'tcx> {
}
impl<O> AssertKind<O> {
+ /// Returns true if this an overflow checking assertion controlled by -C overflow-checks.
+ pub fn is_optional_overflow_check(&self) -> bool {
+ use AssertKind::*;
+ use BinOp::*;
+ matches!(self, OverflowNeg(..) | Overflow(Add | Sub | Mul | Shl | Shr, ..))
+ }
+
/// Getting a description does not require `O` to be printable, and does not
/// require allocation.
- /// The caller is expected to handle `BoundsCheck` separately.
+ /// The caller is expected to handle `BoundsCheck` and `MisalignedPointerDereference` separately.
pub fn description(&self) -> &'static str {
use AssertKind::*;
match self {
@@ -1295,7 +1307,9 @@ impl<O> AssertKind<O> {
ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion",
ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking",
ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking",
- BoundsCheck { .. } => bug!("Unexpected AssertKind"),
+ BoundsCheck { .. } | MisalignedPointerDereference { .. } => {
+ bug!("Unexpected AssertKind")
+ }
}
}
@@ -1352,6 +1366,13 @@ impl<O> AssertKind<O> {
Overflow(BinOp::Shl, _, r) => {
write!(f, "\"attempt to shift left by `{{}}`, which would overflow\", {:?}", r)
}
+ MisalignedPointerDereference { required, found } => {
+ write!(
+ f,
+ "\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\", {:?}, {:?}",
+ required, found
+ )
+ }
_ => write!(f, "\"{}\"", self.description()),
}
}
@@ -1396,6 +1417,13 @@ impl<O: fmt::Debug> fmt::Debug for AssertKind<O> {
Overflow(BinOp::Shl, _, r) => {
write!(f, "attempt to shift left by `{:#?}`, which would overflow", r)
}
+ MisalignedPointerDereference { required, found } => {
+ write!(
+ f,
+ "misaligned pointer dereference: address must be a multiple of {:?} but is {:?}",
+ required, found
+ )
+ }
_ => write!(f, "{}", self.description()),
}
}
@@ -1453,6 +1481,9 @@ impl Debug for Statement<'_> {
write!(fmt, "discriminant({:?}) = {:?}", place, variant_index)
}
Deinit(ref place) => write!(fmt, "Deinit({:?})", place),
+ PlaceMention(ref place) => {
+ write!(fmt, "PlaceMention({:?})", place)
+ }
AscribeUserType(box (ref place, ref c_ty), ref variance) => {
write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
}
@@ -1508,31 +1539,26 @@ impl<V, T> ProjectionElem<V, T> {
}
/// Returns `true` if this is a `Field` projection with the given index.
- pub fn is_field_to(&self, f: Field) -> bool {
+ pub fn is_field_to(&self, f: FieldIdx) -> bool {
matches!(*self, Self::Field(x, _) if x == f)
}
+
+ /// Returns `true` if this is accepted inside `VarDebugInfoContents::Place`.
+ pub fn can_use_in_debuginfo(&self) -> bool {
+ match self {
+ Self::Deref | Self::Downcast(_, _) | Self::Field(_, _) => true,
+ Self::ConstantIndex { .. }
+ | Self::Index(_)
+ | Self::OpaqueCast(_)
+ | Self::Subslice { .. } => false,
+ }
+ }
}
/// Alias for projections as they appear in `UserTypeProjection`, where we
/// need neither the `V` parameter for `Index` nor the `T` for `Field`.
pub type ProjectionKind = ProjectionElem<(), ()>;
-rustc_index::newtype_index! {
- /// A [newtype'd][wrapper] index type in the MIR [control-flow graph][CFG]
- ///
- /// A field (e.g., `f` in `_1.f`) is one variant of [`ProjectionElem`]. Conceptually,
- /// rustc can identify that a field projection refers to either two different regions of memory
- /// or the same one between the base and the 'projection element'.
- /// Read more about projections in the [rustc-dev-guide][mir-datatypes]
- ///
- /// [wrapper]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html#newtype
- /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg
- /// [mir-datatypes]: https://rustc-dev-guide.rust-lang.org/mir/index.html#mir-data-types
- #[derive(HashStable)]
- #[debug_format = "field[{}]"]
- pub struct Field {}
-}
-
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct PlaceRef<'tcx> {
pub local: Local,
@@ -1775,7 +1801,7 @@ impl SourceScope {
/// from the function that was inlined instead of the function call site.
pub fn lint_root(
self,
- source_scopes: &IndexVec<SourceScope, SourceScopeData<'_>>,
+ source_scopes: &IndexSlice<SourceScope, SourceScopeData<'_>>,
) -> Option<HirId> {
let mut data = &source_scopes[self];
// FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it
@@ -1795,7 +1821,7 @@ impl SourceScope {
#[inline]
pub fn inlined_instance<'tcx>(
self,
- source_scopes: &IndexVec<SourceScope, SourceScopeData<'tcx>>,
+ source_scopes: &IndexSlice<SourceScope, SourceScopeData<'tcx>>,
) -> Option<ty::Instance<'tcx>> {
let scope_data = &source_scopes[self];
if let Some((inlined_instance, _)) = scope_data.inlined {
@@ -1963,7 +1989,8 @@ impl<'tcx> Rvalue<'tcx> {
| CastKind::PtrToPtr
| CastKind::Pointer(_)
| CastKind::PointerFromExposedAddress
- | CastKind::DynStar,
+ | CastKind::DynStar
+ | CastKind::Transmute,
_,
_,
)
@@ -1979,6 +2006,13 @@ impl<'tcx> Rvalue<'tcx> {
}
impl BorrowKind {
+ pub fn mutability(&self) -> Mutability {
+ match *self {
+ BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => Mutability::Not,
+ BorrowKind::Mut { .. } => Mutability::Mut,
+ }
+ }
+
pub fn allows_two_phase_borrow(&self) -> bool {
match *self {
BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false,
@@ -1995,13 +2029,6 @@ impl BorrowKind {
}
}
-impl BinOp {
- pub fn is_checkable(self) -> bool {
- use self::BinOp::*;
- matches!(self, Add | Sub | Mul | Shl | Shr)
- }
-}
-
impl<'tcx> Debug for Rvalue<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
use self::Rvalue::*;
@@ -2528,7 +2555,7 @@ impl<'tcx> ConstantKind<'tcx> {
let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
&& let Some(parent_did) = parent_hir_id.as_owner()
{
- InternalSubsts::identity_for_item(tcx, parent_did.to_def_id())
+ InternalSubsts::identity_for_item(tcx, parent_did)
} else {
List::empty()
};
@@ -2557,7 +2584,7 @@ impl<'tcx> ConstantKind<'tcx> {
Self::Unevaluated(
UnevaluatedConst {
def: def.to_global(),
- substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
+ substs: InternalSubsts::identity_for_item(tcx, def.did),
promoted: None,
},
ty,
@@ -2687,12 +2714,17 @@ impl<'tcx> UserTypeProjections {
self.map_projections(|pat_ty_proj| pat_ty_proj.deref())
}
- pub fn leaf(self, field: Field) -> Self {
+ pub fn leaf(self, field: FieldIdx) -> Self {
self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
}
- pub fn variant(self, adt_def: AdtDef<'tcx>, variant_index: VariantIdx, field: Field) -> Self {
- self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
+ pub fn variant(
+ self,
+ adt_def: AdtDef<'tcx>,
+ variant_index: VariantIdx,
+ field_index: FieldIdx,
+ ) -> Self {
+ self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field_index))
}
}
@@ -2735,7 +2767,7 @@ impl UserTypeProjection {
self
}
- pub(crate) fn leaf(mut self, field: Field) -> Self {
+ pub(crate) fn leaf(mut self, field: FieldIdx) -> Self {
self.projs.push(ProjectionElem::Field(field, ()));
self
}
@@ -2744,13 +2776,13 @@ impl UserTypeProjection {
mut self,
adt_def: AdtDef<'_>,
variant_index: VariantIdx,
- field: Field,
+ field_index: FieldIdx,
) -> Self {
self.projs.push(ProjectionElem::Downcast(
Some(adt_def.variant(variant_index).name),
variant_index,
));
- self.projs.push(ProjectionElem::Field(field, ()));
+ self.projs.push(ProjectionElem::Field(field_index, ()));
self
}
}
@@ -3085,7 +3117,7 @@ mod size_asserts {
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
static_assert_size!(BasicBlockData<'_>, 144);
- static_assert_size!(LocalDecl<'_>, 56);
+ static_assert_size!(LocalDecl<'_>, 40);
static_assert_size!(Statement<'_>, 32);
static_assert_size!(StatementKind<'_>, 16);
static_assert_size!(Terminator<'_>, 112);
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 7a05ee2ff..f592f1515 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -381,7 +381,9 @@ impl<'tcx> CodegenUnit<'tcx> {
| InstanceDef::Virtual(..)
| InstanceDef::ClosureOnceShim { .. }
| InstanceDef::DropGlue(..)
- | InstanceDef::CloneShim(..) => None,
+ | InstanceDef::CloneShim(..)
+ | InstanceDef::ThreadLocalShim(..)
+ | InstanceDef::FnPtrAddrShim(..) => None,
}
}
MonoItem::Static(def_id) => def_id.as_local().map(Idx::index),
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index 24fe3b472..f62853c3e 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -12,6 +12,9 @@ pub struct MirPatch<'tcx> {
new_statements: Vec<(Location, StatementKind<'tcx>)>,
new_locals: Vec<LocalDecl<'tcx>>,
resume_block: Option<BasicBlock>,
+ // Only for unreachable in cleanup path.
+ unreachable_cleanup_block: Option<BasicBlock>,
+ terminate_block: Option<BasicBlock>,
body_span: Span,
next_local: usize,
}
@@ -25,14 +28,31 @@ impl<'tcx> MirPatch<'tcx> {
new_locals: vec![],
next_local: body.local_decls.len(),
resume_block: None,
+ unreachable_cleanup_block: None,
+ terminate_block: None,
body_span: body.span,
};
- // Check if we already have a resume block
for (bb, block) in body.basic_blocks.iter_enumerated() {
+ // Check if we already have a resume block
if let TerminatorKind::Resume = block.terminator().kind && block.statements.is_empty() {
result.resume_block = Some(bb);
- break;
+ continue;
+ }
+
+ // Check if we already have an unreachable block
+ if let TerminatorKind::Unreachable = block.terminator().kind
+ && block.statements.is_empty()
+ && block.is_cleanup
+ {
+ result.unreachable_cleanup_block = Some(bb);
+ continue;
+ }
+
+ // Check if we already have a terminate block
+ if let TerminatorKind::Terminate = block.terminator().kind && block.statements.is_empty() {
+ result.terminate_block = Some(bb);
+ continue;
}
}
@@ -56,6 +76,40 @@ impl<'tcx> MirPatch<'tcx> {
bb
}
+ pub fn unreachable_cleanup_block(&mut self) -> BasicBlock {
+ if let Some(bb) = self.unreachable_cleanup_block {
+ return bb;
+ }
+
+ let bb = self.new_block(BasicBlockData {
+ statements: vec![],
+ terminator: Some(Terminator {
+ source_info: SourceInfo::outermost(self.body_span),
+ kind: TerminatorKind::Unreachable,
+ }),
+ is_cleanup: true,
+ });
+ self.unreachable_cleanup_block = Some(bb);
+ bb
+ }
+
+ pub fn terminate_block(&mut self) -> BasicBlock {
+ if let Some(bb) = self.terminate_block {
+ return bb;
+ }
+
+ let bb = self.new_block(BasicBlockData {
+ statements: vec![],
+ terminator: Some(Terminator {
+ source_info: SourceInfo::outermost(self.body_span),
+ kind: TerminatorKind::Terminate,
+ }),
+ is_cleanup: true,
+ });
+ self.terminate_block = Some(bb);
+ bb
+ }
+
pub fn is_patched(&self, bb: BasicBlock) -> bool {
self.patch_map[bb].is_some()
}
@@ -72,28 +126,28 @@ impl<'tcx> MirPatch<'tcx> {
&mut self,
ty: Ty<'tcx>,
span: Span,
- local_info: Option<Box<LocalInfo<'tcx>>>,
+ local_info: LocalInfo<'tcx>,
) -> Local {
let index = self.next_local;
self.next_local += 1;
let mut new_decl = LocalDecl::new(ty, span).internal();
- new_decl.local_info = local_info;
+ **new_decl.local_info.as_mut().assert_crate_local() = local_info;
self.new_locals.push(new_decl);
- Local::new(index as usize)
+ Local::new(index)
}
pub fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
let index = self.next_local;
self.next_local += 1;
self.new_locals.push(LocalDecl::new(ty, span));
- Local::new(index as usize)
+ Local::new(index)
}
pub fn new_internal(&mut self, ty: Ty<'tcx>, span: Span) -> Local {
let index = self.next_local;
self.next_local += 1;
self.new_locals.push(LocalDecl::new(ty, span).internal());
- Local::new(index as usize)
+ Local::new(index)
}
pub fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock {
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index d8829e3e7..7e5195359 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -123,6 +123,7 @@ fn dump_matched_mir_node<'tcx, F>(
// see notes on #41697 above
let def_path =
ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id()));
+ // ignore-tidy-odd-backticks the literal below is fine
write!(file, "// MIR for `{}", def_path)?;
match body.source.promoted {
None => write!(file, "`")?,
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index b964c1852..cfdf1dcf5 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -2,20 +2,20 @@
use crate::mir::{Body, ConstantKind, Promoted};
use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::vec_map::VecMap;
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::unord::UnordSet;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_index::bit_set::BitMatrix;
use rustc_index::vec::{Idx, IndexVec};
use rustc_span::Span;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{FieldIdx, VariantIdx};
use smallvec::SmallVec;
use std::cell::Cell;
use std::fmt::{self, Debug};
-use super::{Field, SourceInfo};
+use super::SourceInfo;
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
pub enum UnsafetyViolationKind {
@@ -123,7 +123,7 @@ pub struct UnsafetyCheckResult {
pub violations: Vec<UnsafetyViolation>,
/// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint.
- pub used_unsafe_blocks: FxHashSet<hir::HirId>,
+ pub used_unsafe_blocks: UnordSet<hir::HirId>,
/// This is `Some` iff the item is not a closure.
pub unused_unsafes: Option<Vec<(hir::HirId, UnusedUnsafe)>>,
@@ -152,7 +152,7 @@ pub struct GeneratorLayout<'tcx> {
/// Which of the above fields are in each variant. Note that one field may
/// be stored in multiple variants.
- pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
+ pub variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, GeneratorSavedLocal>>,
/// The source that led to each variant being created (usually, a yield or
/// await).
@@ -227,9 +227,9 @@ pub struct BorrowCheckResult<'tcx> {
/// All the opaque types that are restricted to concrete types
/// by this function. Unlike the value in `TypeckResults`, this has
/// unerased regions.
- pub concrete_opaque_types: VecMap<LocalDefId, OpaqueHiddenType<'tcx>>,
+ pub concrete_opaque_types: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
- pub used_mut_upvars: SmallVec<[Field; 8]>,
+ pub used_mut_upvars: SmallVec<[FieldIdx; 8]>,
pub tainted_by_errors: Option<ErrorGuaranteed>,
}
@@ -353,7 +353,7 @@ pub enum ConstraintCategory<'tcx> {
/// like `Foo { field: my_val }`)
Usage,
OpaqueType,
- ClosureUpvar(Field),
+ ClosureUpvar(FieldIdx),
/// A constraint from a user-written predicate
/// with the provided span, written on the item
@@ -375,7 +375,7 @@ pub enum ConstraintCategory<'tcx> {
#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
pub enum ReturnConstraint {
Normal,
- ClosureUpvar(Field),
+ ClosureUpvar(FieldIdx),
}
/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
@@ -411,10 +411,8 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
let inner = tcx.fold_regions(ty, |r, depth| match r.kind() {
ty::ReVar(vid) => {
- let br = ty::BoundRegion {
- var: ty::BoundVar::new(vid.index()),
- kind: ty::BrAnon(vid.as_u32(), None),
- };
+ let br =
+ ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon(None) };
tcx.mk_re_late_bound(depth, br)
}
_ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 28a3b51b7..2165403da 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -247,6 +247,7 @@ pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str {
StorageLive(..) => "StorageLive",
StorageDead(..) => "StorageDead",
Retag(..) => "Retag",
+ PlaceMention(..) => "PlaceMention",
AscribeUserType(..) => "AscribeUserType",
Coverage(..) => "Coverage",
Intrinsic(..) => "Intrinsic",
@@ -261,11 +262,10 @@ pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str {
Goto { .. } => "Goto",
SwitchInt { .. } => "SwitchInt",
Resume => "Resume",
- Abort => "Abort",
+ Terminate => "Terminate",
Return => "Return",
Unreachable => "Unreachable",
Drop { .. } => "Drop",
- DropAndReplace { .. } => "DropAndReplace",
Call { .. } => "Call",
Assert { .. } => "Assert",
Yield { .. } => "Yield",
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index ae09562a8..93800d484 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -3,7 +3,7 @@
//! This is in a dedicated file so that changes to this file can be reviewed more carefully.
//! The intention is that this file only contains datatype declarations, no code.
-use super::{BasicBlock, Constant, Field, Local, SwitchTargets, UserTypeProjection};
+use super::{BasicBlock, Constant, Local, SwitchTargets, UserTypeProjection};
use crate::mir::coverage::{CodeRegion, CoverageKind};
use crate::traits::Reveal;
@@ -16,7 +16,8 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir};
use rustc_hir::{self, GeneratorKind};
-use rustc_target::abi::VariantIdx;
+use rustc_index::vec::IndexVec;
+use rustc_target::abi::{FieldIdx, VariantIdx};
use rustc_ast::Mutability;
use rustc_span::def_id::LocalDefId;
@@ -78,7 +79,8 @@ pub enum MirPhase {
/// MIR, this is UB.
/// - Retags: If `-Zmir-emit-retag` is enabled, analysis MIR has "implicit" retags in the same way
/// that Rust itself has them. Where exactly these are is generally subject to change, and so we
- /// don't document this here. Runtime MIR has all retags explicit.
+ /// don't document this here. Runtime MIR has most retags explicit (though implicit retags
+ /// can still occur at `Rvalue::{Ref,AddrOf}`).
/// - Generator bodies: In analysis MIR, locals may actually be behind a pointer that user code has
/// access to. This occurs in generator bodies. Such locals do not behave like other locals,
/// because they eg may be aliased in surprising ways. Runtime MIR has no such special locals -
@@ -133,7 +135,6 @@ pub enum AnalysisPhase {
pub enum RuntimePhase {
/// In addition to the semantic changes, beginning with this phase, the following variants are
/// disallowed:
- /// * [`TerminatorKind::DropAndReplace`]
/// * [`TerminatorKind::Yield`]
/// * [`TerminatorKind::GeneratorDrop`]
/// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
@@ -219,6 +220,11 @@ pub enum BorrowKind {
/// immutable, but not aliasable. This solves the problem. For
/// simplicity, we don't give users the way to express this
/// borrow, it's just used when translating closures.
+ ///
+ // FIXME(#112072): This is wrong. Unique borrows are mutable borrows except
+ // that they do not require their pointee to be marked as a mutable.
+ // They should still be treated as mutable borrows in every other way,
+ // e.g. for variance or overlap checking.
Unique,
/// Data is mutable and not aliasable.
@@ -326,6 +332,15 @@ pub enum StatementKind<'tcx> {
/// Only `RetagKind::Default` and `RetagKind::FnEntry` are permitted.
Retag(RetagKind, Box<Place<'tcx>>),
+ /// This statement exists to preserve a trace of a scrutinee matched against a wildcard binding.
+ /// This is especially useful for `let _ = PLACE;` bindings that desugar to a single
+ /// `PlaceMention(PLACE)`.
+ ///
+ /// When executed at runtime this is a nop.
+ ///
+ /// Disallowed after drop elaboration.
+ PlaceMention(Box<Place<'tcx>>),
+
/// Encodes a user's type ascription. These need to be preserved
/// intact so that NLL can respect them. For example:
/// ```ignore (illustrative)
@@ -505,15 +520,15 @@ pub struct CopyNonOverlapping<'tcx> {
///
/// A note on unwinding: Panics may occur during the execution of some terminators. Depending on the
/// `-C panic` flag, this may either cause the program to abort or the call stack to unwind. Such
-/// terminators have a `cleanup: Option<BasicBlock>` field on them. If stack unwinding occurs, then
-/// once the current function is reached, execution continues at the given basic block, if any. If
-/// `cleanup` is `None` then no cleanup is performed, and the stack continues unwinding. This is
-/// equivalent to the execution of a `Resume` terminator.
+/// terminators have a `unwind: UnwindAction` field on them. If stack unwinding occurs, then
+/// once the current function is reached, an action will be taken based on the `unwind` field.
+/// If the action is `Cleanup`, then the execution continues at the given basic block. If the
+/// action is `Continue` then no cleanup is performed, and the stack continues unwinding.
///
-/// The basic block pointed to by a `cleanup` field must have its `cleanup` flag set. `cleanup`
-/// basic blocks have a couple restrictions:
-/// 1. All `cleanup` fields in them must be `None`.
-/// 2. `Return` terminators are not allowed in them. `Abort` and `Unwind` terminators are.
+/// The basic block pointed to by a `Cleanup` unwind action must have its `cleanup` flag set.
+/// `cleanup` basic blocks have a couple restrictions:
+/// 1. All `unwind` fields in them must be `UnwindAction::Terminate` or `UnwindAction::Unreachable`.
+/// 2. `Return` terminators are not allowed in them. `Terminate` and `Resume` terminators are.
/// 3. All other basic blocks (in the current body) that are reachable from `cleanup` basic blocks
/// must also be `cleanup`. This is a part of the type system and checked statically, so it is
/// still an error to have such an edge in the CFG even if it's known that it won't be taken at
@@ -555,11 +570,11 @@ pub enum TerminatorKind<'tcx> {
/// deaggregation runs.
Resume,
- /// Indicates that the landing pad is finished and that the process should abort.
+ /// Indicates that the landing pad is finished and that the process should terminate.
///
/// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in
/// cleanup blocks.
- Abort,
+ Terminate,
/// Returns from the function.
///
@@ -594,44 +609,7 @@ pub enum TerminatorKind<'tcx> {
/// > The drop glue is executed if, among all statements executed within this `Body`, an assignment to
/// > the place or one of its "parents" occurred more recently than a move out of it. This does not
/// > consider indirect assignments.
- Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> },
-
- /// Drops the place and assigns a new value to it.
- ///
- /// This first performs the exact same operation as the pre drop-elaboration `Drop` terminator;
- /// it then additionally assigns the `value` to the `place` as if by an assignment statement.
- /// This assignment occurs both in the unwind and the regular code paths. The semantics are best
- /// explained by the elaboration:
- ///
- /// ```ignore (MIR)
- /// BB0 {
- /// DropAndReplace(P <- V, goto BB1, unwind BB2)
- /// }
- /// ```
- ///
- /// becomes
- ///
- /// ```ignore (MIR)
- /// BB0 {
- /// Drop(P, goto BB1, unwind BB2)
- /// }
- /// BB1 {
- /// // P is now uninitialized
- /// P <- V
- /// }
- /// BB2 {
- /// // P is now uninitialized -- its dtor panicked
- /// P <- V
- /// }
- /// ```
- ///
- /// Disallowed after drop elaboration.
- DropAndReplace {
- place: Place<'tcx>,
- value: Operand<'tcx>,
- target: BasicBlock,
- unwind: Option<BasicBlock>,
- },
+ Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction },
/// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
/// the referred to function. The operand types must match the argument types of the function.
@@ -655,8 +633,8 @@ pub enum TerminatorKind<'tcx> {
destination: Place<'tcx>,
/// Where to go after this call returns. If none, the call necessarily diverges.
target: Option<BasicBlock>,
- /// Cleanups to be done if the call unwinds.
- cleanup: Option<BasicBlock>,
+ /// Action to be taken if the call unwinds.
+ unwind: UnwindAction,
/// `true` if this is from a call in HIR rather than from an overloaded
/// operator. True for overloaded function call.
from_hir_call: bool,
@@ -675,14 +653,13 @@ pub enum TerminatorKind<'tcx> {
/// When overflow checking is disabled and this is run-time MIR (as opposed to compile-time MIR
/// that is used for CTFE), the following variants of this terminator behave as `goto target`:
/// - `OverflowNeg(..)`,
- /// - `Overflow(op, ..)` if op is a "checkable" operation (add, sub, mul, shl, shr, but NOT
- /// div or rem).
+ /// - `Overflow(op, ..)` if op is add, sub, mul, shl, shr, but NOT div or rem.
Assert {
cond: Operand<'tcx>,
expected: bool,
msg: AssertMessage<'tcx>,
target: BasicBlock,
- cleanup: Option<BasicBlock>,
+ unwind: UnwindAction,
},
/// Marks a suspend point.
@@ -748,9 +725,8 @@ pub enum TerminatorKind<'tcx> {
/// in practice, but in order to avoid fragility we want to always
/// consider it in borrowck. We don't want to accept programs which
/// pass borrowck only when `panic=abort` or some assertions are disabled
- /// due to release vs. debug mode builds. This needs to be an `Option` because
- /// of the `remove_noop_landing_pads` and `abort_unwinding_calls` passes.
- unwind: Option<BasicBlock>,
+ /// due to release vs. debug mode builds.
+ unwind: UnwindAction,
},
/// Block ends with an inline assembly block. This is a terminator since
@@ -773,12 +749,31 @@ pub enum TerminatorKind<'tcx> {
/// diverging (InlineAsmOptions::NORETURN).
destination: Option<BasicBlock>,
- /// Cleanup to be done if the inline assembly unwinds. This is present
+ /// Action to be taken if the inline assembly unwinds. This is present
/// if and only if InlineAsmOptions::MAY_UNWIND is set.
- cleanup: Option<BasicBlock>,
+ unwind: UnwindAction,
},
}
+/// Action to be taken when a stack unwind happens.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub enum UnwindAction {
+ /// No action is to be taken. Continue unwinding.
+ ///
+ /// This is similar to `Cleanup(bb)` where `bb` does nothing but `Resume`, but they are not
+ /// equivalent, as presence of `Cleanup(_)` will make a frame non-POF.
+ Continue,
+ /// Triggers undefined behavior if unwind happens.
+ Unreachable,
+ /// Terminates the execution if unwind happens.
+ ///
+ /// Depending on the platform and situation this may cause a non-unwindable panic or abort.
+ Terminate,
+ /// Cleanups to be done.
+ Cleanup(BasicBlock),
+}
+
/// Information about an assertion failure.
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
pub enum AssertKind<O> {
@@ -789,6 +784,7 @@ pub enum AssertKind<O> {
RemainderByZero(O),
ResumedAfterReturn(GeneratorKind),
ResumedAfterPanic(GeneratorKind),
+ MisalignedPointerDereference { required: O, found: O },
}
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
@@ -917,7 +913,15 @@ pub struct Place<'tcx> {
#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub enum ProjectionElem<V, T> {
Deref,
- Field(Field, T),
+
+ /// A field (e.g., `f` in `_1.f`) is one variant of [`ProjectionElem`]. Conceptually,
+ /// rustc can identify that a field projection refers to either two different regions of memory
+ /// or the same one between the base and the 'projection element'.
+ /// Read more about projections in the [rustc-dev-guide][mir-datatypes]
+ ///
+ /// [mir-datatypes]: https://rustc-dev-guide.rust-lang.org/mir/index.html#mir-data-types
+ Field(FieldIdx, T),
+
/// Index into a slice/array.
///
/// Note that this does not also dereference, and so it does not exactly correspond to slice
@@ -1110,11 +1114,7 @@ pub enum Rvalue<'tcx> {
/// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
///
/// For addition, subtraction, and multiplication on integers the error condition is set when
- /// the infinite precision result would be unequal to the actual result.
- ///
- /// For shift operations on integers the error condition is set when the value of right-hand
- /// side is greater than or equal to the number of bits in the type of the left-hand side, or
- /// when the value of right-hand side is negative.
+ /// the infinite precision result would not be equal to the actual result.
///
/// Other combinations of types and operators are unsupported.
CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),
@@ -1149,7 +1149,7 @@ pub enum Rvalue<'tcx> {
///
/// Disallowed after deaggregation for all aggregate kinds except `Array` and `Generator`. After
/// generator lowering, `Generator` aggregate kinds are disallowed too.
- Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
+ Aggregate(Box<AggregateKind<'tcx>>, IndexVec<FieldIdx, Operand<'tcx>>),
/// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
///
@@ -1189,6 +1189,13 @@ pub enum CastKind {
IntToFloat,
PtrToPtr,
FnPtrToPtr,
+ /// Reinterpret the bits of the input as a different type.
+ ///
+ /// MIR is well-formed if the input and output types have different sizes,
+ /// but running a transmute between differently-sized types is UB.
+ ///
+ /// Allowed only in [`MirPhase::Runtime`]; Earlier it's a [`TerminatorKind::Call`].
+ Transmute,
}
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
@@ -1199,11 +1206,11 @@ pub enum AggregateKind<'tcx> {
Tuple,
/// The second field is the variant index. It's equal to 0 for struct
- /// and union expressions. The fourth field is
+ /// and union expressions. The last field is the
/// active field number and is present only for union expressions
/// -- e.g., for a union expression `SomeUnion { c: .. }`, the
/// active field index would identity the field `c`
- Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
+ Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<FieldIdx>),
Closure(DefId, SubstsRef<'tcx>),
Generator(DefId, SubstsRef<'tcx>, hir::Movability),
@@ -1280,7 +1287,7 @@ pub enum BinOp {
mod size_asserts {
use super::*;
// tidy-alphabetical-start
- static_assert_size!(AggregateKind<'_>, 40);
+ static_assert_size!(AggregateKind<'_>, 32);
static_assert_size!(Operand<'_>, 24);
static_assert_size!(Place<'_>, 16);
static_assert_size!(PlaceElem<'_>, 24);
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 0aa2c500f..4f00abf7f 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -6,7 +6,7 @@
use crate::mir::*;
use crate::ty::{self, Ty, TyCtxt};
use rustc_hir as hir;
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{FieldIdx, VariantIdx};
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct PlaceTy<'tcx> {
@@ -33,7 +33,7 @@ impl<'tcx> PlaceTy<'tcx> {
///
/// Note that the resulting type has not been normalized.
#[instrument(level = "debug", skip(tcx), ret)]
- pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> {
+ pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> {
match self.ty.kind() {
ty::Adt(adt_def, substs) => {
let variant_def = match self.variant_index {
@@ -43,7 +43,7 @@ impl<'tcx> PlaceTy<'tcx> {
&adt_def.variant(variant_index)
}
};
- let field_def = &variant_def.fields[f.index()];
+ let field_def = &variant_def.fields[f];
field_def.ty(tcx, substs)
}
ty::Tuple(tys) => tys[f.index()],
@@ -61,14 +61,14 @@ impl<'tcx> PlaceTy<'tcx> {
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
/// projects `place_ty` onto `elem`, returning the appropriate
/// `Ty` or downcast variant corresponding to that projection.
- /// The `handle_field` callback must map a `Field` to its `Ty`,
+ /// The `handle_field` callback must map a `FieldIdx` to its `Ty`,
/// (which should be trivial when `T` = `Ty`).
pub fn projection_ty_core<V, T>(
self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
elem: &ProjectionElem<V, T>,
- mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
+ mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>,
mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
) -> PlaceTy<'tcx>
where
@@ -98,7 +98,7 @@ impl<'tcx> PlaceTy<'tcx> {
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_target_usize(tcx, param_env);
- let len = size - (from as u64) - (to as u64);
+ let len = size - from - to;
tcx.mk_array(*inner, len)
}
_ => bug!("cannot subslice non-array type: `{:?}`", self),
@@ -116,7 +116,7 @@ impl<'tcx> PlaceTy<'tcx> {
}
impl<'tcx> Place<'tcx> {
- pub fn ty_from<D>(
+ pub fn ty_from<D: ?Sized>(
local: Local,
projection: &[PlaceElem<'tcx>],
local_decls: &D,
@@ -132,7 +132,7 @@ impl<'tcx> Place<'tcx> {
})
}
- pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
+ pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
where
D: HasLocalDecls<'tcx>,
{
@@ -141,7 +141,7 @@ impl<'tcx> Place<'tcx> {
}
impl<'tcx> PlaceRef<'tcx> {
- pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
+ pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
where
D: HasLocalDecls<'tcx>,
{
@@ -155,7 +155,7 @@ pub enum RvalueInitializationState {
}
impl<'tcx> Rvalue<'tcx> {
- pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
+ pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
where
D: HasLocalDecls<'tcx>,
{
@@ -164,17 +164,7 @@ impl<'tcx> Rvalue<'tcx> {
Rvalue::Repeat(ref operand, count) => {
tcx.mk_array_with_const_len(operand.ty(local_decls, tcx), count)
}
- Rvalue::ThreadLocalRef(did) => {
- let static_ty = tcx.type_of(did).subst_identity();
- if tcx.is_mutable_static(did) {
- tcx.mk_mut_ptr(static_ty)
- } else if tcx.is_foreign_item(did) {
- tcx.mk_imm_ptr(static_ty)
- } else {
- // FIXME: These things don't *really* have 'static lifetime.
- tcx.mk_imm_ref(tcx.lifetimes.re_static, static_ty)
- }
- }
+ Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did),
Rvalue::Ref(reg, bk, ref place) => {
let place_ty = place.ty(local_decls, tcx).ty;
tcx.mk_ref(reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() })
@@ -227,7 +217,7 @@ impl<'tcx> Rvalue<'tcx> {
}
impl<'tcx> Operand<'tcx> {
- pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
+ pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
where
D: HasLocalDecls<'tcx>,
{
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 6e905224c..2c6126cdd 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -1,6 +1,6 @@
use smallvec::SmallVec;
-use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind};
+use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction};
use rustc_ast::InlineAsmTemplatePiece;
pub use rustc_ast::Mutability;
use rustc_macros::HashStable;
@@ -118,11 +118,11 @@ impl<'tcx> Terminator<'tcx> {
self.kind.successors_mut()
}
- pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
+ pub fn unwind(&self) -> Option<&UnwindAction> {
self.kind.unwind()
}
- pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
+ pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> {
self.kind.unwind_mut()
}
}
@@ -135,35 +135,33 @@ impl<'tcx> TerminatorKind<'tcx> {
pub fn successors(&self) -> Successors<'_> {
use self::TerminatorKind::*;
match *self {
- Resume
- | Abort
- | GeneratorDrop
- | Return
- | Unreachable
- | Call { target: None, cleanup: None, .. }
- | InlineAsm { destination: None, cleanup: None, .. } => {
- None.into_iter().chain((&[]).into_iter().copied())
+ Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. }
+ | Yield { resume: t, drop: Some(ref u), .. }
+ | Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
+ | Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
+ | FalseUnwind { real_target: t, unwind: UnwindAction::Cleanup(ref u) }
+ | InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => {
+ Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
}
Goto { target: t }
- | Call { target: None, cleanup: Some(t), .. }
- | Call { target: Some(t), cleanup: None, .. }
+ | Call { target: None, unwind: UnwindAction::Cleanup(t), .. }
+ | Call { target: Some(t), unwind: _, .. }
| Yield { resume: t, drop: None, .. }
- | DropAndReplace { target: t, unwind: None, .. }
- | Drop { target: t, unwind: None, .. }
- | Assert { target: t, cleanup: None, .. }
- | FalseUnwind { real_target: t, unwind: None }
- | InlineAsm { destination: Some(t), cleanup: None, .. }
- | InlineAsm { destination: None, cleanup: Some(t), .. } => {
+ | Drop { target: t, unwind: _, .. }
+ | Assert { target: t, unwind: _, .. }
+ | FalseUnwind { real_target: t, unwind: _ }
+ | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. }
+ | InlineAsm { destination: Some(t), unwind: _, .. } => {
Some(t).into_iter().chain((&[]).into_iter().copied())
}
- Call { target: Some(t), cleanup: Some(ref u), .. }
- | Yield { resume: t, drop: Some(ref u), .. }
- | DropAndReplace { target: t, unwind: Some(ref u), .. }
- | Drop { target: t, unwind: Some(ref u), .. }
- | Assert { target: t, cleanup: Some(ref u), .. }
- | FalseUnwind { real_target: t, unwind: Some(ref u) }
- | InlineAsm { destination: Some(t), cleanup: Some(ref u), .. } => {
- Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
+ Resume
+ | Terminate
+ | GeneratorDrop
+ | Return
+ | Unreachable
+ | Call { target: None, unwind: _, .. }
+ | InlineAsm { destination: None, unwind: _, .. } => {
+ None.into_iter().chain((&[]).into_iter().copied())
}
SwitchInt { ref targets, .. } => {
None.into_iter().chain(targets.targets.iter().copied())
@@ -177,34 +175,34 @@ impl<'tcx> TerminatorKind<'tcx> {
pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
use self::TerminatorKind::*;
match *self {
- Resume
- | Abort
- | GeneratorDrop
- | Return
- | Unreachable
- | Call { target: None, cleanup: None, .. }
- | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&mut []),
+ Call { target: Some(ref mut t), unwind: UnwindAction::Cleanup(ref mut u), .. }
+ | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
+ | Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
+ | Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
+ | FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) }
+ | InlineAsm {
+ destination: Some(ref mut t),
+ unwind: UnwindAction::Cleanup(ref mut u),
+ ..
+ } => Some(t).into_iter().chain(slice::from_mut(u)),
Goto { target: ref mut t }
- | Call { target: None, cleanup: Some(ref mut t), .. }
- | Call { target: Some(ref mut t), cleanup: None, .. }
+ | Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
+ | Call { target: Some(ref mut t), unwind: _, .. }
| Yield { resume: ref mut t, drop: None, .. }
- | DropAndReplace { target: ref mut t, unwind: None, .. }
- | Drop { target: ref mut t, unwind: None, .. }
- | Assert { target: ref mut t, cleanup: None, .. }
- | FalseUnwind { real_target: ref mut t, unwind: None }
- | InlineAsm { destination: Some(ref mut t), cleanup: None, .. }
- | InlineAsm { destination: None, cleanup: Some(ref mut t), .. } => {
+ | Drop { target: ref mut t, unwind: _, .. }
+ | Assert { target: ref mut t, unwind: _, .. }
+ | FalseUnwind { real_target: ref mut t, unwind: _ }
+ | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
+ | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => {
Some(t).into_iter().chain(&mut [])
}
- Call { target: Some(ref mut t), cleanup: Some(ref mut u), .. }
- | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
- | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. }
- | Drop { target: ref mut t, unwind: Some(ref mut u), .. }
- | Assert { target: ref mut t, cleanup: Some(ref mut u), .. }
- | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) }
- | InlineAsm { destination: Some(ref mut t), cleanup: Some(ref mut u), .. } => {
- Some(t).into_iter().chain(slice::from_mut(u))
- }
+ Resume
+ | Terminate
+ | GeneratorDrop
+ | Return
+ | Unreachable
+ | Call { target: None, unwind: _, .. }
+ | InlineAsm { destination: None, unwind: _, .. } => None.into_iter().chain(&mut []),
SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets),
FalseEdge { ref mut real_target, ref mut imaginary_target } => {
Some(real_target).into_iter().chain(slice::from_mut(imaginary_target))
@@ -212,43 +210,41 @@ impl<'tcx> TerminatorKind<'tcx> {
}
}
- pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
+ pub fn unwind(&self) -> Option<&UnwindAction> {
match *self {
TerminatorKind::Goto { .. }
| TerminatorKind::Resume
- | TerminatorKind::Abort
+ | TerminatorKind::Terminate
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop
| TerminatorKind::Yield { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::FalseEdge { .. } => None,
- TerminatorKind::Call { cleanup: ref unwind, .. }
- | TerminatorKind::Assert { cleanup: ref unwind, .. }
- | TerminatorKind::DropAndReplace { ref unwind, .. }
+ TerminatorKind::Call { ref unwind, .. }
+ | TerminatorKind::Assert { ref unwind, .. }
| TerminatorKind::Drop { ref unwind, .. }
| TerminatorKind::FalseUnwind { ref unwind, .. }
- | TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind),
+ | TerminatorKind::InlineAsm { ref unwind, .. } => Some(unwind),
}
}
- pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
+ pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> {
match *self {
TerminatorKind::Goto { .. }
| TerminatorKind::Resume
- | TerminatorKind::Abort
+ | TerminatorKind::Terminate
| TerminatorKind::Return
| TerminatorKind::Unreachable
| TerminatorKind::GeneratorDrop
| TerminatorKind::Yield { .. }
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::FalseEdge { .. } => None,
- TerminatorKind::Call { cleanup: ref mut unwind, .. }
- | TerminatorKind::Assert { cleanup: ref mut unwind, .. }
- | TerminatorKind::DropAndReplace { ref mut unwind, .. }
+ TerminatorKind::Call { ref mut unwind, .. }
+ | TerminatorKind::Assert { ref mut unwind, .. }
| TerminatorKind::Drop { ref mut unwind, .. }
| TerminatorKind::FalseUnwind { ref mut unwind, .. }
- | TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind),
+ | TerminatorKind::InlineAsm { ref mut unwind, .. } => Some(unwind),
}
}
@@ -274,11 +270,17 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
let labels = self.fmt_successor_labels();
assert_eq!(successor_count, labels.len());
- match successor_count {
- 0 => Ok(()),
-
- 1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
-
+ let unwind = match self.unwind() {
+ // Not needed or included in successors
+ None | Some(UnwindAction::Continue) | Some(UnwindAction::Cleanup(_)) => None,
+ Some(UnwindAction::Unreachable) => Some("unwind unreachable"),
+ Some(UnwindAction::Terminate) => Some("unwind terminate"),
+ };
+
+ match (successor_count, unwind) {
+ (0, None) => Ok(()),
+ (0, Some(unwind)) => write!(fmt, " -> {}", unwind),
+ (1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
_ => {
write!(fmt, " -> [")?;
for (i, target) in self.successors().enumerate() {
@@ -287,6 +289,9 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
}
write!(fmt, "{}: {:?}", labels[i], target)?;
}
+ if let Some(unwind) = unwind {
+ write!(fmt, ", {unwind}")?;
+ }
write!(fmt, "]")
}
}
@@ -305,13 +310,10 @@ impl<'tcx> TerminatorKind<'tcx> {
Return => write!(fmt, "return"),
GeneratorDrop => write!(fmt, "generator_drop"),
Resume => write!(fmt, "resume"),
- Abort => write!(fmt, "abort"),
+ Terminate => write!(fmt, "abort"),
Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value),
Unreachable => write!(fmt, "unreachable"),
Drop { place, .. } => write!(fmt, "drop({:?})", place),
- DropAndReplace { place, value, .. } => {
- write!(fmt, "replace({:?} <- {:?})", place, value)
- }
Call { func, args, destination, .. } => {
write!(fmt, "{:?} = ", destination)?;
write!(fmt, "{:?}(", func)?;
@@ -387,7 +389,7 @@ impl<'tcx> TerminatorKind<'tcx> {
pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
use self::TerminatorKind::*;
match *self {
- Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
+ Return | Resume | Terminate | Unreachable | GeneratorDrop => vec![],
Goto { .. } => vec!["".into()],
SwitchInt { ref targets, .. } => targets
.values
@@ -395,31 +397,35 @@ impl<'tcx> TerminatorKind<'tcx> {
.map(|&u| Cow::Owned(u.to_string()))
.chain(iter::once("otherwise".into()))
.collect(),
- Call { target: Some(_), cleanup: Some(_), .. } => {
+ Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
vec!["return".into(), "unwind".into()]
}
- Call { target: Some(_), cleanup: None, .. } => vec!["return".into()],
- Call { target: None, cleanup: Some(_), .. } => vec!["unwind".into()],
- Call { target: None, cleanup: None, .. } => vec![],
+ Call { target: Some(_), unwind: _, .. } => vec!["return".into()],
+ Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()],
+ Call { target: None, unwind: _, .. } => vec![],
Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
Yield { drop: None, .. } => vec!["resume".into()],
- DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => {
- vec!["return".into()]
- }
- DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => {
- vec!["return".into(), "unwind".into()]
+ Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
+ Drop { unwind: _, .. } => vec!["return".into()],
+ Assert { unwind: UnwindAction::Cleanup(_), .. } => {
+ vec!["success".into(), "unwind".into()]
}
- Assert { cleanup: None, .. } => vec!["".into()],
- Assert { .. } => vec!["success".into(), "unwind".into()],
+ Assert { unwind: _, .. } => vec!["success".into()],
FalseEdge { .. } => vec!["real".into(), "imaginary".into()],
- FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
- FalseUnwind { unwind: None, .. } => vec!["real".into()],
- InlineAsm { destination: Some(_), cleanup: Some(_), .. } => {
+ FalseUnwind { unwind: UnwindAction::Cleanup(_), .. } => {
+ vec!["real".into(), "unwind".into()]
+ }
+ FalseUnwind { unwind: _, .. } => vec!["real".into()],
+ InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
vec!["return".into(), "unwind".into()]
}
- InlineAsm { destination: Some(_), cleanup: None, .. } => vec!["return".into()],
- InlineAsm { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()],
- InlineAsm { destination: None, cleanup: None, .. } => vec![],
+ InlineAsm { destination: Some(_), unwind: _, .. } => {
+ vec!["return".into()]
+ }
+ InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => {
+ vec!["unwind".into()]
+ }
+ InlineAsm { destination: None, unwind: _, .. } => vec![],
}
}
}
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index f37222cb2..7d247eeb6 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -101,7 +101,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
///
/// A Postorder traversal of this graph is `D B C A` or `D C B A`
pub struct Postorder<'a, 'tcx> {
- basic_blocks: &'a IndexVec<BasicBlock, BasicBlockData<'tcx>>,
+ basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
visited: BitSet<BasicBlock>,
visit_stack: Vec<(BasicBlock, Successors<'a>)>,
root_is_start_block: bool,
@@ -109,7 +109,7 @@ pub struct Postorder<'a, 'tcx> {
impl<'a, 'tcx> Postorder<'a, 'tcx> {
pub fn new(
- basic_blocks: &'a IndexVec<BasicBlock, BasicBlockData<'tcx>>,
+ basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
root: BasicBlock,
) -> Postorder<'a, 'tcx> {
let mut po = Postorder {
@@ -178,17 +178,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
// When we yield `B` and call `traverse_successor`, we push `C` to the stack, but
// since we've already visited `E`, that child isn't added to the stack. The last
// two iterations yield `C` and finally `A` for a final traversal of [E, D, B, C, A]
- loop {
- let bb = if let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() {
- if let Some(bb) = iter.next() {
- bb
- } else {
- break;
- }
- } else {
- break;
- };
-
+ while let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() && let Some(bb) = iter.next() {
if self.visited.insert(bb) {
if let Some(term) = &self.basic_blocks[bb].terminator {
self.visit_stack.push((bb, term.successors()));
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 5c056b299..caa5edc32 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -335,12 +335,14 @@ macro_rules! make_mir_visitor {
ty::InstanceDef::VTableShim(_def_id) |
ty::InstanceDef::ReifyShim(_def_id) |
ty::InstanceDef::Virtual(_def_id, _) |
+ ty::InstanceDef::ThreadLocalShim(_def_id) |
ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
ty::InstanceDef::DropGlue(_def_id, None) => {}
ty::InstanceDef::FnPtrShim(_def_id, ty) |
ty::InstanceDef::DropGlue(_def_id, Some(ty)) |
- ty::InstanceDef::CloneShim(_def_id, ty) => {
+ ty::InstanceDef::CloneShim(_def_id, ty) |
+ ty::InstanceDef::FnPtrAddrShim(_def_id, ty) => {
// FIXME(eddyb) use a better `TyContext` here.
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
}
@@ -405,6 +407,13 @@ macro_rules! make_mir_visitor {
StatementKind::Retag(kind, place) => {
self.visit_retag($(& $mutability)? *kind, place, location);
}
+ StatementKind::PlaceMention(place) => {
+ self.visit_place(
+ place,
+ PlaceContext::NonUse(NonUseContext::PlaceMention),
+ location
+ );
+ }
StatementKind::AscribeUserType(
box (place, user_ty),
variance
@@ -453,7 +462,7 @@ macro_rules! make_mir_visitor {
match kind {
TerminatorKind::Goto { .. } |
TerminatorKind::Resume |
- TerminatorKind::Abort |
+ TerminatorKind::Terminate |
TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable |
TerminatorKind::FalseEdge { .. } |
@@ -495,26 +504,12 @@ macro_rules! make_mir_visitor {
);
}
- TerminatorKind::DropAndReplace {
- place,
- value,
- target: _,
- unwind: _,
- } => {
- self.visit_place(
- place,
- PlaceContext::MutatingUse(MutatingUseContext::Drop),
- location
- );
- self.visit_operand(value, location);
- }
-
TerminatorKind::Call {
func,
args,
destination,
target: _,
- cleanup: _,
+ unwind: _,
from_hir_call: _,
fn_span: _
} => {
@@ -534,7 +529,7 @@ macro_rules! make_mir_visitor {
expected: _,
msg,
target: _,
- cleanup: _,
+ unwind: _,
} => {
self.visit_operand(cond, location);
self.visit_assert_message(msg, location);
@@ -560,7 +555,7 @@ macro_rules! make_mir_visitor {
options: _,
line_spans: _,
destination: _,
- cleanup: _,
+ unwind: _,
} => {
for op in operands {
match op {
@@ -615,6 +610,10 @@ macro_rules! make_mir_visitor {
ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
// Nothing to visit
}
+ MisalignedPointerDereference { required, found } => {
+ self.visit_operand(required, location);
+ self.visit_operand(found, location);
+ }
}
}
@@ -641,8 +640,8 @@ macro_rules! make_mir_visitor {
BorrowKind::Shallow => PlaceContext::NonMutatingUse(
NonMutatingUseContext::ShallowBorrow
),
- BorrowKind::Unique => PlaceContext::NonMutatingUse(
- NonMutatingUseContext::UniqueBorrow
+ BorrowKind::Unique => PlaceContext::MutatingUse(
+ MutatingUseContext::Borrow
),
BorrowKind::Mut { .. } =>
PlaceContext::MutatingUse(MutatingUseContext::Borrow),
@@ -811,7 +810,6 @@ macro_rules! make_mir_visitor {
source_info,
internal: _,
local_info: _,
- is_block_tail: _,
} = local_decl;
self.visit_ty($(& $mutability)? *ty, TyContext::LocalDecl {
@@ -834,6 +832,7 @@ macro_rules! make_mir_visitor {
name: _,
source_info,
value,
+ argument_index: _,
} = var_debug_info;
self.visit_source_info(source_info);
@@ -1248,8 +1247,6 @@ pub enum NonMutatingUseContext {
SharedBorrow,
/// Shallow borrow.
ShallowBorrow,
- /// Unique borrow.
- UniqueBorrow,
/// AddressOf for *const pointer.
AddressOf,
/// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
@@ -1302,6 +1299,8 @@ pub enum NonUseContext {
AscribeUserTy,
/// The data of a user variable, for debug info.
VarDebugInfo,
+ /// PlaceMention statement.
+ PlaceMention,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -1323,9 +1322,7 @@ impl PlaceContext {
matches!(
self,
PlaceContext::NonMutatingUse(
- NonMutatingUseContext::SharedBorrow
- | NonMutatingUseContext::ShallowBorrow
- | NonMutatingUseContext::UniqueBorrow
+ NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::ShallowBorrow
) | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
)
}
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
new file mode 100644
index 000000000..7d9aea022
--- /dev/null
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -0,0 +1,336 @@
+use crate::mir;
+use crate::traits;
+use crate::ty::{self, Ty};
+use std::mem::{size_of, transmute_copy, MaybeUninit};
+
+#[derive(Copy, Clone)]
+pub struct Erased<T: Copy> {
+ // We use `MaybeUninit` here so we can store any value
+ // in `data` since we aren't actually storing a `T`.
+ data: MaybeUninit<T>,
+}
+
+pub trait EraseType: Copy {
+ type Result: Copy;
+}
+
+// Allow `type_alias_bounds` since compilation will fail without `EraseType`.
+#[allow(type_alias_bounds)]
+pub type Erase<T: EraseType> = Erased<impl Copy>;
+
+#[inline(always)]
+pub fn erase<T: EraseType>(src: T) -> Erase<T> {
+ // Ensure the sizes match
+ const {
+ if std::mem::size_of::<T>() != std::mem::size_of::<T::Result>() {
+ panic!("size of T must match erased type T::Result")
+ }
+ };
+
+ Erased::<<T as EraseType>::Result> {
+ // SAFETY: Is it safe to transmute to MaybeUninit for types with the same sizes.
+ data: unsafe { transmute_copy(&src) },
+ }
+}
+
+/// Restores an erased value.
+#[inline(always)]
+pub fn restore<T: EraseType>(value: Erase<T>) -> T {
+ let value: Erased<<T as EraseType>::Result> = value;
+ // SAFETY: Due to the use of impl Trait in `Erase` the only way to safely create an instance
+ // of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of
+ // the right size.
+ unsafe { transmute_copy(&value.data) }
+}
+
+impl<T> EraseType for &'_ T {
+ type Result = [u8; size_of::<*const ()>()];
+}
+
+impl<T> EraseType for &'_ [T] {
+ type Result = [u8; size_of::<*const [()]>()];
+}
+
+impl<T> EraseType for &'_ ty::List<T> {
+ type Result = [u8; size_of::<*const ()>()];
+}
+
+impl<T> EraseType for Result<&'_ T, traits::query::NoSolution> {
+ type Result = [u8; size_of::<Result<&'static (), traits::query::NoSolution>>()];
+}
+
+impl<T> EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> {
+ type Result = [u8; size_of::<Result<&'static (), rustc_errors::ErrorGuaranteed>>()];
+}
+
+impl<T> EraseType for Result<&'_ T, traits::CodegenObligationError> {
+ type Result = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()];
+}
+
+impl<T> EraseType for Result<&'_ T, ty::layout::FnAbiError<'_>> {
+ type Result = [u8; size_of::<Result<&'static (), ty::layout::FnAbiError<'static>>>()];
+}
+
+impl<T> EraseType for Result<(&'_ T, rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed> {
+ type Result = [u8; size_of::<
+ Result<(&'static (), rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed>,
+ >()];
+}
+
+impl EraseType for Result<Option<ty::Instance<'_>>, rustc_errors::ErrorGuaranteed> {
+ type Result =
+ [u8; size_of::<Result<Option<ty::Instance<'static>>, rustc_errors::ErrorGuaranteed>>()];
+}
+
+impl EraseType for Result<Option<ty::Const<'_>>, rustc_errors::ErrorGuaranteed> {
+ type Result =
+ [u8; size_of::<Result<Option<ty::Const<'static>>, rustc_errors::ErrorGuaranteed>>()];
+}
+
+impl EraseType for Result<ty::GenericArg<'_>, traits::query::NoSolution> {
+ type Result = [u8; size_of::<Result<ty::GenericArg<'static>, traits::query::NoSolution>>()];
+}
+
+impl EraseType for Result<bool, ty::layout::LayoutError<'_>> {
+ type Result = [u8; size_of::<Result<bool, ty::layout::LayoutError<'static>>>()];
+}
+
+impl EraseType for Result<rustc_target::abi::TyAndLayout<'_, Ty<'_>>, ty::layout::LayoutError<'_>> {
+ type Result = [u8; size_of::<
+ Result<
+ rustc_target::abi::TyAndLayout<'static, Ty<'static>>,
+ ty::layout::LayoutError<'static>,
+ >,
+ >()];
+}
+
+impl EraseType for Result<ty::Const<'_>, mir::interpret::LitToConstError> {
+ type Result = [u8; size_of::<Result<ty::Const<'static>, mir::interpret::LitToConstError>>()];
+}
+
+impl EraseType for Result<mir::ConstantKind<'_>, mir::interpret::LitToConstError> {
+ type Result =
+ [u8; size_of::<Result<mir::ConstantKind<'static>, mir::interpret::LitToConstError>>()];
+}
+
+impl EraseType for Result<mir::interpret::ConstAlloc<'_>, mir::interpret::ErrorHandled> {
+ type Result = [u8; size_of::<
+ Result<mir::interpret::ConstAlloc<'static>, mir::interpret::ErrorHandled>,
+ >()];
+}
+
+impl EraseType for Result<mir::interpret::ConstValue<'_>, mir::interpret::ErrorHandled> {
+ type Result = [u8; size_of::<
+ Result<mir::interpret::ConstValue<'static>, mir::interpret::ErrorHandled>,
+ >()];
+}
+
+impl EraseType for Result<Option<ty::ValTree<'_>>, mir::interpret::ErrorHandled> {
+ type Result =
+ [u8; size_of::<Result<Option<ty::ValTree<'static>>, mir::interpret::ErrorHandled>>()];
+}
+
+impl EraseType for Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop> {
+ type Result =
+ [u8; size_of::<Result<&'static ty::List<Ty<'static>>, ty::util::AlwaysRequiresDrop>>()];
+}
+
+impl<T> EraseType for Option<&'_ T> {
+ type Result = [u8; size_of::<Option<&'static ()>>()];
+}
+
+impl<T> EraseType for Option<&'_ [T]> {
+ type Result = [u8; size_of::<Option<&'static [()]>>()];
+}
+
+impl EraseType for Option<rustc_middle::hir::Owner<'_>> {
+ type Result = [u8; size_of::<Option<rustc_middle::hir::Owner<'static>>>()];
+}
+
+impl EraseType for Option<mir::DestructuredConstant<'_>> {
+ type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
+}
+
+impl EraseType for Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
+ type Result = [u8; size_of::<Option<ty::EarlyBinder<ty::TraitRef<'static>>>>()];
+}
+
+impl EraseType for Option<ty::EarlyBinder<Ty<'_>>> {
+ type Result = [u8; size_of::<Option<ty::EarlyBinder<Ty<'static>>>>()];
+}
+
+impl<T> EraseType for rustc_hir::MaybeOwner<&'_ T> {
+ type Result = [u8; size_of::<rustc_hir::MaybeOwner<&'static ()>>()];
+}
+
+impl<T: EraseType> EraseType for ty::EarlyBinder<T> {
+ type Result = T::Result;
+}
+
+impl EraseType for ty::Binder<'_, ty::FnSig<'_>> {
+ type Result = [u8; size_of::<ty::Binder<'static, ty::FnSig<'static>>>()];
+}
+
+impl<T0, T1> EraseType for (&'_ T0, &'_ T1) {
+ type Result = [u8; size_of::<(&'static (), &'static ())>()];
+}
+
+impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) {
+ type Result = [u8; size_of::<(&'static (), &'static [()])>()];
+}
+
+macro_rules! trivial {
+ ($($ty:ty),+ $(,)?) => {
+ $(
+ impl EraseType for $ty {
+ type Result = [u8; size_of::<$ty>()];
+ }
+ )*
+ }
+}
+
+trivial! {
+ (),
+ bool,
+ Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>,
+ Option<rustc_ast::expand::allocator::AllocatorKind>,
+ Option<rustc_attr::ConstStability>,
+ Option<rustc_attr::DefaultBodyStability>,
+ Option<rustc_attr::Stability>,
+ Option<rustc_data_structures::svh::Svh>,
+ Option<rustc_hir::def::DefKind>,
+ Option<rustc_hir::GeneratorKind>,
+ Option<rustc_hir::HirId>,
+ Option<rustc_middle::middle::stability::DeprecationEntry>,
+ Option<rustc_middle::ty::Destructor>,
+ Option<rustc_middle::ty::ImplTraitInTraitData>,
+ Option<rustc_span::def_id::CrateNum>,
+ Option<rustc_span::def_id::DefId>,
+ Option<rustc_span::def_id::LocalDefId>,
+ Option<rustc_span::Span>,
+ Option<rustc_target::spec::PanicStrategy>,
+ Option<usize>,
+ Result<(), rustc_errors::ErrorGuaranteed>,
+ Result<(), rustc_middle::traits::query::NoSolution>,
+ Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>,
+ rustc_ast::expand::allocator::AllocatorKind,
+ rustc_attr::ConstStability,
+ rustc_attr::DefaultBodyStability,
+ rustc_attr::Deprecation,
+ rustc_attr::Stability,
+ rustc_data_structures::svh::Svh,
+ rustc_errors::ErrorGuaranteed,
+ rustc_hir::Constness,
+ rustc_hir::def_id::DefId,
+ rustc_hir::def_id::DefIndex,
+ rustc_hir::def_id::LocalDefId,
+ rustc_hir::def::DefKind,
+ rustc_hir::Defaultness,
+ rustc_hir::definitions::DefKey,
+ rustc_hir::GeneratorKind,
+ rustc_hir::HirId,
+ rustc_hir::IsAsync,
+ rustc_hir::ItemLocalId,
+ rustc_hir::LangItem,
+ rustc_hir::OwnerId,
+ rustc_hir::Upvar,
+ rustc_index::bit_set::FiniteBitSet<u32>,
+ rustc_middle::middle::dependency_format::Linkage,
+ rustc_middle::middle::exported_symbols::SymbolExportInfo,
+ rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault,
+ rustc_middle::middle::resolve_bound_vars::ResolvedArg,
+ rustc_middle::middle::stability::DeprecationEntry,
+ rustc_middle::mir::ConstQualifs,
+ rustc_middle::mir::interpret::AllocId,
+ rustc_middle::mir::interpret::ErrorHandled,
+ rustc_middle::mir::interpret::LitToConstError,
+ rustc_middle::thir::ExprId,
+ rustc_middle::traits::CodegenObligationError,
+ rustc_middle::traits::EvaluationResult,
+ rustc_middle::traits::OverflowError,
+ rustc_middle::traits::query::NoSolution,
+ rustc_middle::traits::WellFormedLoc,
+ rustc_middle::ty::adjustment::CoerceUnsizedInfo,
+ rustc_middle::ty::AssocItem,
+ rustc_middle::ty::AssocItemContainer,
+ rustc_middle::ty::BoundVariableKind,
+ rustc_middle::ty::DeducedParamAttrs,
+ rustc_middle::ty::Destructor,
+ rustc_middle::ty::fast_reject::SimplifiedType,
+ rustc_middle::ty::ImplPolarity,
+ rustc_middle::ty::Representability,
+ rustc_middle::ty::ReprOptions,
+ rustc_middle::ty::UnusedGenericParams,
+ rustc_middle::ty::util::AlwaysRequiresDrop,
+ rustc_middle::ty::Visibility<rustc_span::def_id::DefId>,
+ rustc_session::config::CrateType,
+ rustc_session::config::EntryFnType,
+ rustc_session::config::OptLevel,
+ rustc_session::config::SymbolManglingVersion,
+ rustc_session::cstore::CrateDepKind,
+ rustc_session::cstore::ExternCrate,
+ rustc_session::cstore::LinkagePreference,
+ rustc_session::Limits,
+ rustc_session::lint::LintExpectationId,
+ rustc_span::def_id::CrateNum,
+ rustc_span::def_id::DefPathHash,
+ rustc_span::ExpnHash,
+ rustc_span::ExpnId,
+ rustc_span::Span,
+ rustc_span::Symbol,
+ rustc_span::symbol::Ident,
+ rustc_target::spec::PanicStrategy,
+ rustc_type_ir::Variance,
+ u32,
+ usize,
+}
+
+macro_rules! tcx_lifetime {
+ ($($($fake_path:ident)::+),+ $(,)?) => {
+ $(
+ impl<'tcx> EraseType for $($fake_path)::+<'tcx> {
+ type Result = [u8; size_of::<$($fake_path)::+<'static>>()];
+ }
+ )*
+ }
+}
+
+tcx_lifetime! {
+ rustc_middle::hir::Owner,
+ rustc_middle::middle::exported_symbols::ExportedSymbol,
+ rustc_middle::mir::ConstantKind,
+ rustc_middle::mir::DestructuredConstant,
+ rustc_middle::mir::interpret::ConstAlloc,
+ rustc_middle::mir::interpret::ConstValue,
+ rustc_middle::mir::interpret::GlobalId,
+ rustc_middle::mir::interpret::LitToConstInput,
+ rustc_middle::traits::ChalkEnvironmentAndGoal,
+ rustc_middle::traits::query::MethodAutoderefStepsResult,
+ rustc_middle::traits::query::type_op::AscribeUserType,
+ rustc_middle::traits::query::type_op::Eq,
+ rustc_middle::traits::query::type_op::ProvePredicate,
+ rustc_middle::traits::query::type_op::Subtype,
+ rustc_middle::ty::AdtDef,
+ rustc_middle::ty::AliasTy,
+ rustc_middle::ty::Clause,
+ rustc_middle::ty::ClosureTypeInfo,
+ rustc_middle::ty::Const,
+ rustc_middle::ty::DestructuredConst,
+ rustc_middle::ty::ExistentialTraitRef,
+ rustc_middle::ty::FnSig,
+ rustc_middle::ty::GenericArg,
+ rustc_middle::ty::GenericPredicates,
+ rustc_middle::ty::inhabitedness::InhabitedPredicate,
+ rustc_middle::ty::Instance,
+ rustc_middle::ty::InstanceDef,
+ rustc_middle::ty::layout::FnAbiError,
+ rustc_middle::ty::layout::LayoutError,
+ rustc_middle::ty::ParamEnv,
+ rustc_middle::ty::Predicate,
+ rustc_middle::ty::SymbolName,
+ rustc_middle::ty::TraitRef,
+ rustc_middle::ty::Ty,
+ rustc_middle::ty::UnevaluatedConst,
+ rustc_middle::ty::ValTree,
+ rustc_middle::ty::VtblEntry,
+}
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 78ee8a6a8..23b28ac5c 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -12,6 +12,11 @@ use rustc_hir::hir_id::{HirId, OwnerId};
use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
+use rustc_target::abi::FieldIdx;
+
+/// Placeholder for `CrateNum`'s "local" counterpart
+#[derive(Copy, Clone, Debug)]
+pub struct LocalCrate;
/// The `Key` trait controls what types can legally be used as the key
/// for a query.
@@ -21,15 +26,11 @@ pub trait Key: Sized {
//
// ...But r-a doesn't support them yet and using a default here causes r-a to not infer
// return types of queries which is very annoying. Thus, until r-a support associated
- // type defaults, plese restrain from using them here <3
+ // type defaults, please restrain from using them here <3
//
// r-a issue: <https://github.com/rust-lang/rust-analyzer/issues/13693>
type CacheSelector;
- /// Given an instance of this key, what crate is it referring to?
- /// This is used to find the provider.
- fn query_crate_is_local(&self) -> bool;
-
/// In the event that a cycle occurs, if no explicit span has been
/// given for a query with key `self`, what span should we use?
fn default_span(&self, tcx: TyCtxt<'_>) -> Span;
@@ -45,14 +46,17 @@ pub trait Key: Sized {
}
}
+pub trait AsLocalKey: Key {
+ type LocalKey;
+
+ /// Given an instance of this key, what crate is it referring to?
+ /// This is used to find the provider.
+ fn as_local_key(&self) -> Option<Self::LocalKey>;
+}
+
impl Key for () {
type CacheSelector = SingleCacheSelector;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -61,23 +65,22 @@ impl Key for () {
impl<'tcx> Key for ty::InstanceDef<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.def_id())
}
}
-impl<'tcx> Key for ty::Instance<'tcx> {
- type CacheSelector = DefaultCacheSelector<Self>;
+impl<'tcx> AsLocalKey for ty::InstanceDef<'tcx> {
+ type LocalKey = Self;
#[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
+ fn as_local_key(&self) -> Option<Self::LocalKey> {
+ self.def_id().is_local().then(|| *self)
}
+}
+
+impl<'tcx> Key for ty::Instance<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.def_id())
@@ -87,11 +90,6 @@ impl<'tcx> Key for ty::Instance<'tcx> {
impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.instance.default_span(tcx)
}
@@ -100,11 +98,6 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -113,11 +106,6 @@ impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -126,25 +114,27 @@ impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
impl Key for CrateNum {
type CacheSelector = VecCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- *self == LOCAL_CRATE
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
-impl Key for OwnerId {
- type CacheSelector = VecCacheSelector<Self>;
+impl AsLocalKey for CrateNum {
+ type LocalKey = LocalCrate;
#[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
+ fn as_local_key(&self) -> Option<Self::LocalKey> {
+ (*self == LOCAL_CRATE).then_some(LocalCrate)
}
+}
+
+impl Key for OwnerId {
+ type CacheSelector = VecCacheSelector<Self>;
+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.to_def_id().default_span(tcx)
}
+
fn key_as_def_id(&self) -> Option<DefId> {
Some(self.to_def_id())
}
@@ -153,13 +143,10 @@ impl Key for OwnerId {
impl Key for LocalDefId {
type CacheSelector = VecCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.to_def_id().default_span(tcx)
}
+
fn key_as_def_id(&self) -> Option<DefId> {
Some(self.to_def_id())
}
@@ -168,26 +155,28 @@ impl Key for LocalDefId {
impl Key for DefId {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.krate == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(*self)
}
+
#[inline(always)]
fn key_as_def_id(&self) -> Option<DefId> {
Some(*self)
}
}
-impl Key for ty::WithOptConstParam<LocalDefId> {
- type CacheSelector = DefaultCacheSelector<Self>;
+impl AsLocalKey for DefId {
+ type LocalKey = LocalDefId;
#[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
+ fn as_local_key(&self) -> Option<Self::LocalKey> {
+ self.as_local()
}
+}
+
+impl Key for ty::WithOptConstParam<LocalDefId> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.did.default_span(tcx)
}
@@ -196,10 +185,6 @@ impl Key for ty::WithOptConstParam<LocalDefId> {
impl Key for SimplifiedType {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -208,10 +193,6 @@ impl Key for SimplifiedType {
impl Key for (DefId, DefId) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.0.krate == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.1.default_span(tcx)
}
@@ -220,10 +201,6 @@ impl Key for (DefId, DefId) {
impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
@@ -232,10 +209,6 @@ impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) {
impl Key for (DefId, LocalDefId) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.0.krate == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.1.default_span(tcx)
}
@@ -244,10 +217,6 @@ impl Key for (DefId, LocalDefId) {
impl Key for (LocalDefId, DefId) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
@@ -256,38 +225,27 @@ impl Key for (LocalDefId, DefId) {
impl Key for (LocalDefId, LocalDefId) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
}
-impl Key for (DefId, Option<Ident>) {
+impl Key for (DefId, Ident) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.0.krate == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.0)
}
+
#[inline(always)]
fn key_as_def_id(&self) -> Option<DefId> {
Some(self.0)
}
}
-impl Key for (DefId, LocalDefId, Ident) {
+impl Key for (LocalDefId, LocalDefId, Ident) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.0.krate == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.1.default_span(tcx)
}
@@ -296,34 +254,40 @@ impl Key for (DefId, LocalDefId, Ident) {
impl Key for (CrateNum, DefId) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.0 == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.1.default_span(tcx)
}
}
-impl Key for (CrateNum, SimplifiedType) {
- type CacheSelector = DefaultCacheSelector<Self>;
+impl AsLocalKey for (CrateNum, DefId) {
+ type LocalKey = DefId;
#[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.0 == LOCAL_CRATE
+ fn as_local_key(&self) -> Option<Self::LocalKey> {
+ (self.0 == LOCAL_CRATE).then(|| self.1)
}
+}
+
+impl Key for (CrateNum, SimplifiedType) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
-impl Key for (DefId, SimplifiedType) {
- type CacheSelector = DefaultCacheSelector<Self>;
+impl AsLocalKey for (CrateNum, SimplifiedType) {
+ type LocalKey = SimplifiedType;
#[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.0.krate == LOCAL_CRATE
+ fn as_local_key(&self) -> Option<Self::LocalKey> {
+ (self.0 == LOCAL_CRATE).then(|| self.1)
}
+}
+
+impl Key for (DefId, SimplifiedType) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
@@ -332,10 +296,6 @@ impl Key for (DefId, SimplifiedType) {
impl<'tcx> Key for SubstsRef<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -344,10 +304,6 @@ impl<'tcx> Key for SubstsRef<'tcx> {
impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.0.krate == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
@@ -356,10 +312,6 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- (self.0).def.did.krate == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
(self.0).def.did.default_span(tcx)
}
@@ -368,10 +320,6 @@ impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
@@ -380,22 +328,14 @@ impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.1.def_id().krate == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.1.def_id())
}
}
-impl<'tcx> Key for (ty::Const<'tcx>, mir::Field) {
+impl<'tcx> Key for (ty::Const<'tcx>, FieldIdx) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -404,10 +344,6 @@ impl<'tcx> Key for (ty::Const<'tcx>, mir::Field) {
impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -416,10 +352,6 @@ impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.def_id().krate == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.def_id())
}
@@ -428,10 +360,6 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.def_id().krate == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.def_id())
}
@@ -440,10 +368,6 @@ impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.0.def_id().krate == LOCAL_CRATE
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.0.def_id())
}
@@ -452,10 +376,6 @@ impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
impl<'tcx> Key for GenericArg<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -464,10 +384,6 @@ impl<'tcx> Key for GenericArg<'tcx> {
impl<'tcx> Key for mir::ConstantKind<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -476,10 +392,6 @@ impl<'tcx> Key for mir::ConstantKind<'tcx> {
impl<'tcx> Key for ty::Const<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -488,13 +400,10 @@ impl<'tcx> Key for ty::Const<'tcx> {
impl<'tcx> Key for Ty<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
+
fn ty_adt_id(&self) -> Option<DefId> {
match self.kind() {
ty::Adt(adt, _) => Some(adt.did()),
@@ -506,10 +415,6 @@ impl<'tcx> Key for Ty<'tcx> {
impl<'tcx> Key for TyAndLayout<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -518,10 +423,6 @@ impl<'tcx> Key for TyAndLayout<'tcx> {
impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -530,10 +431,6 @@ impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -542,10 +439,6 @@ impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
impl<'tcx> Key for ty::ParamEnv<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -554,10 +447,6 @@ impl<'tcx> Key for ty::ParamEnv<'tcx> {
impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- self.value.query_crate_is_local()
- }
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.value.default_span(tcx)
}
@@ -566,10 +455,6 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
impl Key for Symbol {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -578,10 +463,6 @@ impl Key for Symbol {
impl Key for Option<Symbol> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -589,14 +470,9 @@ impl Key for Option<Symbol> {
/// Canonical query goals correspond to abstract trait operations that
/// are not tied to any crate in particular.
-impl<'tcx, T> Key for Canonical<'tcx, T> {
+impl<'tcx, T: Clone> Key for Canonical<'tcx, T> {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -605,11 +481,6 @@ impl<'tcx, T> Key for Canonical<'tcx, T> {
impl Key for (Symbol, u32, u32) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -618,11 +489,6 @@ impl Key for (Symbol, u32, u32) {
impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -631,11 +497,6 @@ impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -644,11 +505,6 @@ impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -657,11 +513,6 @@ impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
@@ -670,11 +521,6 @@ impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -683,11 +529,6 @@ impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
impl Key for HirId {
type CacheSelector = DefaultCacheSelector<Self>;
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
-
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.hir().span(*self)
}
@@ -702,10 +543,6 @@ impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
type CacheSelector = DefaultCacheSelector<Self>;
// Just forward to `Ty<'tcx>`
- #[inline(always)]
- fn query_crate_is_local(&self) -> bool {
- true
- }
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 5133da342..7a5a16035 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -7,8 +7,9 @@
use crate::ty::{self, print::describe_as_module, TyCtxt};
use rustc_span::def_id::LOCAL_CRATE;
+pub mod erase;
mod keys;
-pub use keys::Key;
+pub use keys::{AsLocalKey, Key, LocalCrate};
// Each of these queries corresponds to a function pointer field in the
// `Providers` struct for requesting a value of that type, and a method
@@ -26,6 +27,15 @@ rustc_queries! {
desc { "triggering a delay span bug" }
}
+ query registered_tools(_: ()) -> &'tcx ty::RegisteredTools {
+ arena_cache
+ desc { "compute registered tools for crate" }
+ }
+
+ query early_lint_checks(_: ()) -> () {
+ desc { "perform lints prior to macro expansion" }
+ }
+
query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt {
feedable
no_hash
@@ -87,7 +97,7 @@ rustc_queries! {
/// Gives access to the HIR ID for the given `LocalDefId` owner `key` if any.
///
- /// Definitions that were generated with no HIR, would be feeded to return `None`.
+ /// Definitions that were generated with no HIR, would be fed to return `None`.
query opt_local_def_id_to_hir_id(key: LocalDefId) -> Option<hir::HirId>{
desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) }
feedable
@@ -182,6 +192,7 @@ rustc_queries! {
{
desc { "determine whether the opaque is a type-alias impl trait" }
separate_provide_extern
+ feedable
}
query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32>
@@ -616,20 +627,26 @@ rustc_queries! {
separate_provide_extern
}
+ query implied_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
+ desc { |tcx| "computing the implied predicates of `{}`", tcx.def_path_str(key) }
+ cache_on_disk_if { key.is_local() }
+ separate_provide_extern
+ }
+
/// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query
/// returns the full set of predicates. If `Some<Ident>`, then the query returns only the
/// subset of super-predicates that reference traits that define the given associated type.
/// This is used to avoid cycles in resolving types like `T::Item`.
- query super_predicates_that_define_assoc_type(key: (DefId, Option<rustc_span::symbol::Ident>)) -> ty::GenericPredicates<'tcx> {
- desc { |tcx| "computing the super traits of `{}`{}",
+ query super_predicates_that_define_assoc_type(key: (DefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
+ desc { |tcx| "computing the super traits of `{}` with associated type name `{}`",
tcx.def_path_str(key.0),
- if let Some(assoc_name) = key.1 { format!(" with associated type name `{}`", assoc_name) } else { "".to_string() },
+ key.1
}
}
/// To avoid cycles within the predicates of a single item we compute
/// per-type-parameter predicates for resolving `T::AssocTy`.
- query type_param_predicates(key: (DefId, LocalDefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
+ query type_param_predicates(key: (LocalDefId, LocalDefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir().ty_param_name(key.1) }
}
@@ -764,7 +781,7 @@ rustc_queries! {
///
/// 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) -> &'tcx FxHashMap<DefId, DefId> {
+ query impl_item_implementor_ids(impl_id: DefId) -> &'tcx DefIdMap<DefId> {
arena_cache
desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) }
}
@@ -775,7 +792,7 @@ rustc_queries! {
/// if `fn_def_id` is the def id of a function defined inside an impl that implements a trait, then it
/// creates and returns the associated items that correspond to each impl trait in return position
/// of the implemented trait.
- query associated_items_for_impl_trait_in_trait(fn_def_id: DefId) -> &'tcx [DefId] {
+ query associated_types_for_impl_traits_in_associated_fn(fn_def_id: DefId) -> &'tcx [DefId] {
desc { |tcx| "creating associated items for impl trait in trait returned by `{}`", tcx.def_path_str(fn_def_id) }
cache_on_disk_if { fn_def_id.is_local() }
separate_provide_extern
@@ -783,10 +800,9 @@ rustc_queries! {
/// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
/// associated item.
- query associated_item_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {
+ query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {
desc { |tcx| "creates the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) }
cache_on_disk_if { true }
- separate_provide_extern
}
/// Given an `impl_id`, return the trait it implements.
@@ -906,8 +922,8 @@ rustc_queries! {
/// 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(_: ()) -> &'tcx (
- FxHashSet<LocalDefId>,
- FxHashMap<LocalDefId, Vec<(DefId, DefId)>>
+ LocalDefIdSet,
+ LocalDefIdMap<Vec<(DefId, DefId)>>
) {
arena_cache
desc { "finding live symbols in crate" }
@@ -1105,9 +1121,9 @@ rustc_queries! {
desc { "converting literal to mir constant" }
}
- query check_match(key: DefId) {
- desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) }
- cache_on_disk_if { key.is_local() }
+ query check_match(key: LocalDefId) {
+ desc { |tcx| "match-checking `{}`", tcx.def_path_str(key.to_def_id()) }
+ cache_on_disk_if { true }
}
/// Performs part of the privacy check and computes effective visibilities.
@@ -1120,7 +1136,7 @@ rustc_queries! {
desc { "checking for private elements in public interfaces" }
}
- query reachable_set(_: ()) -> &'tcx FxHashSet<LocalDefId> {
+ query reachable_set(_: ()) -> &'tcx LocalDefIdSet {
arena_cache
desc { "reachability" }
}
@@ -1152,14 +1168,6 @@ rustc_queries! {
feedable
}
- /// The `opt_rpitit_info` query returns the pair of the def id of the function where the RPIT
- /// is defined and the opaque def id if any.
- query opt_rpitit_info(def_id: DefId) -> Option<ty::ImplTraitInTraitData> {
- desc { |tcx| "opt_rpitit_info `{}`", tcx.def_path_str(def_id) }
- cache_on_disk_if { def_id.is_local() }
- feedable
- }
-
/// Gets the span for the definition.
query def_span(def_id: DefId) -> Span {
desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) }
@@ -1229,7 +1237,7 @@ rustc_queries! {
separate_provide_extern
}
- query asm_target_features(def_id: DefId) -> &'tcx FxHashSet<Symbol> {
+ query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet<Symbol> {
desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) }
}
@@ -1324,6 +1332,7 @@ rustc_queries! {
/// might want to use `reveal_all()` method to change modes.
query param_env(def_id: DefId) -> ty::ParamEnv<'tcx> {
desc { |tcx| "computing normalized predicates of `{}`", tcx.def_path_str(def_id) }
+ feedable
}
/// Like `param_env`, but returns the `ParamEnv` in `Reveal::All` mode.
@@ -1507,10 +1516,6 @@ rustc_queries! {
desc { "getting traits in scope at a block" }
}
- 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 {
desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
@@ -1845,7 +1850,7 @@ rustc_queries! {
query maybe_unused_trait_imports(_: ()) -> &'tcx FxIndexSet<LocalDefId> {
desc { "fetching potentially unused trait imports" }
}
- query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxHashSet<Symbol> {
+ query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx UnordSet<Symbol> {
desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
}
@@ -2114,7 +2119,7 @@ rustc_queries! {
desc { "raw operations for metadata file access" }
}
- query crate_for_resolver((): ()) -> &'tcx Steal<rustc_ast::ast::Crate> {
+ query crate_for_resolver((): ()) -> &'tcx Steal<(rustc_ast::Crate, rustc_ast::AttrVec)> {
feedable
no_hash
desc { "the ast before macro expansion and name resolution" }
@@ -2213,7 +2218,7 @@ rustc_queries! {
}
/// Used in `super_combine_consts` to ICE if the type of the two consts are definitely not going to end up being
- /// equal to eachother. This might return `Ok` even if the types are unequal, but will never return `Err` if
+ /// equal to eachother. This might return `Ok` even if the types are not equal, but will never return `Err` if
/// the types might be equal.
query check_tys_might_be_eq(arg: Canonical<'tcx, (ty::ParamEnv<'tcx>, Ty<'tcx>, Ty<'tcx>)>) -> Result<(), NoSolution> {
desc { "check whether two const param are definitely not equal to eachother"}
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 3b11fab8c..7d79a13d3 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -17,14 +17,14 @@ use rustc_index::newtype_index;
use rustc_index::vec::IndexVec;
use rustc_middle::middle::region;
use rustc_middle::mir::interpret::AllocId;
-use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
+use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp};
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AdtDef, FnSig, Ty, UpvarSubsts};
use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::{FieldIdx, VariantIdx};
use rustc_target::asm::InlineAsmRegOrRegClass;
use std::fmt;
use std::ops::Index;
@@ -227,6 +227,9 @@ pub enum StmtKind<'tcx> {
/// The lint level for this `let` statement.
lint_level: LintLevel,
+
+ /// Span of the `let <PAT> = <INIT>` part.
+ span: Span,
},
}
@@ -366,7 +369,7 @@ pub enum ExprKind<'tcx> {
/// Variant containing the field.
variant_index: VariantIdx,
/// This can be a named (`.foo`) or unnamed (`.0`) field.
- name: Field,
+ name: FieldIdx,
},
/// A *non-overloaded* indexing operation.
Index {
@@ -491,7 +494,7 @@ pub enum ExprKind<'tcx> {
/// This is used in struct constructors.
#[derive(Clone, Debug, HashStable)]
pub struct FieldExpr {
- pub name: Field,
+ pub name: FieldIdx,
pub expr: ExprId,
}
@@ -570,7 +573,7 @@ pub enum BindingMode {
#[derive(Clone, Debug, HashStable)]
pub struct FieldPat<'tcx> {
- pub field: Field,
+ pub field: FieldIdx,
pub pattern: Box<Pat<'tcx>>,
}
@@ -594,6 +597,55 @@ impl<'tcx> Pat<'tcx> {
_ => None,
}
}
+
+ /// Call `f` on every "binding" in a pattern, e.g., on `a` in
+ /// `match foo() { Some(a) => (), None => () }`
+ pub fn each_binding(&self, mut f: impl FnMut(Symbol, BindingMode, Ty<'tcx>, Span)) {
+ self.walk_always(|p| {
+ if let PatKind::Binding { name, mode, ty, .. } = p.kind {
+ f(name, mode, ty, p.span);
+ }
+ });
+ }
+
+ /// Walk the pattern in left-to-right order.
+ ///
+ /// If `it(pat)` returns `false`, the children are not visited.
+ pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
+ self.walk_(&mut it)
+ }
+
+ fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
+ if !it(self) {
+ return;
+ }
+
+ use PatKind::*;
+ match &self.kind {
+ Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } => {}
+ AscribeUserType { subpattern, .. }
+ | Binding { subpattern: Some(subpattern), .. }
+ | Deref { subpattern } => subpattern.walk_(it),
+ Leaf { subpatterns } | Variant { subpatterns, .. } => {
+ subpatterns.iter().for_each(|field| field.pattern.walk_(it))
+ }
+ Or { pats } => pats.iter().for_each(|p| p.walk_(it)),
+ Array { box ref prefix, ref slice, box ref suffix }
+ | Slice { box ref prefix, ref slice, box ref suffix } => {
+ prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it))
+ }
+ }
+ }
+
+ /// Walk the pattern in left-to-right order.
+ ///
+ /// If you always want to recurse, prefer this method over `walk`.
+ pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) {
+ self.walk(|p| {
+ it(p);
+ true
+ })
+ }
}
impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
@@ -784,7 +836,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
if let PatKind::Wild = p.pattern.kind {
continue;
}
- let name = variant.fields[p.field.index()].name;
+ let name = variant.fields[p.field].name;
write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
printed += 1;
}
@@ -879,7 +931,7 @@ mod size_asserts {
static_assert_size!(ExprKind<'_>, 40);
static_assert_size!(Pat<'_>, 72);
static_assert_size!(PatKind<'_>, 56);
- static_assert_size!(Stmt<'_>, 48);
- static_assert_size!(StmtKind<'_>, 40);
+ static_assert_size!(Stmt<'_>, 56);
+ static_assert_size!(StmtKind<'_>, 48);
// tidy-alphabetical-end
}
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index 79a0e75aa..5614528c4 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -175,6 +175,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm
ref pattern,
lint_level: _,
else_block,
+ span: _,
} => {
if let Some(init) = initializer {
visitor.visit_expr(&visitor.thir()[*init]);
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 6231dd9b6..91f07389f 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -305,8 +305,6 @@ pub enum ObligationCauseCode<'tcx> {
SizedReturnType,
/// Yield type must be `Sized`.
SizedYieldType,
- /// Box expression result type must be `Sized`.
- SizedBoxType,
/// Inline asm operand type must be `Sized`.
InlineAsmSized,
/// `[expr; N]` requires `type_of(expr): Copy`.
@@ -699,9 +697,9 @@ impl<'tcx, N> ImplSource<'tcx, N> {
}
pub fn borrow_nested_obligations(&self) -> &[N] {
- match &self {
- ImplSource::UserDefined(i) => &i.nested[..],
- ImplSource::Param(n, _) => &n,
+ match self {
+ ImplSource::UserDefined(i) => &i.nested,
+ ImplSource::Param(n, _) => n,
ImplSource::Builtin(i) => &i.nested,
ImplSource::AutoImpl(d) => &d.nested,
ImplSource::Closure(c) => &c.nested,
@@ -715,6 +713,23 @@ impl<'tcx, N> ImplSource<'tcx, N> {
}
}
+ pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] {
+ match self {
+ ImplSource::UserDefined(i) => &mut i.nested,
+ ImplSource::Param(n, _) => n,
+ ImplSource::Builtin(i) => &mut i.nested,
+ ImplSource::AutoImpl(d) => &mut d.nested,
+ ImplSource::Closure(c) => &mut c.nested,
+ ImplSource::Generator(c) => &mut c.nested,
+ ImplSource::Future(c) => &mut c.nested,
+ ImplSource::Object(d) => &mut d.nested,
+ ImplSource::FnPointer(d) => &mut d.nested,
+ ImplSource::TraitAlias(d) => &mut d.nested,
+ ImplSource::TraitUpcasting(d) => &mut d.nested,
+ ImplSource::ConstDestruct(i) => &mut i.nested,
+ }
+ }
+
pub fn map<M, F>(self, f: F) -> ImplSource<'tcx, M>
where
F: FnMut(N) -> M,
@@ -899,6 +914,9 @@ pub enum ObjectSafetyViolation {
/// (e.g., `trait Foo : Bar<Self>`).
SupertraitSelf(SmallVec<[Span; 1]>),
+ // Supertrait has a non-lifetime `for<T>` binder.
+ SupertraitNonLifetimeBinder(SmallVec<[Span; 1]>),
+
/// Method has something illegal.
Method(Symbol, MethodViolationCode, Span),
@@ -921,6 +939,9 @@ impl ObjectSafetyViolation {
.into()
}
}
+ ObjectSafetyViolation::SupertraitNonLifetimeBinder(_) => {
+ "where clause cannot reference non-lifetime `for<...>` variables".into()
+ }
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => {
format!("associated function `{}` has no `self` parameter", name).into()
}
@@ -971,7 +992,9 @@ impl ObjectSafetyViolation {
pub fn solution(&self, err: &mut Diagnostic) {
match self {
- ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => {}
+ ObjectSafetyViolation::SizedSelf(_)
+ | ObjectSafetyViolation::SupertraitSelf(_)
+ | ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => {}
ObjectSafetyViolation::Method(
name,
MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
@@ -1025,7 +1048,8 @@ impl ObjectSafetyViolation {
// diagnostics use a `note` instead of a `span_label`.
match self {
ObjectSafetyViolation::SupertraitSelf(spans)
- | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(),
+ | ObjectSafetyViolation::SizedSelf(spans)
+ | ObjectSafetyViolation::SupertraitNonLifetimeBinder(spans) => spans.clone(),
ObjectSafetyViolation::AssocConst(_, span)
| ObjectSafetyViolation::GAT(_, span)
| ObjectSafetyViolation::Method(_, _, span)
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index bd43867a3..fef2be133 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -1,12 +1,113 @@
use std::ops::ControlFlow;
use rustc_data_structures::intern::Interned;
+use rustc_query_system::cache::Cache;
-use crate::infer::canonical::QueryRegionConstraints;
+use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints};
+use crate::traits::query::NoSolution;
+use crate::traits::Canonical;
use crate::ty::{
- FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
+ self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable,
+ TypeVisitor,
};
+pub type EvaluationCache<'tcx> = Cache<CanonicalGoal<'tcx>, QueryResult<'tcx>>;
+
+/// A goal is a statement, i.e. `predicate`, we want to prove
+/// given some assumptions, i.e. `param_env`.
+///
+/// Most of the time the `param_env` contains the `where`-bounds of the function
+/// we're currently typechecking while the `predicate` is some trait bound.
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+pub struct Goal<'tcx, P> {
+ pub predicate: P,
+ pub param_env: ty::ParamEnv<'tcx>,
+}
+
+impl<'tcx, P> Goal<'tcx, P> {
+ pub fn new(
+ tcx: TyCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ predicate: impl ToPredicate<'tcx, P>,
+ ) -> Goal<'tcx, P> {
+ Goal { param_env, predicate: predicate.to_predicate(tcx) }
+ }
+
+ /// Updates the goal to one with a different `predicate` but the same `param_env`.
+ pub fn with<Q>(self, tcx: TyCtxt<'tcx>, predicate: impl ToPredicate<'tcx, Q>) -> Goal<'tcx, Q> {
+ Goal { param_env: self.param_env, predicate: predicate.to_predicate(tcx) }
+ }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+pub struct Response<'tcx> {
+ pub certainty: Certainty,
+ pub var_values: CanonicalVarValues<'tcx>,
+ /// Additional constraints returned by this query.
+ pub external_constraints: ExternalConstraints<'tcx>,
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+pub enum Certainty {
+ Yes,
+ Maybe(MaybeCause),
+}
+
+impl Certainty {
+ pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity);
+
+ /// Use this function to merge the certainty of multiple nested subgoals.
+ ///
+ /// Given an impl like `impl<T: Foo + Bar> Baz for T {}`, we have 2 nested
+ /// subgoals whenever we use the impl as a candidate: `T: Foo` and `T: Bar`.
+ /// If evaluating `T: Foo` results in ambiguity and `T: Bar` results in
+ /// success, we merge these two responses. This results in ambiguity.
+ ///
+ /// If we unify ambiguity with overflow, we return overflow. This doesn't matter
+ /// inside of the solver as we distinguish ambiguity from overflow. It does
+ /// however matter for diagnostics. If `T: Foo` resulted in overflow and `T: Bar`
+ /// in ambiguity without changing the inference state, we still want to tell the
+ /// user that `T: Baz` results in overflow.
+ pub fn unify_with(self, other: Certainty) -> Certainty {
+ match (self, other) {
+ (Certainty::Yes, Certainty::Yes) => Certainty::Yes,
+ (Certainty::Yes, Certainty::Maybe(_)) => other,
+ (Certainty::Maybe(_), Certainty::Yes) => self,
+ (Certainty::Maybe(MaybeCause::Ambiguity), Certainty::Maybe(MaybeCause::Ambiguity)) => {
+ Certainty::Maybe(MaybeCause::Ambiguity)
+ }
+ (Certainty::Maybe(MaybeCause::Ambiguity), Certainty::Maybe(MaybeCause::Overflow))
+ | (Certainty::Maybe(MaybeCause::Overflow), Certainty::Maybe(MaybeCause::Ambiguity))
+ | (Certainty::Maybe(MaybeCause::Overflow), Certainty::Maybe(MaybeCause::Overflow)) => {
+ Certainty::Maybe(MaybeCause::Overflow)
+ }
+ }
+ }
+}
+
+/// Why we failed to evaluate a goal.
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+pub enum MaybeCause {
+ /// We failed due to ambiguity. This ambiguity can either
+ /// be a true ambiguity, i.e. there are multiple different answers,
+ /// or we hit a case where we just don't bother, e.g. `?x: Trait` goals.
+ Ambiguity,
+ /// We gave up due to an overflow, most often by hitting the recursion limit.
+ Overflow,
+}
+
+pub type CanonicalGoal<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, Goal<'tcx, T>>;
+
+pub type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
+
+/// The result of evaluating a canonical query.
+///
+/// FIXME: We use a different type than the existing canonical queries. This is because
+/// we need to add a `Certainty` for `overflow` and may want to restructure this code without
+/// having to worry about changes to currently used code. Once we've made progress on this
+/// solver, merge the two responses again.
+pub type QueryResult<'tcx> = Result<CanonicalResponse<'tcx>, NoSolution>;
+
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>);
@@ -14,7 +115,7 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
type Target = ExternalConstraintsData<'tcx>;
fn deref(&self) -> &Self::Target {
- &*self.0
+ &self.0
}
}
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index df9aa765d..468c2c818 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -37,10 +37,6 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
self.tcx
}
- fn intercrate(&self) -> bool {
- false
- }
-
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env
}
@@ -48,10 +44,6 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
true
} // irrelevant
- fn mark_ambiguous(&mut self) {
- bug!()
- }
-
fn relate_with_variance<T: Relate<'tcx>>(
&mut self,
_: ty::Variance,
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index 8ce06404d..cd0f7e8da 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -3,6 +3,7 @@ use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_macros::HashStable;
use rustc_span::Span;
+use rustc_target::abi::FieldIdx;
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
pub enum PointerCast {
@@ -208,5 +209,5 @@ pub struct CoerceUnsizedInfo {
#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
pub enum CustomCoerceUnsized {
/// Records the index of the field being coerced.
- Struct(usize),
+ Struct(FieldIdx),
}
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index ec21030b3..3a03c0901 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -10,11 +10,11 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::{IndexSlice, IndexVec};
use rustc_query_system::ich::StableHashingContext;
use rustc_session::DataTypeKind;
use rustc_span::symbol::sym;
-use rustc_target::abi::{ReprOptions, VariantIdx};
+use rustc_target::abi::{ReprOptions, VariantIdx, FIRST_VARIANT};
use std::cell::RefCell;
use std::cmp::Ordering;
@@ -168,7 +168,7 @@ impl<'tcx> AdtDef<'tcx> {
}
#[inline]
- pub fn variants(self) -> &'tcx IndexVec<VariantIdx, VariantDef> {
+ pub fn variants(self) -> &'tcx IndexSlice<VariantIdx, VariantDef> {
&self.0.0.variants
}
@@ -228,7 +228,7 @@ impl AdtDefData {
AdtKind::Struct => AdtFlags::IS_STRUCT,
};
- if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor.is_some() {
+ if kind == AdtKind::Struct && variants[FIRST_VARIANT].ctor.is_some() {
flags |= AdtFlags::HAS_CTOR;
}
@@ -357,7 +357,7 @@ impl<'tcx> AdtDef<'tcx> {
/// Asserts this is a struct or union and returns its unique variant.
pub fn non_enum_variant(self) -> &'tcx VariantDef {
assert!(self.is_struct() || self.is_union());
- &self.variant(VariantIdx::new(0))
+ &self.variant(FIRST_VARIANT)
}
#[inline]
@@ -493,7 +493,7 @@ impl<'tcx> AdtDef<'tcx> {
#[inline]
pub fn variant_range(self) -> Range<VariantIdx> {
- VariantIdx::new(0)..VariantIdx::new(self.variants().len())
+ FIRST_VARIANT..self.variants().next_index()
}
/// Computes the discriminant value used by a specific variant.
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index f1a9e50a4..090b76932 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -1,6 +1,6 @@
pub use self::AssocItemContainer::*;
-use crate::ty::{self, DefIdTree};
+use crate::ty;
use rustc_data_structures::sorted_map::SortedIndexMultiMap;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Namespace};
@@ -30,6 +30,11 @@ pub struct AssocItem {
/// Whether this is a method with an explicit self
/// as its first parameter, allowing method calls.
pub fn_has_self_parameter: bool,
+
+ /// `Some` if the associated item (an associated type) comes from the
+ /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData`
+ /// provides additional information about its source.
+ pub opt_rpitit_info: Option<ty::ImplTraitInTraitData>,
}
impl AssocItem {
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index dc2bd54b7..f29bf92b0 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -158,12 +158,12 @@ impl<'tcx> CapturedPlace<'tcx> {
for proj in self.place.projections.iter() {
match proj.kind {
HirProjectionKind::Field(idx, variant) => match ty.kind() {
- ty::Tuple(_) => write!(&mut symbol, "__{}", idx).unwrap(),
+ ty::Tuple(_) => write!(&mut symbol, "__{}", idx.index()).unwrap(),
ty::Adt(def, ..) => {
write!(
&mut symbol,
"__{}",
- def.variant(variant).fields[idx as usize].name.as_str(),
+ def.variant(variant).fields[idx].name.as_str(),
)
.unwrap();
}
@@ -356,11 +356,11 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc
curr_string = format!(
"{}.{}",
curr_string,
- def.variant(variant).fields[idx as usize].name.as_str()
+ def.variant(variant).fields[idx].name.as_str()
);
}
ty::Tuple(_) => {
- curr_string = format!("{}.{}", curr_string, idx);
+ curr_string = format!("{}.{}", curr_string, idx.index());
}
_ => {
bug!(
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 3ce80e06a..8ef4a46a7 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -511,8 +511,6 @@ macro_rules! implement_ty_decoder {
read_isize -> isize;
read_bool -> bool;
- read_f64 -> f64;
- read_f32 -> f32;
read_char -> char;
read_str -> &str;
}
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 527ec9f6e..bcedae233 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,10 +1,10 @@
use crate::middle::resolve_bound_vars as rbv;
use crate::mir::interpret::LitToConstInput;
-use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
+use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_data_structures::intern::Interned;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
use rustc_macros::HashStable;
use std::fmt;
@@ -83,7 +83,7 @@ impl<'tcx> Const<'tcx> {
None => tcx.mk_const(
ty::UnevaluatedConst {
def: def.to_global(),
- substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
+ substs: InternalSubsts::identity_for_item(tcx, def.did),
},
ty,
),
@@ -135,6 +135,9 @@ impl<'tcx> Const<'tcx> {
_,
&hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
)) => {
+ // Use the type from the param's definition, since we can resolve it,
+ // not the expected parameter type from WithOptConstParam.
+ let param_ty = tcx.type_of(def_id).subst_identity();
match tcx.named_bound_var(expr.hir_id) {
Some(rbv::ResolvedArg::EarlyBound(_)) => {
// Find the name and index of the const parameter by indexing the generics of
@@ -143,14 +146,14 @@ impl<'tcx> Const<'tcx> {
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
let name = tcx.item_name(def_id);
- Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+ Some(tcx.mk_const(ty::ParamConst::new(index, name), param_ty))
}
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
- ty,
+ param_ty,
)),
Some(rbv::ResolvedArg::Error(guar)) => {
- Some(tcx.const_error_with_guaranteed(ty, guar))
+ Some(tcx.const_error_with_guaranteed(param_ty, guar))
}
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
}
@@ -262,8 +265,8 @@ impl<'tcx> Const<'tcx> {
}
}
-pub fn const_param_default(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Const<'_>> {
- let default_def_id = match tcx.hir().get_by_def_id(def_id.expect_local()) {
+pub fn const_param_default(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Const<'_>> {
+ let default_def_id = match tcx.hir().get_by_def_id(def_id) {
hir::Node::GenericParam(hir::GenericParam {
kind: hir::GenericParamKind::Const { default: Some(ac), .. },
..
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index eecd78ab6..c0e557d48 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -237,7 +237,7 @@ impl ScalarInt {
}
/// Tries to convert the `ScalarInt` to an unsigned integer of the given size.
- /// Fails if the size of the `ScalarInt` is unequal to `size` and returns the
+ /// Fails if the size of the `ScalarInt` is not equal to `size` and returns the
/// `ScalarInt`s size in that case.
#[inline]
pub fn try_to_uint(self, size: Size) -> Result<u128, Size> {
@@ -297,7 +297,7 @@ impl ScalarInt {
}
/// Tries to convert the `ScalarInt` to a signed integer of the given size.
- /// Fails if the size of the `ScalarInt` is unequal to `size` and returns the
+ /// Fails if the size of the `ScalarInt` is not equal to `size` and returns the
/// `ScalarInt`s size in that case.
#[inline]
pub fn try_to_int(self, size: Size) -> Result<i128, Size> {
@@ -306,38 +306,38 @@ impl ScalarInt {
}
/// Tries to convert the `ScalarInt` to i8.
- /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 1 }`
+ /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 1 }`
/// and returns the `ScalarInt`s size in that case.
pub fn try_to_i8(self) -> Result<i8, Size> {
self.try_to_int(Size::from_bits(8)).map(|v| i8::try_from(v).unwrap())
}
/// Tries to convert the `ScalarInt` to i16.
- /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 2 }`
+ /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 2 }`
/// and returns the `ScalarInt`s size in that case.
pub fn try_to_i16(self) -> Result<i16, Size> {
self.try_to_int(Size::from_bits(16)).map(|v| i16::try_from(v).unwrap())
}
/// Tries to convert the `ScalarInt` to i32.
- /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 4 }`
+ /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 4 }`
/// and returns the `ScalarInt`s size in that case.
pub fn try_to_i32(self) -> Result<i32, Size> {
self.try_to_int(Size::from_bits(32)).map(|v| i32::try_from(v).unwrap())
}
/// Tries to convert the `ScalarInt` to i64.
- /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 8 }`
+ /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 8 }`
/// and returns the `ScalarInt`s size in that case.
pub fn try_to_i64(self) -> Result<i64, Size> {
self.try_to_int(Size::from_bits(64)).map(|v| i64::try_from(v).unwrap())
}
/// Tries to convert the `ScalarInt` to i128.
- /// Fails if the size of the `ScalarInt` is unequal to `Size { raw: 16 }`
+ /// Fails if the size of the `ScalarInt` is not equal to `Size { raw: 16 }`
/// and returns the `ScalarInt`s size in that case.
pub fn try_to_i128(self) -> Result<i128, Size> {
- self.try_to_int(Size::from_bits(128)).map(|v| i128::try_from(v).unwrap())
+ self.try_to_int(Size::from_bits(128))
}
}
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index 5ed4af2e9..8b96864dd 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -79,7 +79,7 @@ impl<'tcx> ValTree<'tcx> {
}
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
- self.try_to_scalar_int().map(|s| s.try_to_target_usize(tcx).ok()).flatten()
+ self.try_to_scalar_int().and_then(|s| s.try_to_target_usize(tcx).ok())
}
/// Get the values inside the ValTree as a slice of bytes. This only works for
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index d9af2fd74..63f7cc2ee 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -8,26 +8,26 @@ use crate::arena::Arena;
use crate::dep_graph::{DepGraph, DepKindStruct};
use crate::infer::canonical::CanonicalVarInfo;
use crate::lint::struct_lint_level;
+use crate::metadata::ModChild;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::resolve_bound_vars;
use crate::middle::stability;
use crate::mir::interpret::{self, Allocation, ConstAllocation};
-use crate::mir::{
- Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted,
-};
+use crate::mir::{Body, BorrowCheckResult, Local, Place, PlaceElem, ProjectionKind, Promoted};
+use crate::query::LocalCrate;
use crate::thir::Thir;
use crate::traits;
+use crate::traits::solve;
use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
use crate::ty::query::{self, TyCtxtAt};
use crate::ty::{
- self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar,
- FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
- ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind,
- ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy,
- Visibility,
+ self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
+ GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
+ PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
+ TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy, Visibility,
};
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
-use rustc_ast as ast;
+use rustc_ast::{self as ast, attr};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::intern::Interned;
@@ -37,6 +37,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{self, Lock, Lrc, MappedReadGuard, ReadGuard, WorkerLocal};
+use rustc_data_structures::unord::UnordSet;
use rustc_errors::{
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
};
@@ -63,13 +64,14 @@ use rustc_span::def_id::{DefPathHash, StableCrateId};
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
+use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi;
use rustc_type_ir::sty::TyKind::*;
use rustc_type_ir::WithCachedTypeInfo;
use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags};
use std::any::Any;
+use std::assert_matches::debug_assert_matches;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::fmt;
@@ -310,7 +312,7 @@ pub struct CommonLifetimes<'tcx> {
pub re_vars: Vec<Region<'tcx>>,
/// Pre-interned values of the form:
- /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })`
+ /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(None) })`
/// for small values of `i` and `v`.
pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
}
@@ -385,10 +387,7 @@ impl<'tcx> CommonLifetimes<'tcx> {
.map(|v| {
mk(ty::ReLateBound(
ty::DebruijnIndex::from(i),
- ty::BoundRegion {
- var: ty::BoundVar::from(v),
- kind: ty::BrAnon(v, None),
- },
+ ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon(None) },
))
})
.collect()
@@ -537,6 +536,9 @@ pub struct GlobalCtxt<'tcx> {
/// Merge this with `selection_cache`?
pub evaluation_cache: traits::EvaluationCache<'tcx>,
+ /// Caches the results of goal evaluation in the new solver.
+ pub new_solver_evaluation_cache: solve::EvaluationCache<'tcx>,
+
/// Data layout specification for the current target.
pub data_layout: TargetDataLayout,
@@ -712,6 +714,7 @@ impl<'tcx> TyCtxt<'tcx> {
pred_rcache: Default::default(),
selection_cache: Default::default(),
evaluation_cache: Default::default(),
+ new_solver_evaluation_cache: Default::default(),
data_layout,
alloc_map: Lock::new(interpret::AllocMap::new()),
}
@@ -922,7 +925,7 @@ impl<'tcx> TyCtxt<'tcx> {
crate_name,
// Don't print the whole stable crate id. That's just
// annoying in debug output.
- stable_crate_id.to_u64() >> 8 * 6,
+ stable_crate_id.to_u64() >> (8 * 6),
self.def_path(def_id).to_string_no_crate_verbose()
)
}
@@ -2044,6 +2047,12 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_alias(self, kind: ty::AliasKind, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> {
+ debug_assert_matches!(
+ (kind, self.def_kind(alias_ty.def_id)),
+ (ty::Opaque, DefKind::OpaqueTy)
+ | (ty::Projection, DefKind::AssocTy)
+ | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder)
+ );
self.mk_ty_from_kind(Alias(kind, alias_ty))
}
@@ -2064,10 +2073,9 @@ impl<'tcx> TyCtxt<'tcx> {
bound_region: ty::BoundRegion,
) -> Region<'tcx> {
// Use a pre-interned one when possible.
- if let ty::BoundRegion { var, kind: ty::BrAnon(v, None) } = bound_region
- && var.as_u32() == v
+ if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region
&& let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
- && let Some(re) = inner.get(v as usize).copied()
+ && let Some(re) = inner.get(var.as_usize()).copied()
{
re
} else {
@@ -2112,7 +2120,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
+ pub fn mk_place_field(self, place: Place<'tcx>, f: FieldIdx, ty: Ty<'tcx>) -> Place<'tcx> {
self.mk_place_elem(place, PlaceElem::Field(f, ty))
}
@@ -2372,7 +2380,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
let map = self.in_scope_traits_map(id.owner)?;
let candidates = map.get(&id.local_id)?;
- Some(&*candidates)
+ Some(candidates)
}
pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
@@ -2440,6 +2448,40 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn trait_solver_next(self) -> bool {
self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
}
+
+ pub fn lower_impl_trait_in_trait_to_assoc_ty(self) -> bool {
+ self.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
+ }
+
+ pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
+ if self.lower_impl_trait_in_trait_to_assoc_ty() {
+ self.opt_rpitit_info(def_id).is_some()
+ } else {
+ self.def_kind(def_id) == DefKind::ImplTraitPlaceholder
+ }
+ }
+
+ /// Named module children from all items except `use` and `extern crate` imports.
+ ///
+ /// In addition to regular items this list also includes struct or variant constructors, and
+ /// items inside `extern {}` blocks because all of them introduce names into parent module.
+ /// For non-reexported children every such name is associated with a separate `DefId`.
+ ///
+ /// Module here is understood in name resolution sense - it can be a `mod` item,
+ /// or a crate root, or an enum, or a trait.
+ pub fn module_children_non_reexports(self, def_id: LocalDefId) -> &'tcx [LocalDefId] {
+ self.resolutions(()).module_children_non_reexports.get(&def_id).map_or(&[], |v| &v[..])
+ }
+
+ /// Named module children from `use` and `extern crate` imports.
+ ///
+ /// Reexported names are not associated with individual `DefId`s,
+ /// e.g. a glob import can introduce a lot of names, all with the same `DefId`.
+ /// That's why the list needs to contain `ModChild` structures describing all the names
+ /// individually instead of `DefId`s.
+ pub fn module_children_reexports(self, def_id: LocalDefId) -> &'tcx [ModChild] {
+ self.resolutions(()).module_children_reexports.get(&def_id).map_or(&[], |v| &v[..])
+ }
}
impl<'tcx> TyCtxtAt<'tcx> {
@@ -2482,26 +2524,21 @@ pub struct DeducedParamAttrs {
}
pub fn provide(providers: &mut ty::query::Providers) {
- providers.module_reexports =
- |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]);
providers.maybe_unused_trait_imports =
|tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
providers.names_imported_by_glob_use = |tcx, id| {
- tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
+ tcx.arena.alloc(UnordSet::from(
+ tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default(),
+ ))
};
providers.extern_mod_stmt_cnum =
|tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
- providers.is_panic_runtime = |tcx, cnum| {
- assert_eq!(cnum, LOCAL_CRATE);
- tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::panic_runtime)
- };
- providers.is_compiler_builtins = |tcx, cnum| {
- assert_eq!(cnum, LOCAL_CRATE);
- tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins)
- };
- providers.has_panic_handler = |tcx, cnum| {
- assert_eq!(cnum, LOCAL_CRATE);
+ providers.is_panic_runtime =
+ |tcx, LocalCrate| attr::contains_name(tcx.hir().krate_attrs(), sym::panic_runtime);
+ providers.is_compiler_builtins =
+ |tcx, LocalCrate| attr::contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins);
+ providers.has_panic_handler = |tcx, LocalCrate| {
// We want to check if the panic handler was defined in this crate
tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
};
diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs
index 5426ac8d7..fb0d90930 100644
--- a/compiler/rustc_middle/src/ty/context/tls.rs
+++ b/compiler/rustc_middle/src/ty/context/tls.rs
@@ -4,6 +4,8 @@ use crate::dep_graph::TaskDepsRef;
use crate::ty::query;
use rustc_data_structures::sync::{self, Lock};
use rustc_errors::Diagnostic;
+#[cfg(not(parallel_compiler))]
+use std::cell::Cell;
use std::mem;
use std::ptr;
use thin_vec::ThinVec;
@@ -47,52 +49,15 @@ impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
}
}
+// Import the thread-local variable from Rayon, which is preserved for Rayon jobs.
#[cfg(parallel_compiler)]
-mod tlv {
- use rustc_rayon_core as rayon_core;
- use std::ptr;
-
- /// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
- /// This is used to get the pointer to the current `ImplicitCtxt`.
- #[inline]
- pub(super) fn get_tlv() -> *const () {
- ptr::from_exposed_addr(rayon_core::tlv::get())
- }
-
- /// Sets Rayon's thread-local variable, which is preserved for Rayon jobs
- /// to `value` during the call to `f`. It is restored to its previous value after.
- /// This is used to set the pointer to the new `ImplicitCtxt`.
- #[inline]
- pub(super) fn with_tlv<F: FnOnce() -> R, R>(value: *const (), f: F) -> R {
- rayon_core::tlv::with(value.expose_addr(), f)
- }
-}
+use rayon_core::tlv::TLV;
+// Otherwise define our own
#[cfg(not(parallel_compiler))]
-mod tlv {
- use std::cell::Cell;
- use std::ptr;
-
- thread_local! {
- /// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
- static TLV: Cell<*const ()> = const { Cell::new(ptr::null()) };
- }
-
- /// Gets the pointer to the current `ImplicitCtxt`.
- #[inline]
- pub(super) fn get_tlv() -> *const () {
- TLV.with(|tlv| tlv.get())
- }
-
- /// Sets TLV to `value` during the call to `f`.
- /// It is restored to its previous value after.
- /// This is used to set the pointer to the new `ImplicitCtxt`.
- #[inline]
- pub(super) fn with_tlv<F: FnOnce() -> R, R>(value: *const (), f: F) -> R {
- let old = TLV.replace(value);
- let _reset = rustc_data_structures::OnDrop(move || TLV.set(old));
- f()
- }
+thread_local! {
+ /// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
+ static TLV: Cell<*const ()> = const { Cell::new(ptr::null()) };
}
#[inline]
@@ -111,7 +76,11 @@ pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) ->
where
F: FnOnce() -> R,
{
- tlv::with_tlv(erase(context), f)
+ TLV.with(|tlv| {
+ let old = tlv.replace(erase(context));
+ let _reset = rustc_data_structures::OnDrop(move || tlv.set(old));
+ f()
+ })
}
/// Allows access to the current `ImplicitCtxt` in a closure if one is available.
@@ -120,7 +89,7 @@ pub fn with_context_opt<F, R>(f: F) -> R
where
F: for<'a, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'tcx>>) -> R,
{
- let context = tlv::get_tlv();
+ let context = TLV.get();
if context.is_null() {
f(None)
} else {
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index e894e1aaf..ae0bb4949 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -3,9 +3,9 @@
use std::ops::ControlFlow;
use crate::ty::{
- AliasTy, Const, ConstKind, DefIdTree, FallibleTypeFolder, InferConst, InferTy, Opaque,
- PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
- TypeSuperVisitable, TypeVisitable, TypeVisitor,
+ AliasTy, Const, ConstKind, FallibleTypeFolder, InferConst, InferTy, Opaque, PolyTraitPredicate,
+ Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
+ TypeVisitor,
};
use rustc_data_structures::fx::FxHashMap;
@@ -117,7 +117,7 @@ pub fn suggest_arbitrary_trait_bound<'tcx>(
}
let param_name = trait_pred.skip_binder().self_ty().to_string();
- let mut constraint = trait_pred.print_modifiers_and_trait_path().to_string();
+ let mut constraint = trait_pred.to_string();
if let Some((name, term)) = associated_ty {
// FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err.
@@ -144,7 +144,7 @@ pub fn suggest_arbitrary_trait_bound<'tcx>(
this requirement",
if generics.where_clause_span.is_empty() { "introducing a" } else { "extending the" },
),
- format!("{} {}: {}", generics.add_where_or_trailing_comma(), param_name, constraint),
+ format!("{} {constraint}", generics.add_where_or_trailing_comma()),
Applicability::MaybeIncorrect,
);
true
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 9c171a69d..aff6c77e0 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -151,12 +151,8 @@ impl<'tcx> TypeError<'tcx> {
.into(),
RegionsPlaceholderMismatch => "one type is more general than the other".into(),
ArgumentSorts(values, _) | Sorts(values) => {
- let mut expected = values.expected.sort_string(tcx);
- let mut found = values.found.sort_string(tcx);
- if expected == found {
- expected = values.expected.sort_string(tcx);
- found = values.found.sort_string(tcx);
- }
+ let expected = values.expected.sort_string(tcx);
+ let found = values.found.sort_string(tcx);
report_maybe_different(&expected, &found).into()
}
Traits(values) => {
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 59deade0a..31d00b65e 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -1,6 +1,6 @@
use crate::mir::Mutability;
use crate::ty::subst::GenericArgKind;
-use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
use rustc_hir::def_id::DefId;
use std::fmt::Debug;
use std::hash::Hash;
@@ -51,15 +51,36 @@ pub enum SimplifiedType {
/// generic parameters as if they were inference variables in that case.
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub enum TreatParams {
- /// Treat parameters as placeholders in the given environment.
+ /// Treat parameters as infer vars. This is the correct mode for caching
+ /// an impl's type for lookup.
+ AsCandidateKey,
+ /// Treat parameters as placeholders in the given environment. This is the
+ /// correct mode for *lookup*, as during candidate selection.
///
- /// Note that this also causes us to treat projections as if they were
- /// placeholders. This is only correct if the given projection cannot
- /// be normalized in the current context. Even if normalization fails,
- /// it may still succeed later if the projection contains any inference
- /// variables.
- AsPlaceholder,
- AsInfer,
+ /// This also treats projections with inference variables as infer vars
+ /// since they could be further normalized.
+ ForLookup,
+ /// Treat parameters as placeholders in the given environment. This is the
+ /// correct mode for *lookup*, as during candidate selection.
+ ///
+ /// N.B. during deep rejection, this acts identically to `ForLookup`.
+ NextSolverLookup,
+}
+
+/// During fast-rejection, we have the choice of treating projection types
+/// as either simplifyable or not, depending on whether we expect the projection
+/// to be normalized/rigid.
+#[derive(PartialEq, Eq, Debug, Clone, Copy)]
+pub enum TreatProjections {
+ /// In the old solver we don't try to normalize projections
+ /// when looking up impls and only access them by using the
+ /// current self type. This means that if the self type is
+ /// a projection which could later be normalized, we must not
+ /// treat it as rigid.
+ ForLookup,
+ /// We can treat projections in the self type as opaque as
+ /// we separately look up impls for the normalized self type.
+ NextSolverLookup,
}
/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
@@ -115,19 +136,20 @@ pub fn simplify_type<'tcx>(
ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
ty::Placeholder(..) => Some(PlaceholderSimplifiedType),
ty::Param(_) => match treat_params {
- TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
- TreatParams::AsInfer => None,
+ TreatParams::ForLookup | TreatParams::NextSolverLookup => {
+ Some(PlaceholderSimplifiedType)
+ }
+ TreatParams::AsCandidateKey => None,
},
ty::Alias(..) => match treat_params {
// When treating `ty::Param` as a placeholder, projections also
// don't unify with anything else as long as they are fully normalized.
//
// We will have to be careful with lazy normalization here.
- TreatParams::AsPlaceholder if !ty.has_non_region_infer() => {
- debug!("treating `{}` as a placeholder", ty);
- Some(PlaceholderSimplifiedType)
- }
- TreatParams::AsPlaceholder | TreatParams::AsInfer => None,
+ // FIXME(lazy_normalization): This is probably not right...
+ TreatParams::ForLookup if !ty.has_non_region_infer() => Some(PlaceholderSimplifiedType),
+ TreatParams::NextSolverLookup => Some(PlaceholderSimplifiedType),
+ TreatParams::ForLookup | TreatParams::AsCandidateKey => None,
},
ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
@@ -166,22 +188,24 @@ pub struct DeepRejectCtxt {
}
impl DeepRejectCtxt {
- pub fn generic_args_may_unify<'tcx>(
+ pub fn substs_refs_may_unify<'tcx>(
self,
- obligation_arg: ty::GenericArg<'tcx>,
- impl_arg: ty::GenericArg<'tcx>,
+ obligation_substs: SubstsRef<'tcx>,
+ impl_substs: SubstsRef<'tcx>,
) -> bool {
- match (obligation_arg.unpack(), impl_arg.unpack()) {
- // We don't fast reject based on regions for now.
- (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true,
- (GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => {
- self.types_may_unify(obl, imp)
- }
- (GenericArgKind::Const(obl), GenericArgKind::Const(imp)) => {
- self.consts_may_unify(obl, imp)
+ iter::zip(obligation_substs, impl_substs).all(|(obl, imp)| {
+ match (obl.unpack(), imp.unpack()) {
+ // We don't fast reject based on regions for now.
+ (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true,
+ (GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => {
+ self.types_may_unify(obl, imp)
+ }
+ (GenericArgKind::Const(obl), GenericArgKind::Const(imp)) => {
+ self.consts_may_unify(obl, imp)
+ }
+ _ => bug!("kind mismatch: {obl} {imp}"),
}
- _ => bug!("kind mismatch: {obligation_arg} {impl_arg}"),
- }
+ })
}
pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -> bool {
@@ -236,9 +260,7 @@ impl DeepRejectCtxt {
},
ty::Adt(obl_def, obl_substs) => match k {
&ty::Adt(impl_def, impl_substs) => {
- obl_def == impl_def
- && iter::zip(obl_substs, impl_substs)
- .all(|(obl, imp)| self.generic_args_may_unify(obl, imp))
+ obl_def == impl_def && self.substs_refs_may_unify(obl_substs, impl_substs)
}
_ => false,
},
@@ -290,15 +312,20 @@ impl DeepRejectCtxt {
// Impls cannot contain these types as these cannot be named directly.
ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
+ // Placeholder types don't unify with anything on their own
ty::Placeholder(..) | ty::Bound(..) => false,
// Depending on the value of `treat_obligation_params`, we either
// treat generic parameters like placeholders or like inference variables.
ty::Param(_) => match self.treat_obligation_params {
- TreatParams::AsPlaceholder => false,
- TreatParams::AsInfer => true,
+ TreatParams::ForLookup | TreatParams::NextSolverLookup => false,
+ TreatParams::AsCandidateKey => true,
},
+ ty::Infer(ty::IntVar(_)) => impl_ty.is_integral(),
+
+ ty::Infer(ty::FloatVar(_)) => impl_ty.is_floating_point(),
+
ty::Infer(_) => true,
// As we're walking the whole type, it may encounter projections
@@ -333,10 +360,13 @@ impl DeepRejectCtxt {
let k = impl_ct.kind();
match obligation_ct.kind() {
ty::ConstKind::Param(_) => match self.treat_obligation_params {
- TreatParams::AsPlaceholder => false,
- TreatParams::AsInfer => true,
+ TreatParams::ForLookup | TreatParams::NextSolverLookup => false,
+ TreatParams::AsCandidateKey => true,
},
+ // Placeholder consts don't unify with anything on their own
+ ty::ConstKind::Placeholder(_) => false,
+
// As we don't necessarily eagerly evaluate constants,
// they might unify with any value.
ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
@@ -349,7 +379,7 @@ impl DeepRejectCtxt {
ty::ConstKind::Infer(_) => true,
- ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
+ ty::ConstKind::Bound(..) => {
bug!("unexpected obl const: {:?}", obligation_ct)
}
}
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 91241ff40..5a6ee1238 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -288,7 +288,7 @@ impl FlagComputation {
self.add_ty(ty);
}
ty::PredicateKind::Ambiguous => {}
- ty::PredicateKind::AliasEq(t1, t2) => {
+ ty::PredicateKind::AliasRelate(t1, t2, _) => {
self.add_term(t1);
self.add_term(t2);
}
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index d66f436f9..203e16bea 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -51,9 +51,7 @@ where
// Region folder
impl<'tcx> TyCtxt<'tcx> {
- /// Folds the escaping and free regions in `value` using `f`, and
- /// sets `skipped_regions` to true if any late-bound region was found
- /// and skipped.
+ /// Folds the escaping and free regions in `value` using `f`.
pub fn fold_regions<T>(
self,
value: T,
@@ -64,17 +62,6 @@ impl<'tcx> TyCtxt<'tcx> {
{
value.fold_with(&mut RegionFolder::new(self, &mut f))
}
-
- pub fn super_fold_regions<T>(
- self,
- value: T,
- mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
- ) -> T
- where
- T: TypeSuperFoldable<TyCtxt<'tcx>>,
- {
- value.super_fold_with(&mut RegionFolder::new(self, &mut f))
- }
}
/// Folds over the substructure of a type, visiting its component
@@ -392,9 +379,7 @@ impl<'tcx> TyCtxt<'tcx> {
let index = entry.index();
let var = ty::BoundVar::from_usize(index);
let kind = entry
- .or_insert_with(|| {
- ty::BoundVariableKind::Region(ty::BrAnon(index as u32, None))
- })
+ .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(None)))
.expect_region();
let br = ty::BoundRegion { var, kind };
self.tcx.mk_re_late_bound(ty::INNERMOST, br)
@@ -404,9 +389,7 @@ impl<'tcx> TyCtxt<'tcx> {
let index = entry.index();
let var = ty::BoundVar::from_usize(index);
let kind = entry
- .or_insert_with(|| {
- ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon(index as u32))
- })
+ .or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon))
.expect_ty();
self.tcx.mk_bound(ty::INNERMOST, BoundTy { var, kind })
}
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index e268553f8..ac42d6e05 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -1,5 +1,5 @@
use crate::ty::context::TyCtxt;
-use crate::ty::{self, DefId, DefIdTree, ParamEnv, Ty};
+use crate::ty::{self, DefId, ParamEnv, Ty};
/// Represents whether some type is inhabited in a given context.
/// Examples of uninhabited types are `!`, `enum Void {}`, or a struct
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index f4028a5a9..e73225f70 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -82,6 +82,11 @@ pub enum InstanceDef<'tcx> {
/// The `DefId` is the ID of the `call_once` method in `FnOnce`.
ClosureOnceShim { call_once: DefId, track_caller: bool },
+ /// Compiler-generated accessor for thread locals which returns a reference to the thread local
+ /// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking
+ /// native support.
+ ThreadLocalShim(DefId),
+
/// `core::ptr::drop_in_place::<T>`.
///
/// The `DefId` is for `core::ptr::drop_in_place`.
@@ -96,6 +101,13 @@ pub enum InstanceDef<'tcx> {
///
/// The `DefId` is for `Clone::clone`, the `Ty` is the type `T` with the builtin `Clone` impl.
CloneShim(DefId, Ty<'tcx>),
+
+ /// Compiler-generated `<T as FnPtr>::addr` implementation.
+ ///
+ /// Automatically generated for all potentially higher-ranked `fn(I) -> R` types.
+ ///
+ /// The `DefId` is for `FnPtr::addr`, the `Ty` is the type `T`.
+ FnPtrAddrShim(DefId, Ty<'tcx>),
}
impl<'tcx> Instance<'tcx> {
@@ -149,9 +161,11 @@ impl<'tcx> InstanceDef<'tcx> {
| InstanceDef::FnPtrShim(def_id, _)
| InstanceDef::Virtual(def_id, _)
| InstanceDef::Intrinsic(def_id)
+ | InstanceDef::ThreadLocalShim(def_id)
| InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
| InstanceDef::DropGlue(def_id, _)
- | InstanceDef::CloneShim(def_id, _) => def_id,
+ | InstanceDef::CloneShim(def_id, _)
+ | InstanceDef::FnPtrAddrShim(def_id, _) => def_id,
}
}
@@ -159,7 +173,9 @@ impl<'tcx> InstanceDef<'tcx> {
pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
match self {
ty::InstanceDef::Item(def) => Some(def.did),
- ty::InstanceDef::DropGlue(def_id, Some(_)) => Some(def_id),
+ ty::InstanceDef::DropGlue(def_id, Some(_)) | InstanceDef::ThreadLocalShim(def_id) => {
+ Some(def_id)
+ }
InstanceDef::VTableShim(..)
| InstanceDef::ReifyShim(..)
| InstanceDef::FnPtrShim(..)
@@ -167,7 +183,8 @@ impl<'tcx> InstanceDef<'tcx> {
| InstanceDef::Intrinsic(..)
| InstanceDef::ClosureOnceShim { .. }
| InstanceDef::DropGlue(..)
- | InstanceDef::CloneShim(..) => None,
+ | InstanceDef::CloneShim(..)
+ | InstanceDef::FnPtrAddrShim(..) => None,
}
}
@@ -182,12 +199,18 @@ impl<'tcx> InstanceDef<'tcx> {
| InstanceDef::Intrinsic(def_id)
| InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
| InstanceDef::DropGlue(def_id, _)
- | InstanceDef::CloneShim(def_id, _) => ty::WithOptConstParam::unknown(def_id),
+ | InstanceDef::CloneShim(def_id, _)
+ | InstanceDef::ThreadLocalShim(def_id)
+ | InstanceDef::FnPtrAddrShim(def_id, _) => ty::WithOptConstParam::unknown(def_id),
}
}
#[inline]
- pub fn get_attrs(&self, tcx: TyCtxt<'tcx>, attr: Symbol) -> ty::Attributes<'tcx> {
+ pub fn get_attrs(
+ &self,
+ tcx: TyCtxt<'tcx>,
+ attr: Symbol,
+ ) -> impl Iterator<Item = &'tcx rustc_ast::Attribute> {
tcx.get_attrs(self.def_id(), attr)
}
@@ -201,6 +224,7 @@ impl<'tcx> InstanceDef<'tcx> {
let def_id = match *self {
ty::InstanceDef::Item(def) => def.did,
ty::InstanceDef::DropGlue(_, Some(_)) => return false,
+ ty::InstanceDef::ThreadLocalShim(_) => return false,
_ => return true,
};
matches!(
@@ -241,6 +265,9 @@ impl<'tcx> InstanceDef<'tcx> {
)
});
}
+ if let ty::InstanceDef::ThreadLocalShim(..) = *self {
+ return false;
+ }
tcx.codegen_fn_attrs(self.def_id()).requests_inline()
}
@@ -264,6 +291,8 @@ impl<'tcx> InstanceDef<'tcx> {
pub fn has_polymorphic_mir_body(&self) -> bool {
match *self {
InstanceDef::CloneShim(..)
+ | InstanceDef::ThreadLocalShim(..)
+ | InstanceDef::FnPtrAddrShim(..)
| InstanceDef::FnPtrShim(..)
| InstanceDef::DropGlue(_, Some(_)) => false,
InstanceDef::ClosureOnceShim { .. }
@@ -295,6 +324,7 @@ fn fmt_instance(
InstanceDef::Item(_) => Ok(()),
InstanceDef::VTableShim(_) => write!(f, " - shim(vtable)"),
InstanceDef::ReifyShim(_) => write!(f, " - shim(reify)"),
+ InstanceDef::ThreadLocalShim(_) => write!(f, " - shim(tls)"),
InstanceDef::Intrinsic(_) => write!(f, " - intrinsic"),
InstanceDef::Virtual(_, num) => write!(f, " - virtual#{}", num),
InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({})", ty),
@@ -302,6 +332,7 @@ fn fmt_instance(
InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"),
InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({}))", ty),
InstanceDef::CloneShim(_, ty) => write!(f, " - shim({})", ty),
+ InstanceDef::FnPtrAddrShim(_, ty) => write!(f, " - shim({})", ty),
}
}
@@ -781,6 +812,12 @@ fn needs_fn_once_adapter_shim(
#[derive(Debug, Copy, Clone, Eq, PartialEq, Decodable, Encodable, HashStable)]
pub struct UnusedGenericParams(FiniteBitSet<u32>);
+impl Default for UnusedGenericParams {
+ fn default() -> Self {
+ UnusedGenericParams::new_all_used()
+ }
+}
+
impl UnusedGenericParams {
pub fn new_all_unused(amount: u32) -> Self {
let mut bitset = FiniteBitSet::new_empty();
@@ -807,4 +844,12 @@ impl UnusedGenericParams {
pub fn all_used(&self) -> bool {
self.0.is_empty()
}
+
+ pub fn bits(&self) -> u32 {
+ self.0.0
+ }
+
+ pub fn from_bits(bits: u32) -> UnusedGenericParams {
+ UnusedGenericParams(FiniteBitSet(bits))
+ }
}
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 254ffc33c..195d951f9 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -5,7 +5,7 @@ use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
-use rustc_index::vec::Idx;
+use rustc_index::vec::IndexVec;
use rustc_session::config::OptLevel;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
@@ -281,6 +281,12 @@ pub enum SizeSkeleton<'tcx> {
/// Any statically computable Layout.
Known(Size),
+ /// This is a generic const expression (i.e. N * 2), which may contain some parameters.
+ /// It must be of type usize, and represents the size of a type in bytes.
+ /// It is not required to be evaluatable to a concrete value, but can be used to check
+ /// that another SizeSkeleton is of equal size.
+ Generic(ty::Const<'tcx>),
+
/// A potentially-fat pointer.
Pointer {
/// If true, this pointer is never null.
@@ -326,6 +332,37 @@ impl<'tcx> SizeSkeleton<'tcx> {
),
}
}
+ ty::Array(inner, len)
+ if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts =>
+ {
+ match SizeSkeleton::compute(inner, tcx, param_env)? {
+ // This may succeed because the multiplication of two types may overflow
+ // but a single size of a nested array will not.
+ SizeSkeleton::Known(s) => {
+ if let Some(c) = len.try_eval_target_usize(tcx, param_env) {
+ let size = s
+ .bytes()
+ .checked_mul(c)
+ .ok_or_else(|| LayoutError::SizeOverflow(ty))?;
+ return Ok(SizeSkeleton::Known(Size::from_bytes(size)));
+ }
+ let len = tcx.expand_abstract_consts(len);
+ let prev = ty::Const::from_target_usize(tcx, s.bytes());
+ let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else {
+ return Err(LayoutError::SizeOverflow(ty));
+ };
+ Ok(SizeSkeleton::Generic(gen_size))
+ }
+ SizeSkeleton::Pointer { .. } => Err(err),
+ SizeSkeleton::Generic(g) => {
+ let len = tcx.expand_abstract_consts(len);
+ let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else {
+ return Err(LayoutError::SizeOverflow(ty));
+ };
+ Ok(SizeSkeleton::Generic(gen_size))
+ }
+ }
+ }
ty::Adt(def, substs) => {
// Only newtypes and enums w/ nullable pointer optimization.
@@ -335,7 +372,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
// Get a zero-sized variant or a pointer newtype.
let zero_or_ptr_variant = |i| {
- let i = VariantIdx::new(i);
+ let i = VariantIdx::from_usize(i);
let fields =
def.variant(i).fields.iter().map(|field| {
SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env)
@@ -355,6 +392,9 @@ impl<'tcx> SizeSkeleton<'tcx> {
}
ptr = Some(field);
}
+ SizeSkeleton::Generic(_) => {
+ return Err(err);
+ }
}
}
Ok(ptr)
@@ -410,11 +450,66 @@ impl<'tcx> SizeSkeleton<'tcx> {
(SizeSkeleton::Pointer { tail: a, .. }, SizeSkeleton::Pointer { tail: b, .. }) => {
a == b
}
+ // constants are always pre-normalized into a canonical form so this
+ // only needs to check if their pointers are identical.
+ (SizeSkeleton::Generic(a), SizeSkeleton::Generic(b)) => a == b,
_ => false,
}
}
}
+/// When creating the layout for types with abstract conts in their size (i.e. [usize; 4 * N]),
+/// to ensure that they have a canonical order and can be compared directly we combine all
+/// constants, and sort the other terms. This allows comparison of expressions of sizes,
+/// allowing for things like transmutating between types that depend on generic consts.
+/// This returns `None` if multiplication of constants overflows.
+fn mul_sorted_consts<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ a: ty::Const<'tcx>,
+ b: ty::Const<'tcx>,
+) -> Option<ty::Const<'tcx>> {
+ use crate::mir::BinOp::Mul;
+ use ty::ConstKind::Expr;
+ use ty::Expr::Binop;
+
+ let mut work = vec![a, b];
+ let mut done = vec![];
+ while let Some(n) = work.pop() {
+ if let Expr(Binop(Mul, l, r)) = n.kind() {
+ work.push(l);
+ work.push(r)
+ } else {
+ done.push(n);
+ }
+ }
+ let mut k = 1;
+ let mut overflow = false;
+ done.retain(|c| {
+ let Some(c) = c.try_eval_target_usize(tcx, param_env) else {
+ return true;
+ };
+ let Some(next) = c.checked_mul(k) else {
+ overflow = true;
+ return false;
+ };
+ k = next;
+ false
+ });
+ if overflow {
+ return None;
+ }
+ if k != 1 {
+ done.push(ty::Const::from_target_usize(tcx, k));
+ } else if k == 0 {
+ return Some(ty::Const::from_target_usize(tcx, 0));
+ }
+ done.sort_unstable();
+
+ // create a single tree from the buffer
+ done.into_iter().reduce(|acc, n| tcx.mk_const(Expr(Binop(Mul, n, acc)), n.ty()))
+}
+
pub trait HasTyCtxt<'tcx>: HasDataLayout {
fn tcx(&self) -> TyCtxt<'tcx>;
}
@@ -636,7 +731,7 @@ where
variants: Variants::Single { index: variant_index },
fields: match NonZeroUsize::new(fields) {
Some(fields) => FieldsShape::Union(fields),
- None => FieldsShape::Arbitrary { offsets: vec![], memory_index: vec![] },
+ None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() },
},
abi: Abi::Uninhabited,
largest_niche: None,
@@ -730,7 +825,11 @@ where
*/
};
- let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
+ let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type()
+ // Projection eagerly bails out when the pointee references errors,
+ // fall back to structurally deducing metadata.
+ && !pointee.references_error()
+ {
let metadata = tcx.normalize_erasing_regions(
cx.param_env(),
tcx.mk_projection(metadata_def_id, [pointee]),
@@ -794,7 +893,8 @@ where
ty::Adt(def, substs) => {
match this.variants {
Variants::Single { index } => {
- TyMaybeWithLayout::Ty(def.variant(index).fields[i].ty(tcx, substs))
+ let field = &def.variant(index).fields[FieldIdx::from_usize(i)];
+ TyMaybeWithLayout::Ty(field.ty(tcx, substs))
}
// Discriminant field for enums (where applicable).
@@ -1126,10 +1226,11 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
| AvrNonBlockingInterrupt
| CCmseNonSecureCall
| Wasm
- | RustIntrinsic
| PlatformIntrinsic
| Unadjusted => false,
- Rust | RustCall | RustCold => tcx.sess.panic_strategy() == PanicStrategy::Unwind,
+ Rust | RustCall | RustCold | RustIntrinsic => {
+ tcx.sess.panic_strategy() == PanicStrategy::Unwind
+ }
}
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index dce18a585..2e516f291 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -34,6 +34,7 @@ use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::steal::Steal;
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
@@ -44,10 +45,12 @@ use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
use rustc_serialize::{Decodable, Encodable};
+use rustc_session::lint::LintBuffer;
+pub use rustc_session::lint::RegisteredTools;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ExpnId, ExpnKind, Span};
-use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx};
+use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions};
use rustc_type_ir::WithCachedTypeInfo;
pub use subst::*;
@@ -148,8 +151,6 @@ mod typeck_results;
// Data types
-pub type RegisteredTools = FxHashSet<Ident>;
-
pub struct ResolverOutputs {
pub global_ctxt: ResolverGlobalCtxt,
pub ast_lowering: ResolverAstLowering,
@@ -165,7 +166,8 @@ pub struct ResolverGlobalCtxt {
pub effective_visibilities: EffectiveVisibilities,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
- pub reexport_map: FxHashMap<LocalDefId, Vec<ModChild>>,
+ pub module_children_non_reexports: LocalDefIdMap<Vec<LocalDefId>>,
+ pub module_children_reexports: LocalDefIdMap<Vec<ModChild>>,
pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
pub main_def: Option<MainDefinition>,
pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
@@ -175,7 +177,6 @@ pub struct ResolverGlobalCtxt {
/// 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,
pub doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>,
pub doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>,
pub all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
@@ -209,6 +210,9 @@ pub struct ResolverAstLowering {
pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
/// List functions and methods for which lifetime elision was successful.
pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
+
+ /// Lints that were emitted by the resolver and early lints.
+ pub lint_buffer: Steal<LintBuffer>,
}
#[derive(Clone, Copy, Debug)]
@@ -325,12 +329,15 @@ pub struct ClosureSizeProfileData<'tcx> {
pub after_feature_tys: Ty<'tcx>,
}
-pub trait DefIdTree: Copy {
- fn opt_parent(self, id: DefId) -> Option<DefId>;
+impl TyCtxt<'_> {
+ #[inline]
+ pub fn opt_parent(self, id: DefId) -> Option<DefId> {
+ self.def_key(id).parent.map(|index| DefId { index, ..id })
+ }
#[inline]
#[track_caller]
- fn parent(self, id: DefId) -> DefId {
+ pub fn parent(self, id: DefId) -> DefId {
match self.opt_parent(id) {
Some(id) => id,
// not `unwrap_or_else` to avoid breaking caller tracking
@@ -340,17 +347,17 @@ pub trait DefIdTree: Copy {
#[inline]
#[track_caller]
- fn opt_local_parent(self, id: LocalDefId) -> Option<LocalDefId> {
+ pub fn opt_local_parent(self, id: LocalDefId) -> Option<LocalDefId> {
self.opt_parent(id.to_def_id()).map(DefId::expect_local)
}
#[inline]
#[track_caller]
- fn local_parent(self, id: LocalDefId) -> LocalDefId {
+ pub fn local_parent(self, id: LocalDefId) -> LocalDefId {
self.parent(id.to_def_id()).expect_local()
}
- fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
+ pub fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
if descendant.krate != ancestor.krate {
return false;
}
@@ -365,13 +372,6 @@ pub trait DefIdTree: Copy {
}
}
-impl<'tcx> DefIdTree for TyCtxt<'tcx> {
- #[inline]
- fn opt_parent(self, id: DefId) -> Option<DefId> {
- self.def_key(id).parent.map(|index| DefId { index, ..id })
- }
-}
-
impl<Id> Visibility<Id> {
pub fn is_public(self) -> bool {
matches!(self, Visibility::Public)
@@ -391,19 +391,19 @@ impl<Id: Into<DefId>> Visibility<Id> {
}
/// Returns `true` if an item with this visibility is accessible from the given module.
- pub fn is_accessible_from(self, module: impl Into<DefId>, tree: impl DefIdTree) -> bool {
+ pub fn is_accessible_from(self, module: impl Into<DefId>, tcx: TyCtxt<'_>) -> bool {
match self {
// Public items are visible everywhere.
Visibility::Public => true,
- Visibility::Restricted(id) => tree.is_descendant_of(module.into(), id.into()),
+ Visibility::Restricted(id) => tcx.is_descendant_of(module.into(), id.into()),
}
}
/// Returns `true` if this visibility is at least as accessible as the given visibility
- pub fn is_at_least(self, vis: Visibility<impl Into<DefId>>, tree: impl DefIdTree) -> bool {
+ pub fn is_at_least(self, vis: Visibility<impl Into<DefId>>, tcx: TyCtxt<'_>) -> bool {
match vis {
Visibility::Public => self.is_public(),
- Visibility::Restricted(id) => self.is_accessible_from(id, tree),
+ Visibility::Restricted(id) => self.is_accessible_from(id, tcx),
}
}
}
@@ -544,7 +544,7 @@ impl<'tcx> Predicate<'tcx> {
| PredicateKind::Clause(Clause::TypeOutlives(_))
| PredicateKind::Clause(Clause::Projection(_))
| PredicateKind::Clause(Clause::ConstArgHasType(..))
- | PredicateKind::AliasEq(..)
+ | PredicateKind::AliasRelate(..)
| PredicateKind::ObjectSafe(_)
| PredicateKind::ClosureKind(_, _, _)
| PredicateKind::Subtype(_)
@@ -641,7 +641,23 @@ pub enum PredicateKind<'tcx> {
/// This predicate requires two terms to be equal to eachother.
///
/// Only used for new solver
- AliasEq(Term<'tcx>, Term<'tcx>),
+ AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection),
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, Debug)]
+pub enum AliasRelationDirection {
+ Equate,
+ Subtype,
+}
+
+impl std::fmt::Display for AliasRelationDirection {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ AliasRelationDirection::Equate => write!(f, "=="),
+ AliasRelationDirection::Subtype => write!(f, "<:"),
+ }
+ }
}
/// The crate outlives map is computed during typeck and contains the
@@ -977,11 +993,11 @@ impl<'tcx> Term<'tcx> {
}
}
- /// This function returns `None` for `AliasKind::Opaque`.
+ /// This function returns the inner `AliasTy` if this term is a projection.
///
/// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly
/// deal with constants.
- pub fn to_alias_term_no_opaque(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
+ pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
match self.unpack() {
TermKind::Ty(ty) => match ty.kind() {
ty::Alias(kind, alias_ty) => match kind {
@@ -999,7 +1015,7 @@ impl<'tcx> Term<'tcx> {
pub fn is_infer(&self) -> bool {
match self.unpack() {
- TermKind::Ty(ty) => ty.is_ty_or_numeric_infer(),
+ TermKind::Ty(ty) => ty.is_ty_var(),
TermKind::Const(ct) => ct.is_ct_infer(),
}
}
@@ -1036,6 +1052,21 @@ impl<'tcx> TermKind<'tcx> {
}
}
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum ParamTerm {
+ Ty(ParamTy),
+ Const(ParamConst),
+}
+
+impl ParamTerm {
+ pub fn index(self) -> usize {
+ match self {
+ ParamTerm::Ty(ty) => ty.index as usize,
+ ParamTerm::Const(ct) => ct.index as usize,
+ }
+ }
+}
+
/// This kind of predicate has no *direct* correspondent in the
/// syntax, but it roughly corresponds to the syntactic forms:
///
@@ -1129,6 +1160,13 @@ impl<'tcx, T> ToPredicate<'tcx, T> for T {
}
}
+impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ ty::Binder::dummy(self).to_predicate(tcx)
+ }
+}
+
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
@@ -1143,6 +1181,13 @@ impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
}
}
+impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ ty::Binder::dummy(self).to_predicate(tcx)
+ }
+}
+
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
@@ -1193,7 +1238,7 @@ impl<'tcx> Predicate<'tcx> {
PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(Clause::Projection(..))
| PredicateKind::Clause(Clause::ConstArgHasType(..))
- | PredicateKind::AliasEq(..)
+ | PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))
@@ -1214,7 +1259,7 @@ impl<'tcx> Predicate<'tcx> {
PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(Clause::Trait(..))
| PredicateKind::Clause(Clause::ConstArgHasType(..))
- | PredicateKind::AliasEq(..)
+ | PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))
@@ -1236,7 +1281,7 @@ impl<'tcx> Predicate<'tcx> {
PredicateKind::Clause(Clause::Trait(..))
| PredicateKind::Clause(Clause::ConstArgHasType(..))
| PredicateKind::Clause(Clause::Projection(..))
- | PredicateKind::AliasEq(..)
+ | PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))
@@ -1386,7 +1431,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
// lifetimes with 'static and remapping only those used in the
// `impl Trait` return type, resulting in the parameters
// shifting.
- let id_substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
debug!(?id_substs);
// This zip may have several times the same lifetime in `substs` paired with a different
@@ -1410,12 +1455,12 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
#[derive(HashStable, TyEncodable, TyDecodable)]
pub struct Placeholder<T> {
pub universe: UniverseIndex,
- pub name: T,
+ pub bound: T,
}
-pub type PlaceholderRegion = Placeholder<BoundRegionKind>;
+pub type PlaceholderRegion = Placeholder<BoundRegion>;
-pub type PlaceholderType = Placeholder<BoundTyKind>;
+pub type PlaceholderType = Placeholder<BoundTy>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
@@ -1847,7 +1892,7 @@ pub struct VariantDef {
/// Discriminant of this variant.
pub discr: VariantDiscr,
/// Fields of this variant.
- pub fields: Vec<FieldDef>,
+ pub fields: IndexVec<FieldIdx, FieldDef>,
/// Flags of the variant (e.g. is field list non-exhaustive)?
flags: VariantFlags,
}
@@ -1874,7 +1919,7 @@ impl VariantDef {
variant_did: Option<DefId>,
ctor: Option<(CtorKind, DefId)>,
discr: VariantDiscr,
- fields: Vec<FieldDef>,
+ fields: IndexVec<FieldIdx, FieldDef>,
adt_kind: AdtKind,
parent_did: DefId,
recovered: bool,
@@ -2028,7 +2073,6 @@ impl<'tcx> FieldDef {
}
}
-pub type Attributes<'tcx> = impl Iterator<Item = &'tcx ast::Attribute>;
#[derive(Debug, PartialEq, Eq)]
pub enum ImplOverlapKind {
/// These impls are always allowed to overlap.
@@ -2071,7 +2115,9 @@ pub enum ImplOverlapKind {
Issue33140,
}
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
+/// Useful source information about where a desugared associated type for an
+/// RPITIT originated from.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable)]
pub enum ImplTraitInTraitData {
Trait { fn_def_id: DefId, opaque_def_id: DefId },
Impl { fn_def_id: DefId },
@@ -2214,26 +2260,37 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
- variant
- .fields
- .iter()
- .position(|field| self.hygienic_eq(ident, field.ident(self), variant.def_id))
+ /// If the def-id is an associated type that was desugared from a
+ /// return-position `impl Trait` from a trait, then provide the source info
+ /// about where that RPITIT came from.
+ pub fn opt_rpitit_info(self, def_id: DefId) -> Option<ImplTraitInTraitData> {
+ if let DefKind::AssocTy = self.def_kind(def_id) {
+ self.associated_item(def_id).opt_rpitit_info
+ } else {
+ None
+ }
+ }
+
+ pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<FieldIdx> {
+ variant.fields.iter_enumerated().find_map(|(i, field)| {
+ self.hygienic_eq(ident, field.ident(self), variant.def_id).then_some(i)
+ })
}
/// Returns `true` if the impls are the same polarity and the trait either
/// has no items or is annotated `#[marker]` and prevents item overrides.
+ #[instrument(level = "debug", skip(self), ret)]
pub fn impls_are_allowed_to_overlap(
self,
def_id1: DefId,
def_id2: DefId,
) -> Option<ImplOverlapKind> {
+ let impl_trait_ref1 = self.impl_trait_ref(def_id1);
+ let impl_trait_ref2 = self.impl_trait_ref(def_id2);
// If either trait impl references an error, they're allowed to overlap,
// as one of them essentially doesn't exist.
- if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.subst_identity().references_error())
- || self
- .impl_trait_ref(def_id2)
- .map_or(false, |tr| tr.subst_identity().references_error())
+ if impl_trait_ref1.map_or(false, |tr| tr.subst_identity().references_error())
+ || impl_trait_ref2.map_or(false, |tr| tr.subst_identity().references_error())
{
return Some(ImplOverlapKind::Permitted { marker: false });
}
@@ -2241,19 +2298,11 @@ impl<'tcx> TyCtxt<'tcx> {
match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) {
(ImplPolarity::Reservation, _) | (_, ImplPolarity::Reservation) => {
// `#[rustc_reservation_impl]` impls don't overlap with anything
- debug!(
- "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (reservations)",
- def_id1, def_id2
- );
return Some(ImplOverlapKind::Permitted { marker: false });
}
(ImplPolarity::Positive, ImplPolarity::Negative)
| (ImplPolarity::Negative, ImplPolarity::Positive) => {
// `impl AutoTrait for Type` + `impl !AutoTrait for Type`
- debug!(
- "impls_are_allowed_to_overlap({:?}, {:?}) - None (differing polarities)",
- def_id1, def_id2
- );
return None;
}
(ImplPolarity::Positive, ImplPolarity::Positive)
@@ -2261,38 +2310,25 @@ impl<'tcx> TyCtxt<'tcx> {
};
let is_marker_overlap = {
- let is_marker_impl = |def_id: DefId| -> bool {
- let trait_ref = self.impl_trait_ref(def_id);
+ let is_marker_impl = |trait_ref: Option<EarlyBinder<TraitRef<'_>>>| -> bool {
trait_ref.map_or(false, |tr| self.trait_def(tr.skip_binder().def_id).is_marker)
};
- is_marker_impl(def_id1) && is_marker_impl(def_id2)
+ is_marker_impl(impl_trait_ref1) && is_marker_impl(impl_trait_ref2)
};
if is_marker_overlap {
- debug!(
- "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (marker overlap)",
- def_id1, def_id2
- );
Some(ImplOverlapKind::Permitted { marker: true })
} else {
if let Some(self_ty1) = self.issue33140_self_ty(def_id1) {
if let Some(self_ty2) = self.issue33140_self_ty(def_id2) {
if self_ty1 == self_ty2 {
- debug!(
- "impls_are_allowed_to_overlap({:?}, {:?}) - issue #33140 HACK",
- def_id1, def_id2
- );
return Some(ImplOverlapKind::Issue33140);
} else {
- debug!(
- "impls_are_allowed_to_overlap({:?}, {:?}) - found {:?} != {:?}",
- def_id1, def_id2, self_ty1, self_ty2
- );
+ debug!("found {self_ty1:?} != {self_ty2:?}");
}
}
}
- debug!("impls_are_allowed_to_overlap({:?}, {:?}) = None", def_id1, def_id2);
None
}
}
@@ -2349,7 +2385,9 @@ impl<'tcx> TyCtxt<'tcx> {
| ty::InstanceDef::Virtual(..)
| ty::InstanceDef::ClosureOnceShim { .. }
| ty::InstanceDef::DropGlue(..)
- | ty::InstanceDef::CloneShim(..) => self.mir_shims(instance),
+ | ty::InstanceDef::CloneShim(..)
+ | ty::InstanceDef::ThreadLocalShim(..)
+ | ty::InstanceDef::FnPtrAddrShim(..) => self.mir_shims(instance),
}
}
@@ -2363,7 +2401,12 @@ impl<'tcx> TyCtxt<'tcx> {
}
/// Gets all attributes with the given name.
- pub fn get_attrs(self, did: DefId, attr: Symbol) -> ty::Attributes<'tcx> {
+ pub fn get_attrs(
+ self,
+ did: impl Into<DefId>,
+ attr: Symbol,
+ ) -> impl Iterator<Item = &'tcx ast::Attribute> {
+ let did: DefId = did.into();
let filter_fn = move |a: &&ast::Attribute| a.has_name(attr);
if let Some(did) = did.as_local() {
self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn)
@@ -2374,8 +2417,9 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- pub fn get_attr(self, did: DefId, attr: Symbol) -> Option<&'tcx ast::Attribute> {
+ pub fn get_attr(self, did: impl Into<DefId>, attr: Symbol) -> Option<&'tcx ast::Attribute> {
if cfg!(debug_assertions) && !rustc_feature::is_valid_for_get_attr(attr) {
+ let did: DefId = did.into();
bug!("get_attr: unexpected called with DefId `{:?}`, attr `{:?}`", did, attr);
} else {
self.get_attrs(did, attr).next()
@@ -2383,7 +2427,8 @@ impl<'tcx> TyCtxt<'tcx> {
}
/// Determines whether an item is annotated with an attribute.
- pub fn has_attr(self, did: DefId, attr: Symbol) -> bool {
+ pub fn has_attr(self, did: impl Into<DefId>, attr: Symbol) -> bool {
+ let did: DefId = did.into();
if cfg!(debug_assertions) && !did.is_local() && rustc_feature::is_builtin_only_local(attr) {
bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr);
} else {
@@ -2493,7 +2538,7 @@ impl<'tcx> TyCtxt<'tcx> {
ident
}
- // FIXME(vincenzoapalzzo): move the HirId to a LocalDefId
+ // FIXME(vincenzopalazzo): move the HirId to a LocalDefId
pub fn adjust_ident_and_get_scope(
self,
mut ident: Ident,
@@ -2540,12 +2585,18 @@ impl<'tcx> TyCtxt<'tcx> {
matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait))
}
- pub fn impl_trait_in_trait_parent(self, mut def_id: DefId) -> DefId {
- while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
- debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
- def_id = self.parent(def_id);
+ pub fn impl_trait_in_trait_parent_fn(self, mut def_id: DefId) -> DefId {
+ match self.opt_rpitit_info(def_id) {
+ Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
+ | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) => fn_def_id,
+ None => {
+ while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
+ debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
+ def_id = self.parent(def_id);
+ }
+ def_id
+ }
}
- def_id
}
pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
@@ -2560,6 +2611,12 @@ impl<'tcx> TyCtxt<'tcx> {
let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
+ if self.lower_impl_trait_in_trait_to_assoc_ty() {
+ return !self
+ .associated_types_for_impl_traits_in_associated_fn(trait_item_def_id)
+ .is_empty();
+ }
+
// FIXME(RPITIT): This does a somewhat manual walk through the signature
// of the trait fn to look for any RPITITs, but that's kinda doing a lot
// of work. We can probably remove this when we refactor RPITITs to be
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 8849e7eab..7534d06ae 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -63,6 +63,7 @@ trivially_parameterized_over_tcx! {
ty::DeducedParamAttrs,
ty::Generics,
ty::ImplPolarity,
+ ty::ImplTraitInTraitData,
ty::ReprOptions,
ty::TraitDef,
ty::UnusedGenericParams,
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 021c20b58..d947d9604 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -1,5 +1,5 @@
use crate::ty::GenericArg;
-use crate::ty::{self, DefIdTree, Ty, TyCtxt};
+use crate::ty::{self, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sso::SsoHashSet;
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 6a053c368..72caadaf6 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,6 +1,6 @@
use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
use crate::ty::{
- self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
+ self, ConstInt, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
use crate::ty::{GenericArg, GenericArgKind};
@@ -701,10 +701,12 @@ pub trait PrettyPrinter<'tcx>:
ty::Error(_) => p!("[type error]"),
ty::Param(ref param_ty) => p!(print(param_ty)),
ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
- ty::BoundTyKind::Anon(bv) => {
- self.pretty_print_bound_var(debruijn, ty::BoundVar::from_u32(bv))?
- }
- ty::BoundTyKind::Param(_, s) => p!(write("{}", s)),
+ ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
+ ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() {
+ true if debruijn == ty::INNERMOST => p!(write("^{}", s)),
+ true => p!(write("^{}_{}", debruijn.index(), s)),
+ false => p!(write("{}", s)),
+ },
},
ty::Adt(def, substs) => {
p!(print_def_path(def.did(), substs));
@@ -728,15 +730,15 @@ pub trait PrettyPrinter<'tcx>:
}
ty::Alias(ty::Projection, ref data) => {
if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
- && self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
+ && self.tcx().is_impl_trait_in_trait(data.def_id)
{
return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
} else {
p!(print(data))
}
}
- ty::Placeholder(placeholder) => match placeholder.name {
- ty::BoundTyKind::Anon(_) => p!(write("Placeholder({:?})", placeholder)),
+ ty::Placeholder(placeholder) => match placeholder.bound.kind {
+ ty::BoundTyKind::Anon => p!(write("Placeholder({:?})", placeholder)),
ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
},
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
@@ -1345,7 +1347,7 @@ pub trait PrettyPrinter<'tcx>:
p!(write("{}::{}", self.tcx().crate_name(def.did.krate), self.tcx().def_path(def.did).to_string_no_crate_verbose()))
}
}
- defkind => bug!("`{:?}` has unexpcted defkind {:?}", ct, defkind),
+ defkind => bug!("`{:?}` has unexpected defkind {:?}", ct, defkind),
}
}
ty::ConstKind::Infer(infer_ct) => {
@@ -2100,7 +2102,9 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
| ty::ReFree(ty::FreeRegion { bound_region: br, .. })
- | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+ | ty::RePlaceholder(ty::Placeholder {
+ bound: ty::BoundRegion { kind: br, .. }, ..
+ }) => {
if br.is_named() {
return true;
}
@@ -2177,7 +2181,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
}
ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
| ty::ReFree(ty::FreeRegion { bound_region: br, .. })
- | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+ | ty::RePlaceholder(ty::Placeholder {
+ bound: ty::BoundRegion { kind: br, .. }, ..
+ }) => {
if let ty::BrNamed(_, name) = br && br.is_named() {
p!(write("{}", name));
return Ok(self);
@@ -2255,7 +2261,10 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
ty::ReLateBound(db, br) if db >= self.current_index => {
*self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br))
}
- ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => {
+ ty::RePlaceholder(ty::PlaceholderRegion {
+ bound: ty::BoundRegion { kind, .. },
+ ..
+ }) => {
// If this is an anonymous placeholder, don't rename. Otherwise, in some
// async fns, we get a `for<'r> Send` bound
match kind {
@@ -2847,7 +2856,7 @@ define_print_and_forward_display! {
p!("the type `", print(ty), "` is found in the environment")
}
ty::PredicateKind::Ambiguous => p!("ambiguous"),
- ty::PredicateKind::AliasEq(t1, t2) => p!(print(t1), " == ", print(t2)),
+ ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
}
}
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index 2bc51baf8..fa9fea723 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -17,7 +17,8 @@ use crate::mir::interpret::{
};
use crate::mir::interpret::{LitToConstError, LitToConstInput};
use crate::mir::mono::CodegenUnit;
-use crate::query::Key;
+use crate::query::erase::{erase, restore, Erase};
+use crate::query::{AsLocalKey, Key};
use crate::thir;
use crate::traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
@@ -41,7 +42,7 @@ use rustc_arena::TypedArena;
use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_attr as attr;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::Lrc;
@@ -50,11 +51,15 @@ use rustc_data_structures::unord::UnordSet;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, DocLinkResMap};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
+use rustc_hir::def_id::{
+ CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet,
+};
use rustc_hir::hir_id::OwnerId;
use rustc_hir::lang_items::{LangItem, LanguageItems};
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
use rustc_index::vec::IndexVec;
+pub(crate) use rustc_query_system::query::QueryJobId;
+use rustc_query_system::query::*;
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::cstore::{CrateDepKind, CrateSource};
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
@@ -64,18 +69,19 @@ use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi;
use rustc_target::spec::PanicStrategy;
+
+use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;
-pub(crate) use rustc_query_system::query::QueryJobId;
-use rustc_query_system::query::*;
-
#[derive(Default)]
pub struct QuerySystem<'tcx> {
pub arenas: QueryArenas<'tcx>,
pub caches: QueryCaches<'tcx>,
+ // Since we erase query value types we tell the typesystem about them with `PhantomData`.
+ _phantom_values: QueryPhantomValues<'tcx>,
}
#[derive(Copy, Clone)]
@@ -97,6 +103,11 @@ pub struct TyCtxtEnsure<'tcx> {
pub tcx: TyCtxt<'tcx>,
}
+#[derive(Copy, Clone)]
+pub struct TyCtxtEnsureWithValue<'tcx> {
+ pub tcx: TyCtxt<'tcx>,
+}
+
impl<'tcx> TyCtxt<'tcx> {
/// Returns a transparent wrapper for `TyCtxt`, which ensures queries
/// are executed instead of just returning their results.
@@ -105,6 +116,15 @@ impl<'tcx> TyCtxt<'tcx> {
TyCtxtEnsure { tcx: self }
}
+ /// Returns a transparent wrapper for `TyCtxt`, which ensures queries
+ /// are executed instead of just returning their results.
+ ///
+ /// This version verifies that the computed result exists in the cache before returning.
+ #[inline(always)]
+ pub fn ensure_with_value(self) -> TyCtxtEnsureWithValue<'tcx> {
+ TyCtxtEnsureWithValue { tcx: self }
+ }
+
/// Returns a transparent wrapper for `TyCtxt` which uses
/// `span` as the location of queries performed through it.
#[inline(always)]
@@ -135,6 +155,20 @@ macro_rules! query_if_arena {
};
}
+/// If `separate_provide_if_extern`, then the key can be projected to its
+/// local key via `<$K as AsLocalKey>::LocalKey`.
+macro_rules! local_key_if_separate_extern {
+ ([] $($K:tt)*) => {
+ $($K)*
+ };
+ ([(separate_provide_extern) $($rest:tt)*] $($K:tt)*) => {
+ <$($K)* as AsLocalKey>::LocalKey
+ };
+ ([$other:tt $($modifiers:tt)*] $($K:tt)*) => {
+ local_key_if_separate_extern!([$($modifiers)*] $($K)*)
+ };
+}
+
macro_rules! separate_provide_extern_decl {
([][$name:ident]) => {
()
@@ -196,6 +230,12 @@ macro_rules! define_callbacks {
$(pub type $name<'tcx> = $($K)*;)*
}
#[allow(nonstandard_style, unused_lifetimes)]
+ pub mod query_keys_local {
+ use super::*;
+
+ $(pub type $name<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*);)*
+ }
+ #[allow(nonstandard_style, unused_lifetimes)]
pub mod query_values {
use super::*;
@@ -227,8 +267,8 @@ macro_rules! define_callbacks {
pub fn $name<'tcx>(
_tcx: TyCtxt<'tcx>,
value: query_provided::$name<'tcx>,
- ) -> query_values::$name<'tcx> {
- query_if_arena!([$($modifiers)*]
+ ) -> Erase<query_values::$name<'tcx>> {
+ erase(query_if_arena!([$($modifiers)*]
{
if mem::needs_drop::<query_provided::$name<'tcx>>() {
&*_tcx.query_system.arenas.$name.alloc(value)
@@ -237,7 +277,7 @@ macro_rules! define_callbacks {
}
}
(value)
- )
+ ))
}
)*
}
@@ -246,10 +286,40 @@ macro_rules! define_callbacks {
use super::*;
$(
- pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache;
+ pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>>::Cache;
)*
}
+ $(
+ // Ensure that keys grow no larger than 64 bytes
+ #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+ const _: () = {
+ if mem::size_of::<query_keys::$name<'static>>() > 64 {
+ panic!("{}", concat!(
+ "the query `",
+ stringify!($name),
+ "` has a key type `",
+ stringify!($($K)*),
+ "` that is too large"
+ ));
+ }
+ };
+
+ // Ensure that values grow no larger than 64 bytes
+ #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+ const _: () = {
+ if mem::size_of::<query_values::$name<'static>>() > 64 {
+ panic!("{}", concat!(
+ "the query `",
+ stringify!($name),
+ "` has a value type `",
+ stringify!($V),
+ "` that is too large"
+ ));
+ }
+ };
+ )*
+
pub struct QueryArenas<'tcx> {
$($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*]
(WorkerLocal<TypedArena<<$V as Deref>::Target>>)
@@ -269,6 +339,11 @@ macro_rules! define_callbacks {
}
#[derive(Default)]
+ pub struct QueryPhantomValues<'tcx> {
+ $($(#[$attr])* pub $name: PhantomData<query_values::$name<'tcx>>,)*
+ }
+
+ #[derive(Default)]
pub struct QueryCaches<'tcx> {
$($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
}
@@ -282,7 +357,31 @@ macro_rules! define_callbacks {
match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
Some(_) => return,
- None => self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure),
+ None => self.tcx.queries.$name(
+ self.tcx,
+ DUMMY_SP,
+ key,
+ QueryMode::Ensure { check_cache: false },
+ ),
+ };
+ })*
+ }
+
+ impl<'tcx> TyCtxtEnsureWithValue<'tcx> {
+ $($(#[$attr])*
+ #[inline(always)]
+ pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
+ let key = key.into_query_param();
+ opt_remap_env_constness!([$($modifiers)*][key]);
+
+ match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
+ Some(_) => return,
+ None => self.tcx.queries.$name(
+ self.tcx,
+ DUMMY_SP,
+ key,
+ QueryMode::Ensure { check_cache: true },
+ ),
};
})*
}
@@ -305,17 +404,17 @@ macro_rules! define_callbacks {
let key = key.into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
- match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
+ restore::<$V>(match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
Some(value) => value,
None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(),
- }
+ })
})*
}
pub struct Providers {
$(pub $name: for<'tcx> fn(
TyCtxt<'tcx>,
- query_keys::$name<'tcx>,
+ query_keys_local::$name<'tcx>,
) -> query_provided::$name<'tcx>,)*
}
@@ -325,17 +424,14 @@ macro_rules! define_callbacks {
impl Default for Providers {
fn default() -> Self {
- use crate::query::Key;
-
Providers {
$($name: |_, key| bug!(
- "`tcx.{}({:?})` is not supported for {} crate;\n\
+ "`tcx.{}({:?})` is not supported for this key;\n\
hint: Queries can be either made to the local crate, or the external crate. \
This error means you tried to use it for one that's not supported.\n\
If that's not the case, {} was likely never assigned to a provider function.\n",
stringify!($name),
key,
- if key.query_crate_is_local() { "local" } else { "external" },
stringify!($name),
),)*
}
@@ -372,7 +468,7 @@ macro_rules! define_callbacks {
span: Span,
key: query_keys::$name<'tcx>,
mode: QueryMode,
- ) -> Option<$V>;)*
+ ) -> Option<Erase<$V>>;)*
}
};
}
@@ -399,11 +495,13 @@ macro_rules! define_feedable {
opt_remap_env_constness!([$($modifiers)*][key]);
let tcx = self.tcx;
- let value = query_provided_to_value::$name(tcx, value);
+ let erased = query_provided_to_value::$name(tcx, value);
+ let value = restore::<$V>(erased);
let cache = &tcx.query_system.caches.$name;
match try_get_cached(tcx, cache, &key) {
Some(old) => {
+ let old = restore::<$V>(old);
bug!(
"Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
stringify!($name),
@@ -418,7 +516,7 @@ macro_rules! define_feedable {
&value,
hash_result!([$($modifiers)*]),
);
- cache.complete(key, value, dep_node_index);
+ cache.complete(key, erased, dep_node_index);
value
}
}
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 3fc5f5bed..46c931d61 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -22,8 +22,6 @@ pub enum Cause {
pub trait TypeRelation<'tcx>: Sized {
fn tcx(&self) -> TyCtxt<'tcx>;
- fn intercrate(&self) -> bool;
-
fn param_env(&self) -> ty::ParamEnv<'tcx>;
/// Returns a static string we can use for printouts.
@@ -33,9 +31,6 @@ pub trait TypeRelation<'tcx>: Sized {
/// relation. Just affects error messages.
fn a_is_expected(&self) -> bool;
- /// Used during coherence. If called, must emit an always-ambiguous obligation.
- fn mark_ambiguous(&mut self);
-
fn with_cause<F, R>(&mut self, _cause: Cause, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
@@ -559,23 +554,16 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }),
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }),
) if a_def_id == b_def_id => {
- if relation.intercrate() {
- // During coherence, opaque types should be treated as equal to each other, even if their generic params
- // differ, as they could resolve to the same hidden type, even for different generic params.
- relation.mark_ambiguous();
- Ok(a)
- } else {
- let opt_variances = tcx.variances_of(a_def_id);
- let substs = relate_substs_with_variances(
- relation,
- a_def_id,
- opt_variances,
- a_substs,
- b_substs,
- false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
- )?;
- Ok(tcx.mk_opaque(a_def_id, substs))
- }
+ let opt_variances = tcx.variances_of(a_def_id);
+ let substs = relate_substs_with_variances(
+ relation,
+ a_def_id,
+ opt_variances,
+ a_substs,
+ b_substs,
+ false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
+ )?;
+ Ok(tcx.mk_opaque(a_def_id, substs))
}
_ => Err(TypeError::Sorts(expected_found(relation, a, b))),
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index ef643531b..5c604bb6d 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -4,7 +4,7 @@
//! to help with the tedium.
use crate::mir::interpret;
-use crate::mir::{Field, ProjectionKind};
+use crate::mir::ProjectionKind;
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
@@ -68,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
impl fmt::Debug for ty::BoundRegionKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
- ty::BrAnon(n, span) => write!(f, "BrAnon({n:?}, {span:?})"),
+ ty::BrAnon(span) => write!(f, "BrAnon({span:?})"),
ty::BrNamed(did, name) => {
if did.is_crate_root() {
write!(f, "BrNamed({})", name)
@@ -177,7 +177,9 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
write!(f, "TypeWellFormedFromEnv({:?})", ty)
}
ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"),
- ty::PredicateKind::AliasEq(t1, t2) => write!(f, "AliasEq({t1:?}, {t2:?})"),
+ ty::PredicateKind::AliasRelate(t1, t2, dir) => {
+ write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})")
+ }
}
}
}
@@ -215,6 +217,7 @@ CloneLiftImpls! {
// implementation and traversal implementations (the latter only for
// TyCtxt<'_> interners).
TrivialTypeTraversalAndLiftImpls! {
+ ::rustc_target::abi::FieldIdx,
::rustc_target::abi::VariantIdx,
crate::middle::region::Scope,
crate::ty::FloatTy,
@@ -250,8 +253,9 @@ TrivialTypeTraversalAndLiftImpls! {
crate::ty::AssocItem,
crate::ty::AssocKind,
crate::ty::AliasKind,
- crate::ty::Placeholder<crate::ty::BoundRegionKind>,
- crate::ty::Placeholder<crate::ty::BoundTyKind>,
+ crate::ty::AliasRelationDirection,
+ crate::ty::Placeholder<crate::ty::BoundRegion>,
+ crate::ty::Placeholder<crate::ty::BoundTy>,
crate::ty::ClosureKind,
crate::ty::FreeRegion,
crate::ty::InferTy,
@@ -265,7 +269,6 @@ TrivialTypeTraversalAndLiftImpls! {
::rustc_span::Span,
::rustc_span::symbol::Ident,
::rustc_errors::ErrorGuaranteed,
- Field,
interpret::Scalar,
rustc_target::abi::Size,
ty::BoundVar,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index e6a73e8bb..96c1577d5 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -7,14 +7,15 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
use crate::ty::visit::ValidateBoundVars;
use crate::ty::InferTy::*;
use crate::ty::{
- self, AdtDef, DefIdTree, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable,
- TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+ self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
+ TypeVisitableExt, TypeVisitor,
};
use crate::ty::{List, ParamEnv};
use hir::def::DefKind;
use polonius_engine::Atom;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::intern::Interned;
+use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::LangItem;
@@ -22,8 +23,8 @@ use rustc_index::vec::Idx;
use rustc_macros::HashStable;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
-use rustc_target::abi::VariantIdx;
-use rustc_target::spec::abi;
+use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
+use rustc_target::spec::abi::{self, Abi};
use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt;
@@ -60,7 +61,7 @@ pub struct FreeRegion {
#[derive(HashStable)]
pub enum BoundRegionKind {
/// An anonymous region parameter for a given fn (&T)
- BrAnon(u32, Option<Span>),
+ BrAnon(Option<Span>),
/// Named region parameters for functions (a in &'a T)
///
@@ -107,15 +108,6 @@ impl BoundRegionKind {
_ => None,
}
}
-
- pub fn expect_anon(&self) -> u32 {
- match *self {
- BoundRegionKind::BrNamed(_, _) | BoundRegionKind::BrEnv => {
- bug!("expected anon region: {self:?}")
- }
- BoundRegionKind::BrAnon(idx, _) => idx,
- }
- }
}
pub trait Article {
@@ -136,10 +128,6 @@ impl<'tcx> Article for TyKind<'tcx> {
}
}
-// `TyKind` 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!(TyKind<'_>, 32);
-
/// A closure can be modeled as a struct that looks like:
/// ```ignore (illustrative)
/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
@@ -517,8 +505,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
#[inline]
pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
// FIXME requires optimized MIR
- let num_variants = tcx.generator_layout(def_id).unwrap().variant_fields.len();
- VariantIdx::new(0)..VariantIdx::new(num_variants)
+ FIRST_VARIANT..tcx.generator_layout(def_id).unwrap().variant_fields.next_index()
}
/// The discriminant for the given variant. Panics if the `variant_index` is
@@ -878,8 +865,8 @@ impl<'tcx> PolyTraitRef<'tcx> {
}
}
-impl rustc_errors::IntoDiagnosticArg for PolyTraitRef<'_> {
- fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
self.to_string().into_diagnostic_arg()
}
}
@@ -924,6 +911,12 @@ impl<'tcx> ExistentialTraitRef<'tcx> {
}
}
+impl<'tcx> IntoDiagnosticArg for ExistentialTraitRef<'tcx> {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
pub type PolyExistentialTraitRef<'tcx> = Binder<'tcx, ExistentialTraitRef<'tcx>>;
impl<'tcx> PolyExistentialTraitRef<'tcx> {
@@ -940,12 +933,6 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
}
}
-impl rustc_errors::IntoDiagnosticArg for PolyExistentialTraitRef<'_> {
- fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
- self.to_string().into_diagnostic_arg()
- }
-}
-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum BoundVariableKind {
@@ -1160,78 +1147,12 @@ impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
}
}
-struct SkipBindersAt<'tcx> {
- tcx: TyCtxt<'tcx>,
- index: ty::DebruijnIndex,
-}
-
-impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for SkipBindersAt<'tcx> {
- type Error = ();
-
- fn interner(&self) -> TyCtxt<'tcx> {
- self.tcx
- }
-
- fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
- where
- T: ty::TypeFoldable<TyCtxt<'tcx>>,
- {
- self.index.shift_in(1);
- let value = t.try_map_bound(|t| t.try_fold_with(self));
- self.index.shift_out(1);
- value
- }
-
- fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
- if !ty.has_escaping_bound_vars() {
- Ok(ty)
- } else if let ty::Bound(index, bv) = *ty.kind() {
- if index == self.index {
- Err(())
- } else {
- Ok(self.interner().mk_bound(index.shifted_out(1), bv))
- }
- } else {
- ty.try_super_fold_with(self)
- }
- }
-
- fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
- if !r.has_escaping_bound_vars() {
- Ok(r)
- } else if let ty::ReLateBound(index, bv) = r.kind() {
- if index == self.index {
- Err(())
- } else {
- Ok(self.interner().mk_re_late_bound(index.shifted_out(1), bv))
- }
- } else {
- r.try_super_fold_with(self)
- }
- }
-
- fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
- if !ct.has_escaping_bound_vars() {
- Ok(ct)
- } else if let ty::ConstKind::Bound(index, bv) = ct.kind() {
- if index == self.index {
- Err(())
- } else {
- Ok(self.interner().mk_const(
- ty::ConstKind::Bound(index.shifted_out(1), bv),
- ct.ty().try_fold_with(self)?,
- ))
- }
- } else {
- ct.try_super_fold_with(self)
- }
- }
-
- fn try_fold_predicate(
- &mut self,
- p: ty::Predicate<'tcx>,
- ) -> Result<ty::Predicate<'tcx>, Self::Error> {
- if !p.has_escaping_bound_vars() { Ok(p) } else { p.try_super_fold_with(self) }
+impl<'tcx, T> IntoDiagnosticArg for Binder<'tcx, T>
+where
+ T: IntoDiagnosticArg,
+{
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.0.into_diagnostic_arg()
}
}
@@ -1288,7 +1209,7 @@ impl<'tcx> AliasTy<'tcx> {
match tcx.def_kind(self.def_id) {
DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
DefKind::ImplTraitPlaceholder => {
- tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
+ tcx.parent(tcx.impl_trait_in_trait_parent_fn(self.def_id))
}
kind => bug!("expected a projection AliasTy; found {kind:?}"),
}
@@ -1376,6 +1297,12 @@ impl<'tcx> FnSig<'tcx> {
}
}
+impl<'tcx> IntoDiagnosticArg for FnSig<'tcx> {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>;
impl<'tcx> PolyFnSig<'tcx> {
@@ -1403,6 +1330,18 @@ impl<'tcx> PolyFnSig<'tcx> {
pub fn abi(&self) -> abi::Abi {
self.skip_binder().abi
}
+
+ pub fn is_fn_trait_compatible(&self) -> bool {
+ matches!(
+ self.skip_binder(),
+ ty::FnSig {
+ unsafety: rustc_hir::Unsafety::Normal,
+ abi: Abi::Rust,
+ c_variadic: false,
+ ..
+ }
+ )
+ }
}
pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>;
@@ -1522,22 +1461,13 @@ pub struct BoundTy {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum BoundTyKind {
- Anon(u32),
+ Anon,
Param(DefId, Symbol),
}
-impl BoundTyKind {
- pub fn expect_anon(self) -> u32 {
- match self {
- BoundTyKind::Anon(i) => i,
- _ => bug!(),
- }
- }
-}
-
impl From<BoundVar> for BoundTy {
fn from(var: BoundVar) -> Self {
- BoundTy { var, kind: BoundTyKind::Anon(var.as_u32()) }
+ BoundTy { var, kind: BoundTyKind::Anon }
}
}
@@ -1616,19 +1546,24 @@ impl<'tcx> Region<'tcx> {
pub fn get_name(self) -> Option<Symbol> {
if self.has_name() {
- let name = match *self {
+ match *self {
ty::ReEarlyBound(ebr) => Some(ebr.name),
ty::ReLateBound(_, br) => br.kind.get_name(),
ty::ReFree(fr) => fr.bound_region.get_name(),
ty::ReStatic => Some(kw::StaticLifetime),
- ty::RePlaceholder(placeholder) => placeholder.name.get_name(),
+ ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(),
_ => None,
- };
-
- return name;
+ }
+ } else {
+ None
}
+ }
- None
+ pub fn get_name_or_anon(self) -> Symbol {
+ match self.get_name() {
+ Some(name) => name,
+ None => sym::anon,
+ }
}
/// Is this region named by the user?
@@ -1639,7 +1574,7 @@ impl<'tcx> Region<'tcx> {
ty::ReFree(fr) => fr.bound_region.is_named(),
ty::ReStatic => true,
ty::ReVar(..) => false,
- ty::RePlaceholder(placeholder) => placeholder.name.is_named(),
+ ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(),
ty::ReErased => false,
ty::ReError(_) => false,
}
@@ -1762,10 +1697,10 @@ impl<'tcx> Region<'tcx> {
matches!(self.kind(), ty::ReVar(_))
}
- pub fn as_var(self) -> Option<RegionVid> {
+ pub fn as_var(self) -> RegionVid {
match self.kind() {
- ty::ReVar(vid) => Some(vid),
- _ => None,
+ ty::ReVar(vid) => vid,
+ _ => bug!("expected region {:?} to be of kind ReVar", self),
}
}
}
@@ -1892,7 +1827,7 @@ impl<'tcx> Ty<'tcx> {
Adt(def, substs) => {
assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type");
let variant = def.non_enum_variant();
- let f0_ty = variant.fields[0].ty(tcx, substs);
+ let f0_ty = variant.fields[FieldIdx::from_u32(0)].ty(tcx, substs);
match f0_ty.kind() {
// If the first field is an array, we assume it is the only field and its
@@ -1902,7 +1837,7 @@ impl<'tcx> Ty<'tcx> {
// 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_target_usize(tcx, ParamEnv::empty()) as u64, *f0_elem_ty)
+ (f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty)
}
// Otherwise, the fields of this Adt are the SIMD components (and we assume they
// all have the same type).
@@ -1914,11 +1849,6 @@ impl<'tcx> Ty<'tcx> {
}
#[inline]
- pub fn is_region_ptr(self) -> bool {
- matches!(self.kind(), Ref(..))
- }
-
- #[inline]
pub fn is_mutable_ptr(self) -> bool {
matches!(
self.kind(),
@@ -1944,7 +1874,7 @@ impl<'tcx> Ty<'tcx> {
/// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer).
#[inline]
pub fn is_any_ptr(self) -> bool {
- self.is_region_ptr() || self.is_unsafe_ptr() || self.is_fn_ptr()
+ self.is_ref() || self.is_unsafe_ptr() || self.is_fn_ptr()
}
#[inline]
@@ -2508,3 +2438,14 @@ impl<'tcx> VarianceDiagInfo<'tcx> {
}
}
}
+
+// Some types are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+ use super::*;
+ use rustc_data_structures::static_assert_size;
+ // tidy-alphabetical-start
+ static_assert_size!(RegionKind<'_>, 28);
+ static_assert_size!(TyKind<'_>, 32);
+ // tidy-alphabetical-end
+}
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index b090bd9d8..f05b87343 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -302,8 +302,8 @@ impl<'tcx> InternalSubsts<'tcx> {
}
/// Creates an `InternalSubsts` that maps each generic parameter to itself.
- pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
- Self::for_item(tcx, def_id, |param, _| tcx.mk_param_from_def(param))
+ pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> SubstsRef<'tcx> {
+ Self::for_item(tcx, def_id.into(), |param, _| tcx.mk_param_from_def(param))
}
/// Creates an `InternalSubsts` for generic parameter definitions,
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 233c0df2d..6747da7ab 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -1,5 +1,5 @@
use crate::traits::specialization_graph;
-use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
+use crate::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections};
use crate::ty::visit::TypeVisitableExt;
use crate::ty::{Ident, Ty, TyCtxt};
use hir::def_id::LOCAL_CRATE;
@@ -100,8 +100,9 @@ impl<'tcx> TraitDef {
}
impl<'tcx> TyCtxt<'tcx> {
- pub fn for_each_impl<F: FnMut(DefId)>(self, def_id: DefId, mut f: F) {
- let impls = self.trait_impls_of(def_id);
+ /// `trait_def_id` MUST BE the `DefId` of a trait.
+ pub fn for_each_impl<F: FnMut(DefId)>(self, trait_def_id: DefId, mut f: F) {
+ let impls = self.trait_impls_of(trait_def_id);
for &impl_def_id in impls.blanket_impls.iter() {
f(impl_def_id);
@@ -114,27 +115,45 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- /// Iterate over every impl that could possibly match the
- /// self type `self_ty`.
- pub fn for_each_relevant_impl<F: FnMut(DefId)>(
+ /// Iterate over every impl that could possibly match the self type `self_ty`.
+ ///
+ /// `trait_def_id` MUST BE the `DefId` of a trait.
+ pub fn for_each_relevant_impl(
self,
- def_id: DefId,
+ trait_def_id: DefId,
self_ty: Ty<'tcx>,
- mut f: F,
+ f: impl FnMut(DefId),
) {
- let _: Option<()> = self.find_map_relevant_impl(def_id, self_ty, |did| {
- f(did);
- None
- });
+ self.for_each_relevant_impl_treating_projections(
+ trait_def_id,
+ self_ty,
+ TreatProjections::ForLookup,
+ f,
+ )
}
+ pub fn for_each_relevant_impl_treating_projections(
+ self,
+ trait_def_id: DefId,
+ self_ty: Ty<'tcx>,
+ treat_projections: TreatProjections,
+ mut f: impl FnMut(DefId),
+ ) {
+ let _: Option<()> =
+ self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| {
+ f(did);
+ None
+ });
+ }
+
+ /// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn non_blanket_impls_for_ty(
self,
- def_id: DefId,
+ trait_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, TreatParams::AsInfer) {
+ let impls = self.trait_impls_of(trait_def_id);
+ if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
return impls.iter().copied();
}
@@ -145,18 +164,21 @@ impl<'tcx> TyCtxt<'tcx> {
/// 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>>(
+ ///
+ /// `trait_def_id` MUST BE the `DefId` of a trait.
+ pub fn find_map_relevant_impl<T>(
self,
- def_id: DefId,
+ trait_def_id: DefId,
self_ty: Ty<'tcx>,
- mut f: F,
+ treat_projections: TreatProjections,
+ mut f: impl FnMut(DefId) -> Option<T>,
) -> Option<T> {
// FIXME: This depends on the set of all impls for the trait. That is
// unfortunate wrt. incremental compilation.
//
// If we want to be faster, we could have separate queries for
// blanket and non-blanket impls, and compare them separately.
- let impls = self.trait_impls_of(def_id);
+ let impls = self.trait_impls_of(trait_def_id);
for &impl_def_id in impls.blanket_impls.iter() {
if let result @ Some(_) = f(impl_def_id) {
@@ -164,14 +186,17 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- // Note that we're using `TreatParams::AsPlaceholder` to query `non_blanket_impls` while using
- // `TreatParams::AsInfer` while actually adding them.
- //
+ // Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using
+ // `TreatParams::AsCandidateKey` while actually adding them.
+ let treat_params = match treat_projections {
+ TreatProjections::NextSolverLookup => TreatParams::NextSolverLookup,
+ TreatProjections::ForLookup => TreatParams::ForLookup,
+ };
// This way, when searching for some impl for `T: Trait`, we do not look at any impls
// 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, TreatParams::AsPlaceholder) {
+ if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls {
if let result @ Some(_) = f(impl_def_id) {
@@ -190,9 +215,11 @@ impl<'tcx> TyCtxt<'tcx> {
None
}
- /// Returns an iterator containing all impls
- 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);
+ /// Returns an iterator containing all impls for `trait_def_id`.
+ ///
+ /// `trait_def_id` MUST BE the `DefId` of a trait.
+ pub fn all_impls(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
+ let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(trait_def_id);
blanket_impls.iter().chain(non_blanket_impls.iter().flat_map(|(_, v)| v)).cloned()
}
@@ -231,7 +258,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
}
if let Some(simplified_self_ty) =
- fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsInfer)
+ fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsCandidateKey)
{
impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
} else {
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 586958247..47943b94c 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -8,10 +8,9 @@ use crate::{
},
};
use rustc_data_structures::{
- fx::FxHashMap,
+ fx::{FxHashMap, FxIndexMap},
sync::Lrc,
unord::{UnordItems, UnordSet},
- vec_map::VecMap,
};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
@@ -26,6 +25,7 @@ use rustc_macros::HashStable;
use rustc_middle::mir::FakeReadCause;
use rustc_session::Session;
use rustc_span::Span;
+use rustc_target::abi::FieldIdx;
use std::{collections::hash_map::Entry, hash::Hash, iter};
use super::RvalueScopes;
@@ -43,7 +43,7 @@ pub struct TypeckResults<'tcx> {
/// or patterns (`S { field }`). The index is often useful by itself, but to learn more
/// about the field you also need definition of the variant to which the field
/// belongs, but it may not exist if it's a tuple field (`tuple.0`).
- field_indices: ItemLocalMap<usize>,
+ field_indices: ItemLocalMap<FieldIdx>,
/// Stores the types for various nodes in the AST. Note that this table
/// is not guaranteed to be populated outside inference. See
@@ -155,7 +155,7 @@ pub struct TypeckResults<'tcx> {
/// by this function. We also store the
/// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
/// even if they are only set in dead code (which doesn't show up in MIR).
- pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
+ pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
/// Tracks the minimum captures required for a closure;
/// see `MinCaptureInformationMap` for more details.
@@ -314,19 +314,19 @@ impl<'tcx> TypeckResults<'tcx> {
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
}
- pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
+ pub fn field_indices(&self) -> LocalTableInContext<'_, FieldIdx> {
LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
}
- pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
+ pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, FieldIdx> {
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
}
- pub fn field_index(&self, id: hir::HirId) -> usize {
+ pub fn field_index(&self, id: hir::HirId) -> FieldIdx {
self.field_indices().get(id).cloned().expect("no index for a field")
}
- pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
+ pub fn opt_field_index(&self, id: hir::HirId) -> Option<FieldIdx> {
self.field_indices().get(id).cloned()
}
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 90270e0ee..c8a78ec03 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -2,10 +2,11 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir;
+use crate::ty::fast_reject::TreatProjections;
use crate::ty::layout::IntegerExt;
use crate::ty::{
- self, DefIdTree, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder,
- TypeSuperFoldable, TypeVisitableExt,
+ self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
+ TypeVisitableExt,
};
use crate::ty::{GenericArgKind, SubstsRef};
use rustc_apfloat::Float as _;
@@ -14,11 +15,12 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_index::bit_set::GrowableBitSet;
use rustc_index::vec::{Idx, IndexVec};
use rustc_macros::HashStable;
-use rustc_span::{sym, DUMMY_SP};
+use rustc_session::Limit;
+use rustc_span::sym;
use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout};
use rustc_target::spec::abi::Abi;
use smallvec::SmallVec;
@@ -59,22 +61,13 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
}
}
-fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
- let (int, signed) = match *ty.kind() {
- ty::Int(ity) => (Integer::from_int_ty(&tcx, ity), true),
- ty::Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false),
- _ => bug!("non integer discriminant"),
- };
- (int.size(), signed)
-}
-
impl<'tcx> Discr<'tcx> {
/// Adds `1` to the value and wraps around if the maximum for the type is reached.
pub fn wrap_incr(self, tcx: TyCtxt<'tcx>) -> Self {
self.checked_add(tcx, 1).0
}
pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) {
- let (size, signed) = int_size_and_signed(tcx, self.ty);
+ let (size, signed) = self.ty.int_size_and_signed(tcx);
let (val, oflo) = if signed {
let min = size.signed_int_min();
let max = size.signed_int_max();
@@ -233,17 +226,20 @@ impl<'tcx> TyCtxt<'tcx> {
let recursion_limit = self.recursion_limit();
for iteration in 0.. {
if !recursion_limit.value_within_limit(iteration) {
- return self.ty_error_with_message(
- DUMMY_SP,
- &format!("reached the recursion limit finding the struct tail for {}", ty),
- );
+ let suggested_limit = match recursion_limit {
+ Limit(0) => Limit(2),
+ limit => limit * 2,
+ };
+ let reported =
+ self.sess.emit_err(crate::error::RecursionLimitReached { ty, suggested_limit });
+ return self.ty_error(reported);
}
match *ty.kind() {
ty::Adt(def, substs) => {
if !def.is_struct() {
break;
}
- match def.non_enum_variant().fields.last() {
+ match def.non_enum_variant().fields.raw.last() {
Some(field) => {
f();
ty = field.ty(self, substs);
@@ -317,7 +313,7 @@ impl<'tcx> TyCtxt<'tcx> {
(&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
if a_def == b_def && a_def.is_struct() =>
{
- if let Some(f) = a_def.non_enum_variant().fields.last() {
+ if let Some(f) = a_def.non_enum_variant().fields.raw.last() {
a = f.ty(self, a_substs);
b = f.ty(self, b_substs);
} else {
@@ -363,14 +359,20 @@ impl<'tcx> TyCtxt<'tcx> {
self.ensure().coherent_trait(drop_trait);
let ty = self.type_of(adt_did).subst_identity();
- let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
- if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
- if validate(self, impl_did).is_ok() {
- return Some((*item_id, self.constness(impl_did)));
+ let (did, constness) = self.find_map_relevant_impl(
+ drop_trait,
+ ty,
+ // FIXME: This could also be some other mode, like "unexpected"
+ TreatProjections::ForLookup,
+ |impl_did| {
+ if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
+ if validate(self, impl_did).is_ok() {
+ return Some((*item_id, self.constness(impl_did)));
+ }
}
- }
- None
- })?;
+ None
+ },
+ )?;
Some(ty::Destructor { did, constness })
}
@@ -599,6 +601,28 @@ impl<'tcx> TyCtxt<'tcx> {
self.static_mutability(def_id) == Some(hir::Mutability::Mut)
}
+ /// Returns `true` if the item pointed to by `def_id` is a thread local which needs a
+ /// thread local shim generated.
+ #[inline]
+ pub fn needs_thread_local_shim(self, def_id: DefId) -> bool {
+ !self.sess.target.dll_tls_export
+ && self.is_thread_local_static(def_id)
+ && !self.is_foreign_item(def_id)
+ }
+
+ /// Returns the type a reference to the thread local takes in MIR.
+ pub fn thread_local_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
+ let static_ty = self.type_of(def_id).subst_identity();
+ if self.is_mutable_static(def_id) {
+ self.mk_mut_ptr(static_ty)
+ } else if self.is_foreign_item(def_id) {
+ self.mk_imm_ptr(static_ty)
+ } else {
+ // FIXME: These things don't *really* have 'static lifetime.
+ self.mk_imm_ref(self.lifetimes.re_static, static_ty)
+ }
+ }
+
/// Get the type of the pointer to the static that we use in MIR.
pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
// Make sure that any constants in the static's type are evaluated.
@@ -684,10 +708,6 @@ impl<'tcx> TyCtxt<'tcx> {
ty::EarlyBinder(self.explicit_item_bounds(def_id))
}
- pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> {
- ty::EarlyBinder(self.impl_subject(def_id))
- }
-
/// Returns names of captured upvars for closures and generators.
///
/// Here are some examples:
@@ -922,12 +942,21 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
}
impl<'tcx> Ty<'tcx> {
+ pub fn int_size_and_signed(self, tcx: TyCtxt<'tcx>) -> (Size, bool) {
+ let (int, signed) = match *self.kind() {
+ ty::Int(ity) => (Integer::from_int_ty(&tcx, ity), true),
+ ty::Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false),
+ _ => bug!("non integer discriminant"),
+ };
+ (int.size(), signed)
+ }
+
/// 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(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> {
let val = match self.kind() {
ty::Int(_) | ty::Uint(_) => {
- let (size, signed) = int_size_and_signed(tcx, self);
+ let (size, signed) = self.int_size_and_signed(tcx);
let val =
if signed { size.signed_int_max() as u128 } else { size.unsigned_int_max() };
Some(val)
@@ -948,7 +977,7 @@ impl<'tcx> Ty<'tcx> {
pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> {
let val = match self.kind() {
ty::Int(_) | ty::Uint(_) => {
- let (size, signed) = int_size_and_signed(tcx, self);
+ let (size, signed) = self.int_size_and_signed(tcx);
let val = if signed { size.truncate(size.signed_int_min() as u128) } else { 0 };
Some(val)
}
@@ -1432,8 +1461,7 @@ pub fn reveal_opaque_types_in_bounds<'tcx>(
}
/// Determines whether an item is annotated with `doc(hidden)`.
-fn is_doc_hidden(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
- assert!(def_id.is_local());
+fn is_doc_hidden(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
tcx.get_attrs(def_id, sym::doc)
.filter_map(|attr| attr.meta_item_list())
.any(|items| items.iter().any(|item| item.has_name(sym::hidden)))
@@ -1447,7 +1475,7 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
}
/// Determines whether an item is an intrinsic by Abi.
-pub fn is_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+pub fn is_intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
}
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 6814cadb9..08a62c900 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -83,6 +83,9 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
| TypeFlags::HAS_CT_PLACEHOLDER,
)
}
+ fn has_non_region_placeholders(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER)
+ }
fn needs_subst(&self) -> bool {
self.has_type_flags(TypeFlags::NEEDS_SUBST)
}
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index c4f526dbd..55aa4fcff 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -4,7 +4,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_middle::ty::Representability;
-use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_query_system::query::QueryInfo;
use rustc_query_system::Value;
use rustc_span::def_id::LocalDefId;