summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src')
-rw-r--r--compiler/rustc_middle/src/arena.rs21
-rw-r--r--compiler/rustc_middle/src/dep_graph/mod.rs4
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs253
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs11
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs227
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs9
-rw-r--r--compiler/rustc_middle/src/lib.rs13
-rw-r--r--compiler/rustc_middle/src/lint.rs42
-rw-r--r--compiler/rustc_middle/src/macros.rs10
-rw-r--r--compiler/rustc_middle/src/middle/lang_items.rs11
-rw-r--r--compiler/rustc_middle/src/middle/limits.rs1
-rw-r--r--compiler/rustc_middle/src/middle/mod.rs25
-rw-r--r--compiler/rustc_middle/src/middle/region.rs10
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs7
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs122
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs12
-rw-r--r--compiler/rustc_middle/src/mir/generic_graph.rs2
-rw-r--r--compiler/rustc_middle/src/mir/graphviz.rs3
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs18
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs21
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs10
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs99
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs4
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs10
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs28
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs3
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs15
-rw-r--r--compiler/rustc_middle/src/mir/query.rs82
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs16
-rw-r--r--compiler/rustc_middle/src/mir/statement.rs4
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs8
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs12
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs15
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs2
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs4
-rw-r--r--compiler/rustc_middle/src/query/erase.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs34
-rw-r--r--compiler/rustc_middle/src/query/on_disk_cache.rs14
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs26
-rw-r--r--compiler/rustc_middle/src/thir.rs21
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs6
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs135
-rw-r--r--compiler/rustc_middle/src/traits/query.rs11
-rw-r--r--compiler/rustc_middle/src/traits/select.rs36
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs21
-rw-r--r--compiler/rustc_middle/src/traits/solve/cache.rs2
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect.rs11
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect/format.rs13
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs2
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs9
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs6
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs82
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs19
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs68
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs4
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs26
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs248
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs13
-rw-r--r--compiler/rustc_middle/src/ty/error.rs27
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs10
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs28
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs44
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs25
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs16
-rw-r--r--compiler/rustc_middle/src/ty/impls_ty.rs10
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs40
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs2
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs28
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs212
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs8
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs7
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs210
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs14
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs44
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs197
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs9
-rw-r--r--compiler/rustc_middle/src/ty/util.rs135
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs45
-rw-r--r--compiler/rustc_middle/src/util/bug.rs16
-rw-r--r--compiler/rustc_middle/src/values.rs10
85 files changed, 1531 insertions, 1562 deletions
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index dd761b4e3..52fd494a1 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -27,19 +27,12 @@ macro_rules! arena_types {
rustc_middle::mir::Promoted,
rustc_middle::mir::Body<'tcx>
>,
- [decode] closure_debuginfo:
- rustc_index::IndexVec<
- rustc_target::abi::FieldIdx,
- rustc_span::symbol::Symbol,
- >,
[decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>,
- [decode] borrowck_result:
- rustc_middle::mir::BorrowCheckResult<'tcx>,
+ [decode] borrowck_result: rustc_middle::mir::BorrowCheckResult<'tcx>,
[] resolver: rustc_data_structures::steal::Steal<(
rustc_middle::ty::ResolverAstLowering,
rustc_data_structures::sync::Lrc<rustc_ast::Crate>,
)>,
- [] output_filenames: std::sync::Arc<rustc_session::config::OutputFilenames>,
[] 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,
@@ -91,29 +84,19 @@ macro_rules! arena_types {
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>>
>,
- [] all_traits: Vec<rustc_hir::def_id::DefId>,
[] effective_visibilities: rustc_middle::middle::privacy::EffectiveVisibilities,
- [] foreign_module: rustc_session::cstore::ForeignModule,
- [] foreign_modules: Vec<rustc_session::cstore::ForeignModule>,
[] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
[] 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::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
- [] tys: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::TyKind<'tcx>>,
- [] predicates: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::PredicateKind<'tcx>>,
- [] consts: rustc_middle::ty::ConstData<'tcx>,
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
// since we need to allocate this type on both the `rustc_hir` arena
// (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, ()>,
@@ -124,11 +107,9 @@ macro_rules! arena_types {
rustc_hir::def_id::DefId,
rustc_middle::ty::EarlyBinder<rustc_middle::ty::Ty<'tcx>>
>,
- [] bit_set_u32: rustc_index::bit_set::BitSet<u32>,
[] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
[] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>,
[decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
- [] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>),
[] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem,
[] mod_child: rustc_middle::metadata::ModChild,
[] features: rustc_feature::Features,
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index 76ef62f9f..dc0da165a 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -8,8 +8,8 @@ mod dep_node;
pub use rustc_query_system::dep_graph::debug::EdgeFilter;
pub use rustc_query_system::dep_graph::{
- debug::DepNodeFilter, hash_result, DepContext, DepGraphQuery, DepNodeColor, DepNodeIndex, Deps,
- SerializedDepGraph, SerializedDepNodeIndex, TaskDeps, TaskDepsRef, WorkProduct, WorkProductId,
+ debug::DepNodeFilter, hash_result, DepContext, DepGraphQuery, DepNodeIndex, Deps,
+ SerializedDepGraph, SerializedDepNodeIndex, TaskDepsRef, WorkProduct, WorkProductId,
WorkProductMap,
};
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 58c0c6bab..81f34c7b8 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -9,8 +9,8 @@ use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{par_for_each_in, try_par_for_each_in, DynSend, DynSync};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
-use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
+use rustc_hir::intravisit::Visitor;
use rustc_hir::*;
use rustc_index::Idx;
use rustc_middle::hir::nested_filter;
@@ -57,6 +57,10 @@ fn is_body_owner(node: Node<'_>, hir_id: HirId) -> bool {
}
}
+// FIXME: the structure was necessary in the past but now it
+// only serves as "namespace" for HIR-related methods, and can be
+// removed if all the methods are reasonably renamed and moved to tcx
+// (https://github.com/rust-lang/rust/pull/118256#issuecomment-1826442834).
#[derive(Copy, Clone)]
pub struct Map<'hir> {
pub(super) tcx: TyCtxt<'hir>,
@@ -116,7 +120,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> {
let parent_id = parent_id.map_or(CRATE_OWNER_ID, |local_def_index| {
let def_id = LocalDefId { local_def_index };
- self.map.local_def_id_to_hir_id(def_id).owner
+ self.map.tcx.local_def_id_to_hir_id(def_id).owner
});
self.current_id = HirId::make_owner(parent_id.def_id);
@@ -128,6 +132,40 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> {
}
}
+impl<'tcx> TyCtxt<'tcx> {
+ /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found.
+ pub fn opt_hir_node(self, id: HirId) -> Option<Node<'tcx>> {
+ if id.local_id == ItemLocalId::from_u32(0) {
+ let owner = self.hir_owner(id.owner)?;
+ Some(owner.node.into())
+ } else {
+ let owner = self.hir_owner_nodes(id.owner).as_owner()?;
+ let node = owner.nodes[id.local_id].as_ref()?;
+ Some(node.node)
+ }
+ }
+
+ /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found.
+ #[inline]
+ pub fn opt_hir_node_by_def_id(self, id: LocalDefId) -> Option<Node<'tcx>> {
+ self.opt_hir_node(self.opt_local_def_id_to_hir_id(id)?)
+ }
+
+ /// Retrieves the `hir::Node` corresponding to `id`, panicking if it cannot be found.
+ #[track_caller]
+ pub fn hir_node(self, id: HirId) -> Node<'tcx> {
+ self.opt_hir_node(id).unwrap_or_else(|| bug!("couldn't find HIR node for hir id {id:?}"))
+ }
+
+ /// Retrieves the `hir::Node` corresponding to `id`, panicking if it cannot be found.
+ #[inline]
+ #[track_caller]
+ pub fn hir_node_by_def_id(self, id: LocalDefId) -> Node<'tcx> {
+ self.opt_hir_node_by_def_id(id)
+ .unwrap_or_else(|| bug!("couldn't find HIR node for def id {id:?}"))
+ }
+}
+
impl<'hir> Map<'hir> {
#[inline]
pub fn krate(self) -> &'hir Crate<'hir> {
@@ -168,108 +206,6 @@ impl<'hir> Map<'hir> {
self.tcx.definitions_untracked().def_path_hash(def_id)
}
- #[inline]
- pub fn local_def_id_to_hir_id(self, def_id: impl Into<LocalDefId>) -> HirId {
- self.tcx.local_def_id_to_hir_id(def_id.into())
- }
-
- /// 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 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,
- ItemKind::Fn(..) => DefKind::Fn,
- ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind),
- ItemKind::Mod(..) => DefKind::Mod,
- ItemKind::OpaqueTy(..) => DefKind::OpaqueTy,
- ItemKind::TyAlias(..) => DefKind::TyAlias,
- ItemKind::Enum(..) => DefKind::Enum,
- ItemKind::Struct(..) => DefKind::Struct,
- ItemKind::Union(..) => DefKind::Union,
- ItemKind::Trait(..) => DefKind::Trait,
- ItemKind::TraitAlias(..) => DefKind::TraitAlias,
- ItemKind::ExternCrate(_) => DefKind::ExternCrate,
- ItemKind::Use(..) => DefKind::Use,
- ItemKind::ForeignMod { .. } => DefKind::ForeignMod,
- ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
- ItemKind::Impl(impl_) => DefKind::Impl { of_trait: impl_.of_trait.is_some() },
- },
- Node::ForeignItem(item) => match item.kind {
- ForeignItemKind::Fn(..) => DefKind::Fn,
- ForeignItemKind::Static(_, mt) => DefKind::Static(mt),
- ForeignItemKind::Type => DefKind::ForeignTy,
- },
- Node::TraitItem(item) => match item.kind {
- TraitItemKind::Const(..) => DefKind::AssocConst,
- TraitItemKind::Fn(..) => DefKind::AssocFn,
- TraitItemKind::Type(..) => DefKind::AssocTy,
- },
- Node::ImplItem(item) => match item.kind {
- ImplItemKind::Const(..) => DefKind::AssocConst,
- ImplItemKind::Fn(..) => DefKind::AssocFn,
- ImplItemKind::Type(..) => DefKind::AssocTy,
- },
- Node::Variant(_) => DefKind::Variant,
- Node::Ctor(variant_data) => {
- let ctor_of = match self.find_parent(hir_id) {
- Some(Node::Item(..)) => def::CtorOf::Struct,
- Some(Node::Variant(..)) => def::CtorOf::Variant,
- _ => unreachable!(),
- };
- match variant_data.ctor_kind() {
- Some(kind) => DefKind::Ctor(ctor_of, kind),
- None => bug!("constructor node without a constructor"),
- }
- }
- Node::AnonConst(_) => DefKind::AnonConst,
- Node::ConstBlock(_) => DefKind::InlineConst,
- Node::Field(_) => DefKind::Field,
- Node::Expr(expr) => match expr.kind {
- ExprKind::Closure(Closure { movability: None, .. }) => DefKind::Closure,
- ExprKind::Closure(Closure { movability: Some(_), .. }) => DefKind::Coroutine,
- _ => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)),
- },
- Node::GenericParam(param) => match param.kind {
- GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
- GenericParamKind::Type { .. } => DefKind::TyParam,
- GenericParamKind::Const { .. } => DefKind::ConstParam,
- },
- Node::Crate(_) => DefKind::Mod,
- Node::Stmt(_)
- | Node::PathSegment(_)
- | Node::Ty(_)
- | Node::TypeBinding(_)
- | Node::Infer(_)
- | Node::TraitRef(_)
- | Node::Pat(_)
- | Node::PatField(_)
- | Node::ExprField(_)
- | Node::Local(_)
- | Node::Param(_)
- | Node::Arm(_)
- | Node::Lifetime(_)
- | Node::Block(_) => span_bug!(
- self.span(hir_id),
- "unexpected node with def id {local_def_id:?}: {node:?}"
- ),
- };
- Some(def_kind)
- }
-
/// Finds the id of the parent node to this one.
///
/// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
@@ -293,46 +229,15 @@ impl<'hir> Map<'hir> {
}
pub fn get_parent(self, hir_id: HirId) -> Node<'hir> {
- self.get(self.parent_id(hir_id))
+ self.tcx.hir_node(self.parent_id(hir_id))
}
pub fn find_parent(self, hir_id: HirId) -> Option<Node<'hir>> {
- self.find(self.opt_parent_id(hir_id)?)
- }
-
- /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
- pub fn find(self, id: HirId) -> Option<Node<'hir>> {
- if id.local_id == ItemLocalId::from_u32(0) {
- let owner = self.tcx.hir_owner(id.owner)?;
- Some(owner.node.into())
- } else {
- let owner = self.tcx.hir_owner_nodes(id.owner).as_owner()?;
- let node = owner.nodes[id.local_id].as_ref()?;
- Some(node.node)
- }
- }
-
- /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
- #[inline]
- pub fn find_by_def_id(self, id: LocalDefId) -> Option<Node<'hir>> {
- self.find(self.tcx.opt_local_def_id_to_hir_id(id)?)
- }
-
- /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
- #[track_caller]
- pub fn get(self, id: HirId) -> Node<'hir> {
- self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id))
- }
-
- /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
- #[inline]
- #[track_caller]
- pub fn get_by_def_id(self, id: LocalDefId) -> Node<'hir> {
- self.find_by_def_id(id).unwrap_or_else(|| bug!("couldn't find {:?} in the HIR map", id))
+ self.tcx.opt_hir_node(self.opt_parent_id(hir_id)?)
}
pub fn get_if_local(self, id: DefId) -> Option<Node<'hir>> {
- id.as_local().and_then(|id| self.find(self.tcx.opt_local_def_id_to_hir_id(id)?))
+ id.as_local().and_then(|id| self.tcx.opt_hir_node(self.tcx.opt_local_def_id_to_hir_id(id)?))
}
pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> {
@@ -366,7 +271,7 @@ impl<'hir> Map<'hir> {
#[track_caller]
pub fn fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
- if let Some(node) = self.find(hir_id) {
+ if let Some(node) = self.tcx.opt_hir_node(hir_id) {
node.fn_decl()
} else {
bug!("no node for hir_id `{}`", hir_id)
@@ -375,7 +280,7 @@ impl<'hir> Map<'hir> {
#[track_caller]
pub fn fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> {
- if let Some(node) = self.find(hir_id) {
+ if let Some(node) = self.tcx.opt_hir_node(hir_id) {
node.fn_sig()
} else {
bug!("no node for hir_id `{}`", hir_id)
@@ -398,19 +303,22 @@ impl<'hir> Map<'hir> {
/// item (possibly associated), a closure, or a `hir::AnonConst`.
pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId {
let parent = self.parent_id(hir_id);
- assert!(self.find(parent).is_some_and(|n| is_body_owner(n, hir_id)), "{hir_id:?}");
+ assert!(
+ self.tcx.opt_hir_node(parent).is_some_and(|n| is_body_owner(n, hir_id)),
+ "{hir_id:?}"
+ );
parent
}
pub fn body_owner_def_id(self, BodyId { hir_id }: BodyId) -> LocalDefId {
let parent = self.parent_id(hir_id);
- associated_body(self.get(parent)).unwrap().0
+ associated_body(self.tcx.hir_node(parent)).unwrap().0
}
/// Given a `LocalDefId`, returns the `BodyId` associated with it,
/// if the node is a body owner, otherwise returns `None`.
pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<BodyId> {
- let node = self.find_by_def_id(id)?;
+ let node = self.tcx.opt_hir_node_by_def_id(id)?;
let (_, body_id) = associated_body(node)?;
Some(body_id)
}
@@ -419,7 +327,7 @@ impl<'hir> Map<'hir> {
#[track_caller]
pub fn body_owned_by(self, id: LocalDefId) -> BodyId {
self.maybe_body_owned_by(id).unwrap_or_else(|| {
- let hir_id = self.local_def_id_to_hir_id(id);
+ let hir_id = self.tcx.local_def_id_to_hir_id(id);
span_bug!(
self.span(hir_id),
"body_owned_by: {} has no associated body",
@@ -438,14 +346,15 @@ impl<'hir> Map<'hir> {
/// Returns the `BodyOwnerKind` of this `LocalDefId`.
///
/// Panics if `LocalDefId` does not have an associated body.
- pub fn body_owner_kind(self, def_id: LocalDefId) -> BodyOwnerKind {
+ pub fn body_owner_kind(self, def_id: impl Into<DefId>) -> BodyOwnerKind {
+ let def_id = def_id.into();
match self.tcx.def_kind(def_id) {
DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
BodyOwnerKind::Const { inline: false }
}
DefKind::InlineConst => BodyOwnerKind::Const { inline: true },
DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn,
- DefKind::Closure | DefKind::Coroutine => BodyOwnerKind::Closure,
+ DefKind::Closure => BodyOwnerKind::Closure,
DefKind::Static(mt) => BodyOwnerKind::Static(mt),
dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
}
@@ -458,20 +367,17 @@ impl<'hir> Map<'hir> {
/// This should only be used for determining the context of a body, a return
/// value of `Some` does not always suggest that the owner of the body is `const`,
/// just that it has to be checked as if it were.
- pub fn body_const_context(self, def_id: LocalDefId) -> Option<ConstContext> {
+ pub fn body_const_context(self, def_id: impl Into<DefId>) -> Option<ConstContext> {
+ let def_id = def_id.into();
let ccx = match self.body_owner_kind(def_id) {
BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
BodyOwnerKind::Static(mt) => ConstContext::Static(mt),
- BodyOwnerKind::Fn if self.tcx.is_constructor(def_id.to_def_id()) => return None,
- BodyOwnerKind::Fn | BodyOwnerKind::Closure
- if self.tcx.is_const_fn_raw(def_id.to_def_id()) =>
- {
- ConstContext::ConstFn
- }
- BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id.to_def_id()) => {
+ BodyOwnerKind::Fn if self.tcx.is_constructor(def_id) => return None,
+ BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn_raw(def_id) => {
ConstContext::ConstFn
}
+ BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id) => ConstContext::ConstFn,
BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
};
@@ -531,9 +437,7 @@ impl<'hir> Map<'hir> {
pub fn get_module(self, module: LocalModDefId) -> (&'hir Mod<'hir>, Span, HirId) {
let hir_id = HirId::make_owner(module.to_local_def_id());
match self.tcx.hir_owner(hir_id.owner).map(|o| o.node) {
- Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => {
- (m, span, hir_id)
- }
+ Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. })) => (m, span, hir_id),
Some(OwnerNode::Crate(item)) => (item, item.spans.inner_span, hir_id),
node => panic!("not a module: {node:?}"),
}
@@ -654,7 +558,7 @@ impl<'hir> Map<'hir> {
/// until the crate root is reached. Prefer this over your own loop using `parent_id`.
#[inline]
pub fn parent_iter(self, current_id: HirId) -> impl Iterator<Item = (HirId, Node<'hir>)> {
- self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.find(id)?)))
+ self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.tcx.opt_hir_node(id)?)))
}
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
@@ -706,7 +610,7 @@ impl<'hir> Map<'hir> {
pub fn get_return_block(self, id: HirId) -> Option<HirId> {
let mut iter = self.parent_iter(id).peekable();
let mut ignore_tail = false;
- if let Some(Node::Expr(Expr { kind: ExprKind::Ret(_), .. })) = self.find(id) {
+ if let Some(Node::Expr(Expr { kind: ExprKind::Ret(_), .. })) = self.tcx.opt_hir_node(id) {
// When dealing with `return` statements, we don't care about climbing only tail
// expressions.
ignore_tail = true;
@@ -814,7 +718,7 @@ impl<'hir> Map<'hir> {
let mut scope = id;
loop {
scope = self.get_enclosing_scope(scope).unwrap_or(CRATE_HIR_ID);
- if scope == CRATE_HIR_ID || !matches!(self.get(scope), Node::Block(_)) {
+ if scope == CRATE_HIR_ID || !matches!(self.tcx.hir_node(scope), Node::Block(_)) {
return scope;
}
}
@@ -870,7 +774,7 @@ impl<'hir> Map<'hir> {
}
pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> {
- match self.find(id) {
+ match self.tcx.opt_hir_node(id) {
Some(Node::Variant(variant)) => variant,
_ => bug!("expected variant, found {}", self.node_to_string(id)),
}
@@ -889,7 +793,7 @@ impl<'hir> Map<'hir> {
}
pub fn expect_expr(self, id: HirId) -> &'hir Expr<'hir> {
- match self.find(id) {
+ match self.tcx.opt_hir_node(id) {
Some(Node::Expr(expr)) => expr,
_ => bug!("expected expr, found {}", self.node_to_string(id)),
}
@@ -897,7 +801,7 @@ impl<'hir> Map<'hir> {
#[inline]
fn opt_ident(self, id: HirId) -> Option<Ident> {
- match self.get(id) {
+ match self.tcx.opt_hir_node(id)? {
Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
// A `Ctor` doesn't have an identifier itself, but its parent
// struct/variant does. Compare with `hir::Map::opt_span`.
@@ -966,7 +870,7 @@ impl<'hir> Map<'hir> {
}
}
- let span = match self.find(hir_id)? {
+ let span = match self.tcx.opt_hir_node(hir_id)? {
// Function-like.
Node::Item(Item { kind: ItemKind::Fn(sig, ..), span: outer_span, .. })
| Node::TraitItem(TraitItem {
@@ -1056,7 +960,7 @@ impl<'hir> Map<'hir> {
/// Like `hir.span()`, but includes the body of items
/// (instead of just the item header)
pub fn span_with_body(self, hir_id: HirId) -> Span {
- match self.get(hir_id) {
+ match self.tcx.hir_node(hir_id) {
Node::Param(param) => param.span,
Node::Item(item) => item.span,
Node::ForeignItem(foreign_item) => foreign_item.span,
@@ -1151,7 +1055,7 @@ impl<'hir> Map<'hir> {
impl<'hir> intravisit::Map<'hir> for Map<'hir> {
fn find(&self, hir_id: HirId) -> Option<Node<'hir>> {
- (*self).find(hir_id)
+ self.tcx.opt_hir_node(hir_id)
}
fn body(&self, id: BodyId) -> &'hir Body<'hir> {
@@ -1238,7 +1142,10 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
tcx.stable_crate_id(LOCAL_CRATE).hash_stable(&mut hcx, &mut stable_hasher);
// Hash visibility information since it does not appear in HIR.
- resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher);
+ // FIXME: Figure out how to remove `visibilities_for_hashing` by hashing visibilities on
+ // the fly in the resolver, storing only their accumulated hash in `ResolverGlobalCtxt`,
+ // and combining it with other hashes here.
+ resolutions.visibilities_for_hashing.hash_stable(&mut hcx, &mut stable_hasher);
stable_hasher.finish()
});
@@ -1265,7 +1172,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
- match map.find(id) {
+ match map.tcx.opt_hir_node(id) {
Some(Node::Item(item)) => {
let item_str = match item.kind {
ItemKind::ExternCrate(..) => "extern crate",
@@ -1278,7 +1185,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
ItemKind::ForeignMod { .. } => "foreign mod",
ItemKind::GlobalAsm(..) => "global asm",
ItemKind::TyAlias(..) => "ty",
- ItemKind::OpaqueTy(ref opaque) => {
+ ItemKind::OpaqueTy(opaque) => {
if opaque.in_trait {
"opaque type in trait"
} else {
@@ -1314,10 +1221,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
}
- Some(Node::Variant(ref variant)) => {
+ Some(Node::Variant(variant)) => {
format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
}
- Some(Node::Field(ref field)) => {
+ Some(Node::Field(field)) => {
format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
}
Some(Node::AnonConst(_)) => node_str("const"),
@@ -1341,7 +1248,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
),
Some(Node::Lifetime(_)) => node_str("lifetime"),
- Some(Node::GenericParam(ref param)) => {
+ Some(Node::GenericParam(param)) => {
format!("{id} (generic_param {})", path_str(param.def_id))
}
Some(Node::Crate(..)) => String::from("(root_crate)"),
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index f28ec7711..af99c7d55 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -166,7 +166,7 @@ pub fn provide(providers: &mut Providers) {
providers.hir_owner_parent = |tcx, id| {
// Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash.
tcx.opt_local_parent(id.def_id).map_or(CRATE_HIR_ID, |parent| {
- let mut parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent);
+ let mut parent_hir_id = tcx.local_def_id_to_hir_id(parent);
parent_hir_id.local_id =
tcx.hir_crate(()).owners[parent_hir_id.owner.def_id].unwrap().parenting[&id.def_id];
parent_hir_id
@@ -176,16 +176,16 @@ 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 hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let hir_id = tcx.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 hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let hir_id = tcx.local_def_id_to_hir_id(def_id);
tcx.hir().opt_ident_span(hir_id)
};
providers.fn_arg_names = |tcx, def_id| {
let hir = tcx.hir();
- let hir_id = hir.local_def_id_to_hir_id(def_id);
+ let hir_id = tcx.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))
} else if let Node::TraitItem(&TraitItem {
@@ -195,14 +195,13 @@ pub fn provide(providers: &mut Providers) {
| Node::ForeignItem(&ForeignItem {
kind: ForeignItemKind::Fn(_, idents, _),
..
- }) = hir.get(hir_id)
+ }) = tcx.hir_node(hir_id)
{
idents
} else {
span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", def_id);
}
};
- 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| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root());
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 64b63f4c5..e544c2a26 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -21,18 +21,25 @@
//!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lock;
use rustc_macros::HashStable;
use rustc_type_ir::Canonical as IrCanonical;
+use rustc_type_ir::CanonicalVarInfo as IrCanonicalVarInfo;
+pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind};
use smallvec::SmallVec;
+use std::collections::hash_map::Entry;
use std::ops::Index;
use crate::infer::MemberConstraint;
use crate::mir::ConstraintCategory;
use crate::ty::GenericArg;
-use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
+use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
pub type Canonical<'tcx, V> = IrCanonical<TyCtxt<'tcx>, V>;
+pub type CanonicalVarInfo<'tcx> = IrCanonicalVarInfo<TyCtxt<'tcx>>;
+
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
@@ -63,7 +70,7 @@ impl CanonicalVarValues<'_> {
pub fn is_identity(&self) -> bool {
self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
ty::GenericArgKind::Lifetime(r) => {
- matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var.as_usize() == bv)
+ matches!(*r, ty::ReBound(ty::INNERMOST, br) if br.var.as_usize() == bv)
}
ty::GenericArgKind::Type(ty) => {
matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
@@ -79,7 +86,7 @@ impl CanonicalVarValues<'_> {
for arg in self.var_values {
match arg.unpack() {
ty::GenericArgKind::Lifetime(r) => {
- if let ty::ReLateBound(ty::INNERMOST, br) = *r
+ if let ty::ReBound(ty::INNERMOST, br) = *r
&& var == br.var
{
var = var + 1;
@@ -138,158 +145,6 @@ impl<'tcx> Default for OriginalQueryValues<'tcx> {
}
}
-/// Information about a canonical variable that is included with the
-/// canonical value. This is sufficient information for code to create
-/// a copy of the canonical value in some other inference context,
-/// with fresh inference variables replacing the canonical values.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct CanonicalVarInfo<'tcx> {
- pub kind: CanonicalVarKind<'tcx>,
-}
-
-impl<'tcx> CanonicalVarInfo<'tcx> {
- pub fn universe(&self) -> ty::UniverseIndex {
- self.kind.universe()
- }
-
- #[must_use]
- pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarInfo<'tcx> {
- CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
- }
-
- pub fn is_existential(&self) -> bool {
- match self.kind {
- CanonicalVarKind::Ty(_) => true,
- CanonicalVarKind::PlaceholderTy(_) => false,
- CanonicalVarKind::Region(_) => true,
- CanonicalVarKind::PlaceholderRegion(..) => false,
- CanonicalVarKind::Const(..) => true,
- CanonicalVarKind::PlaceholderConst(_, _) => false,
- CanonicalVarKind::Effect => true,
- }
- }
-
- pub fn is_region(&self) -> bool {
- match self.kind {
- CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
- CanonicalVarKind::Ty(_)
- | CanonicalVarKind::PlaceholderTy(_)
- | CanonicalVarKind::Const(_, _)
- | CanonicalVarKind::PlaceholderConst(_, _)
- | CanonicalVarKind::Effect => false,
- }
- }
-
- pub fn expect_placeholder_index(self) -> usize {
- match self.kind {
- CanonicalVarKind::Ty(_)
- | CanonicalVarKind::Region(_)
- | CanonicalVarKind::Const(_, _)
- | CanonicalVarKind::Effect => bug!("expected placeholder: {self:?}"),
-
- CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(),
- CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(),
- CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.as_usize(),
- }
- }
-}
-
-/// Describes the "kind" of the canonical variable. This is a "kind"
-/// in the type-theory sense of the term -- i.e., a "meta" type system
-/// that analyzes type-like values.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub enum CanonicalVarKind<'tcx> {
- /// Some kind of type inference variable.
- Ty(CanonicalTyVarKind),
-
- /// A "placeholder" that represents "any type".
- PlaceholderTy(ty::PlaceholderType),
-
- /// Region variable `'?R`.
- Region(ty::UniverseIndex),
-
- /// A "placeholder" that represents "any region". Created when you
- /// are solving a goal like `for<'a> T: Foo<'a>` to represent the
- /// bound region `'a`.
- PlaceholderRegion(ty::PlaceholderRegion),
-
- /// Some kind of const inference variable.
- Const(ty::UniverseIndex, Ty<'tcx>),
-
- /// Effect variable `'?E`.
- Effect,
-
- /// A "placeholder" that represents "any const".
- PlaceholderConst(ty::PlaceholderConst, Ty<'tcx>),
-}
-
-impl<'tcx> CanonicalVarKind<'tcx> {
- pub fn universe(self) -> ty::UniverseIndex {
- match self {
- CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
- CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
- ty::UniverseIndex::ROOT
- }
- CanonicalVarKind::Effect => ty::UniverseIndex::ROOT,
- CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
- CanonicalVarKind::Region(ui) => ui,
- CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
- CanonicalVarKind::Const(ui, _) => ui,
- CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe,
- }
- }
-
- /// Replaces the universe of this canonical variable with `ui`.
- ///
- /// In case this is a float or int variable, this causes an ICE if
- /// the updated universe is not the root.
- pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx> {
- match self {
- CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => {
- CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
- }
- CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
- | CanonicalVarKind::Effect => {
- assert_eq!(ui, ty::UniverseIndex::ROOT);
- self
- }
- CanonicalVarKind::PlaceholderTy(placeholder) => {
- CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder })
- }
- CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
- CanonicalVarKind::PlaceholderRegion(placeholder) => {
- CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe: ui, ..placeholder })
- }
- CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
- CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
- CanonicalVarKind::PlaceholderConst(
- ty::Placeholder { universe: ui, ..placeholder },
- ty,
- )
- }
- }
- }
-}
-
-/// Rust actually has more than one category of type variables;
-/// notably, the type variables we create for literals (e.g., 22 or
-/// 22.) can only be instantiated with integral/float types (e.g.,
-/// usize or f32). In order to faithfully reproduce a type, we need to
-/// know what set of types a given type variable can be unified with.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
-pub enum CanonicalTyVarKind {
- /// General type variable `?T` that can be unified with arbitrary types.
- General(ty::UniverseIndex),
-
- /// Integral type variable `?I` (that can only be unified with integral types).
- Int,
-
- /// Floating-point type variable `?F` (that can only be unified with float types).
- Float,
-}
-
/// After we execute a query with a canonicalized key, we get back a
/// `Canonical<QueryResponse<..>>`. You can use
/// `instantiate_query_result` to access the data in this result.
@@ -366,7 +221,6 @@ pub type QueryOutlivesConstraint<'tcx> =
TrivialTypeTraversalImpls! {
crate::infer::canonical::Certainty,
- crate::infer::canonical::CanonicalTyVarKind,
}
impl<'tcx> CanonicalVarValues<'tcx> {
@@ -389,7 +243,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
var: ty::BoundVar::from_usize(i),
kind: ty::BrAnon,
};
- ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into()
+ ty::Region::new_bound(tcx, ty::INNERMOST, br).into()
}
CanonicalVarKind::Effect => ty::Const::new_bound(
tcx,
@@ -440,3 +294,62 @@ impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
&self.var_values[value.as_usize()]
}
}
+
+#[derive(Default)]
+pub struct CanonicalParamEnvCache<'tcx> {
+ map: Lock<
+ FxHashMap<
+ ty::ParamEnv<'tcx>,
+ (Canonical<'tcx, ty::ParamEnv<'tcx>>, &'tcx [GenericArg<'tcx>]),
+ >,
+ >,
+}
+
+impl<'tcx> CanonicalParamEnvCache<'tcx> {
+ /// Gets the cached canonical form of `key` or executes
+ /// `canonicalize_op` and caches the result if not present.
+ ///
+ /// `canonicalize_op` is intentionally not allowed to be a closure to
+ /// statically prevent it from capturing `InferCtxt` and resolving
+ /// inference variables, which invalidates the cache.
+ pub fn get_or_insert(
+ &self,
+ tcx: TyCtxt<'tcx>,
+ key: ty::ParamEnv<'tcx>,
+ state: &mut OriginalQueryValues<'tcx>,
+ canonicalize_op: fn(
+ TyCtxt<'tcx>,
+ ty::ParamEnv<'tcx>,
+ &mut OriginalQueryValues<'tcx>,
+ ) -> Canonical<'tcx, ty::ParamEnv<'tcx>>,
+ ) -> Canonical<'tcx, ty::ParamEnv<'tcx>> {
+ if !key.has_type_flags(
+ TypeFlags::HAS_INFER | TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_FREE_REGIONS,
+ ) {
+ return Canonical {
+ max_universe: ty::UniverseIndex::ROOT,
+ variables: List::empty(),
+ value: key,
+ };
+ }
+
+ assert_eq!(state.var_values.len(), 0);
+ assert_eq!(state.universe_map.len(), 1);
+ debug_assert_eq!(&*state.universe_map, &[ty::UniverseIndex::ROOT]);
+
+ match self.map.borrow().entry(key) {
+ Entry::Occupied(e) => {
+ let (canonical, var_values) = e.get();
+ state.var_values.extend_from_slice(var_values);
+ *canonical
+ }
+ Entry::Vacant(e) => {
+ let canonical = canonicalize_op(tcx, key, state);
+ let OriginalQueryValues { var_values, universe_map } = state;
+ assert_eq!(universe_map.len(), 1);
+ e.insert((canonical, tcx.arena.alloc_slice(var_values)));
+ canonical
+ }
+ }
+ }
+}
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index 041a63776..6e50e8940 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -58,18 +58,17 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
// 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.
+ // This is *not* necessary for completeness.
#[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::ReLateParam(..)
+ | ty::ReEarlyParam(..)
| ty::ReError(_) => ty::UniverseIndex::ROOT,
ty::RePlaceholder(placeholder) => placeholder.universe,
- ty::ReVar(..) | ty::ReLateBound(..) => bug!("not a universal region"),
+ ty::ReVar(..) | ty::ReBound(..) => bug!("not a universal region"),
})
}
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 448a3029a..3206c6cf6 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -23,8 +23,8 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![cfg_attr(not(bootstrap), doc(rust_logo))]
-#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
+#![doc(rust_logo)]
+#![feature(rustdoc_internals)]
#![feature(allocator_api)]
#![feature(array_windows)]
#![feature(assert_matches)]
@@ -32,8 +32,7 @@
#![feature(core_intrinsics)]
#![feature(discriminant_kind)]
#![feature(exhaustive_patterns)]
-#![cfg_attr(bootstrap, feature(generators))]
-#![cfg_attr(not(bootstrap), feature(coroutines))]
+#![feature(coroutines)]
#![feature(get_mut_unchecked)]
#![feature(if_let_guard)]
#![feature(inline_const)]
@@ -59,7 +58,6 @@
#![feature(extract_if)]
#![feature(intra_doc_pointers)]
#![feature(yeet_expr)]
-#![feature(result_option_inspect)]
#![feature(const_option)]
#![feature(trait_alias)]
#![feature(ptr_alignment_type)]
@@ -79,9 +77,6 @@ extern crate tracing;
#[macro_use]
extern crate smallvec;
-use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_fluent_macro::fluent_messages;
-
#[cfg(test)]
mod tests;
@@ -112,4 +107,4 @@ pub mod dep_graph;
// Allows macros to refer to this crate as `::rustc_middle`
extern crate self as rustc_middle;
-fluent_messages! { "../messages.ftl" }
+rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index eada116f8..c49c4ee81 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -253,29 +253,10 @@ pub fn explain_lint_level_source(
/// - [`TyCtxt::struct_lint_node`]
/// - `LintContext::lookup`
///
-/// ## `decorate` signature
+/// ## `decorate`
///
-/// The return value of `decorate` is ignored by this function. So what is the
-/// point of returning `&'b mut DiagnosticBuilder<'a, ()>`?
-///
-/// There are 2 reasons for this signature.
-///
-/// First of all, it prevents accidental use of `.emit()` -- it's clear that the
-/// builder will be later used and shouldn't be emitted right away (this is
-/// especially important because the old API expected you to call `.emit()` in
-/// the closure).
-///
-/// Second of all, it makes the most common case of adding just a single label
-/// /suggestion much nicer, since [`DiagnosticBuilder`] methods return
-/// `&mut DiagnosticBuilder`, you can just chain methods, without needed
-/// awkward `{ ...; }`:
-/// ```ignore pseudo-code
-/// struct_lint_level(
-/// ...,
-/// |lint| lint.span_label(sp, "lbl")
-/// // ^^^^^^^^^^^^^^^^^^^^^ returns `&mut DiagnosticBuilder` by default
-/// )
-/// ```
+/// It is not intended to call `emit`/`cancel` on the `DiagnosticBuilder` passed
+/// in the `decorate` callback.
#[track_caller]
pub fn struct_lint_level(
sess: &Session,
@@ -284,9 +265,7 @@ pub fn struct_lint_level(
src: LintLevelSource,
span: Option<MultiSpan>,
msg: impl Into<DiagnosticMessage>,
- decorate: impl for<'a, 'b> FnOnce(
- &'b mut DiagnosticBuilder<'a, ()>,
- ) -> &'b mut DiagnosticBuilder<'a, ()>,
+ decorate: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>),
) {
// Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
// the "real" work.
@@ -298,12 +277,7 @@ pub fn struct_lint_level(
src: LintLevelSource,
span: Option<MultiSpan>,
msg: impl Into<DiagnosticMessage>,
- decorate: Box<
- dyn '_
- + for<'a, 'b> FnOnce(
- &'b mut DiagnosticBuilder<'a, ()>,
- ) -> &'b mut DiagnosticBuilder<'a, ()>,
- >,
+ decorate: Box<dyn '_ + for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>)>,
) {
// Check for future incompatibility lints and issue a stronger warning.
let future_incompatible = lint.future_incompatible;
@@ -334,7 +308,7 @@ pub fn struct_lint_level(
(Level::Expect(expect_id), _) => {
// This case is special as we actually allow the lint itself in this context, but
// we can't return early like in the case for `Level::Allow` because we still
- // need the lint diagnostic to be emitted to `rustc_error::HandlerInner`.
+ // need the lint diagnostic to be emitted to `rustc_error::DiagCtxtInner`.
//
// We can also not mark the lint expectation as fulfilled here right away, as it
// can still be cancelled in the decorate function. All of this means that we simply
@@ -350,11 +324,11 @@ pub fn struct_lint_level(
(Level::Warn | Level::ForceWarn(None), Some(span)) => sess.struct_span_warn(span, ""),
(Level::Warn | Level::ForceWarn(None), None) => sess.struct_warn(""),
(Level::Deny | Level::Forbid, Some(span)) => {
- let mut builder = sess.diagnostic().struct_err_lint("");
+ let mut builder = sess.dcx().struct_err_lint("");
builder.set_span(span);
builder
}
- (Level::Deny | Level::Forbid, None) => sess.diagnostic().struct_err_lint(""),
+ (Level::Deny | Level::Forbid, None) => sess.dcx().struct_err_lint(""),
};
err.set_is_lint();
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index c1884bb80..8c1e58fef 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -4,9 +4,10 @@
///
/// If you have a span available, you should use [`span_bug`] instead.
///
-/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful.
+/// If the bug should only be emitted when compilation didn't fail, [`Session::span_delayed_bug`]
+/// may be useful.
///
-/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
+/// [`Session::span_delayed_bug`]: rustc_session::Session::span_delayed_bug
/// [`span_bug`]: crate::span_bug
#[macro_export]
macro_rules! bug {
@@ -23,9 +24,10 @@ macro_rules! bug {
/// at the code the compiler was compiling when it ICEd. This is the preferred way to trigger
/// ICEs.
///
-/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful.
+/// If the bug should only be emitted when compilation didn't fail, [`Session::span_delayed_bug`]
+/// may be useful.
///
-/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
+/// [`Session::span_delayed_bug`]: rustc_session::Session::span_delayed_bug
#[macro_export]
macro_rules! span_bug {
($span:expr, $msg:expr) => ({ $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg)) });
diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs
index 9a633e04c..2899e629d 100644
--- a/compiler/rustc_middle/src/middle/lang_items.rs
+++ b/compiler/rustc_middle/src/middle/lang_items.rs
@@ -36,6 +36,17 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
+ /// Given a [`ty::ClosureKind`], get the [`DefId`] of its corresponding `Fn`-family
+ /// trait, if it is defined.
+ pub fn fn_trait_kind_to_def_id(self, kind: ty::ClosureKind) -> Option<DefId> {
+ let items = self.lang_items();
+ match kind {
+ ty::ClosureKind::Fn => items.fn_trait(),
+ ty::ClosureKind::FnMut => items.fn_mut_trait(),
+ ty::ClosureKind::FnOnce => items.fn_once_trait(),
+ }
+ }
+
/// Returns `true` if `id` is a `DefId` of [`Fn`], [`FnMut`] or [`FnOnce`] traits.
pub fn is_fn_trait(self, id: DefId) -> bool {
self.fn_trait_kind_from_def_id(id).is_some()
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index d4f023958..b29be92ae 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -8,7 +8,6 @@
//! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
//! just peeks and looks for that attribute.
-use crate::bug;
use crate::error::LimitInvalid;
use crate::query::Providers;
use rustc_ast::Attribute;
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 85c5af9ca..8c1b1ff12 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -7,22 +7,23 @@ pub mod lib_features {
use rustc_data_structures::fx::FxHashMap;
use rustc_span::{symbol::Symbol, Span};
- #[derive(HashStable, Debug)]
+ #[derive(Copy, Clone, Debug, PartialEq, Eq)]
+ #[derive(HashStable, TyEncodable, TyDecodable)]
+ pub enum FeatureStability {
+ AcceptedSince(Symbol),
+ Unstable,
+ }
+
+ #[derive(HashStable, Debug, Default)]
pub struct LibFeatures {
- /// A map from feature to stabilisation version.
- pub stable: FxHashMap<Symbol, (Symbol, Span)>,
- pub unstable: FxHashMap<Symbol, Span>,
+ pub stability: FxHashMap<Symbol, (FeatureStability, Span)>,
}
impl LibFeatures {
- pub fn to_vec(&self) -> Vec<(Symbol, Option<Symbol>)> {
- let mut all_features: Vec<_> = self
- .stable
- .iter()
- .map(|(f, (s, _))| (*f, Some(*s)))
- .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());
+ pub fn to_vec(&self) -> Vec<(Symbol, FeatureStability)> {
+ let mut all_features: Vec<_> =
+ self.stability.iter().map(|(&sym, &(stab, _))| (sym, stab)).collect();
+ all_features.sort_unstable_by(|(a, _), (b, _)| a.as_str().cmp(b.as_str()));
all_features
}
}
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index 56fed05c6..3f6dc2b9f 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -77,7 +77,7 @@ use std::ops::Deref;
/// picture, but rather the ending point.
//
// FIXME(pnkfelix): this currently derives `PartialOrd` and `Ord` to
-// placate the same deriving in `ty::FreeRegion`, but we may want to
+// placate the same deriving in `ty::LateParamRegion`, but we may want to
// actually attach a more meaningful ordering to scopes than the one
// generated via deriving here.
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, TyEncodable, TyDecodable)]
@@ -148,6 +148,8 @@ rustc_index::newtype_index! {
/// * The subscope with `first_statement_index == 1` is scope of `c`,
/// and thus does not include EXPR_2, but covers the `...`.
#[derive(HashStable)]
+ #[encodable]
+ #[orderable]
pub struct FirstStatementIndex {}
}
@@ -178,7 +180,7 @@ impl Scope {
};
let span = tcx.hir().span(hir_id);
if let ScopeData::Remainder(first_statement_index) = self.data {
- if let Node::Block(ref blk) = tcx.hir().get(hir_id) {
+ if let Node::Block(blk) = tcx.hir_node(hir_id) {
// Want span for scope starting after the
// indexed statement and ending at end of
// `blk`; reuse span of `blk` and shift `lo`
@@ -347,10 +349,6 @@ impl ScopeTree {
}
}
- pub fn opt_destruction_scope(&self, n: hir::ItemLocalId) -> Option<Scope> {
- self.destruction_scopes.get(&n).cloned()
- }
-
pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) {
debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime);
assert!(var != lifetime.item_local_id());
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index f7a55fa95..0cba6d5b5 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -219,11 +219,10 @@ fn late_report_deprecation(
}
let method_span = method_span.unwrap_or(span);
tcx.struct_span_lint_hir(lint, hir_id, method_span, message, |diag| {
- if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
+ if let hir::Node::Expr(_) = tcx.hir_node(hir_id) {
let kind = tcx.def_descr(def_id);
deprecation_suggestion(diag, kind, suggestion, method_span);
}
- diag
});
}
@@ -566,7 +565,7 @@ impl<'tcx> TyCtxt<'tcx> {
|span, def_id| {
// The API could be uncallable for other reasons, for example when a private module
// was referenced.
- self.sess.delay_span_bug(span, format!("encountered unmarked API: {def_id:?}"));
+ self.sess.span_delayed_bug(span, format!("encountered unmarked API: {def_id:?}"));
},
)
}
@@ -587,7 +586,7 @@ impl<'tcx> TyCtxt<'tcx> {
unmarked: impl FnOnce(Span, DefId),
) -> bool {
let soft_handler = |lint, span, msg: String| {
- self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |lint| lint)
+ self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |_| {})
};
let eval_result =
self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index a9d09709e..2c38f998c 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -1,17 +1,15 @@
use std::fmt::{self, Debug, Display, Formatter};
-use rustc_hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::{self as hir};
+use rustc_hir::def_id::DefId;
use rustc_session::RemapFileNameExt;
use rustc_span::Span;
use rustc_target::abi::{HasDataLayout, Size};
use crate::mir::interpret::{alloc_range, AllocId, ConstAllocation, ErrorHandled, Scalar};
use crate::mir::{pretty_print_const_value, Promoted};
+use crate::ty::GenericArgsRef;
use crate::ty::ScalarInt;
-use crate::ty::{self, print::pretty_print_const, List, Ty, TyCtxt};
-use crate::ty::{GenericArgs, GenericArgsRef};
+use crate::ty::{self, print::pretty_print_const, Ty, TyCtxt};
///////////////////////////////////////////////////////////////////////////
/// Evaluated Constants
@@ -76,7 +74,7 @@ static_assert_size!(ConstValue<'_>, 24);
impl<'tcx> ConstValue<'tcx> {
#[inline]
- pub fn try_to_scalar(&self) -> Option<Scalar<AllocId>> {
+ pub fn try_to_scalar(&self) -> Option<Scalar> {
match *self {
ConstValue::Indirect { .. } | ConstValue::Slice { .. } | ConstValue::ZeroSized => None,
ConstValue::Scalar(val) => Some(val),
@@ -162,8 +160,8 @@ impl<'tcx> ConstValue<'tcx> {
return Some(&[]);
}
// Non-empty slice, must have memory. We know this is a relative pointer.
- let (inner_alloc_id, offset) = ptr.into_parts();
- let data = tcx.global_alloc(inner_alloc_id?).unwrap_memory();
+ let (inner_prov, offset) = ptr.into_parts();
+ let data = tcx.global_alloc(inner_prov?.alloc_id()).unwrap_memory();
(data, offset.bytes(), offset.bytes() + len)
}
};
@@ -220,6 +218,17 @@ pub enum Const<'tcx> {
}
impl<'tcx> Const<'tcx> {
+ pub fn identity_unevaluated(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::EarlyBinder<Const<'tcx>> {
+ ty::EarlyBinder::bind(Const::Unevaluated(
+ UnevaluatedConst {
+ def: def_id,
+ args: ty::GenericArgs::identity_for_item(tcx, def_id),
+ promoted: None,
+ },
+ tcx.type_of(def_id).skip_binder(),
+ ))
+ }
+
#[inline(always)]
pub fn ty(&self) -> Ty<'tcx> {
match self {
@@ -399,101 +408,6 @@ impl<'tcx> Const<'tcx> {
Self::Val(val, ty)
}
- /// Literals are converted to `Const::Val`, const generic parameters are eagerly
- /// converted to a constant, everything else becomes `Unevaluated`.
- #[instrument(skip(tcx), level = "debug", ret)]
- pub fn from_anon_const(
- tcx: TyCtxt<'tcx>,
- def: LocalDefId,
- param_env: ty::ParamEnv<'tcx>,
- ) -> Self {
- let body_id = match tcx.hir().get_by_def_id(def) {
- hir::Node::AnonConst(ac) => ac.body,
- _ => {
- span_bug!(tcx.def_span(def), "from_anon_const can only process anonymous constants")
- }
- };
-
- let expr = &tcx.hir().body(body_id).value;
- debug!(?expr);
-
- // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
- // currently have to be wrapped in curly brackets, so it's necessary to special-case.
- let expr = match &expr.kind {
- hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
- block.expr.as_ref().unwrap()
- }
- _ => expr,
- };
- debug!("expr.kind: {:?}", expr.kind);
-
- let ty = tcx.type_of(def).instantiate_identity();
- debug!(?ty);
-
- // FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
- // does not provide the parents generics to anonymous constants. We still allow generic const
- // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
- // ever try to substitute the generic parameters in their bodies.
- //
- // While this doesn't happen as these constants are always used as `ty::ConstKind::Param`, it does
- // cause issues if we were to remove that special-case and try to evaluate the constant instead.
- use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
- match expr.kind {
- ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
- // Find the name and index of the const parameter by indexing the generics of
- // the parent item and construct a `ParamConst`.
- let item_def_id = tcx.parent(def_id);
- 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);
- let ty_const = ty::Const::new_param(tcx, ty::ParamConst::new(index, name), ty);
- debug!(?ty_const);
-
- return Self::Ty(ty_const);
- }
- _ => {}
- }
-
- let hir_id = tcx.hir().local_def_id_to_hir_id(def);
- let parent_args = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
- && let Some(parent_did) = parent_hir_id.as_owner()
- {
- GenericArgs::identity_for_item(tcx, parent_did)
- } else {
- List::empty()
- };
- debug!(?parent_args);
-
- let did = def.to_def_id();
- let child_args = GenericArgs::identity_for_item(tcx, did);
- let args = tcx.mk_args_from_iter(parent_args.into_iter().chain(child_args.into_iter()));
- debug!(?args);
-
- let span = tcx.def_span(def);
- let uneval = UnevaluatedConst::new(did, args);
- debug!(?span, ?param_env);
-
- match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
- Ok(val) => {
- debug!("evaluated const value");
- Self::Val(val, ty)
- }
- Err(_) => {
- debug!("error encountered during evaluation");
- // Error was handled in `const_eval_resolve`. Here we just create a
- // new unevaluated const and error hard later in codegen
- Self::Unevaluated(
- UnevaluatedConst {
- def: did,
- args: GenericArgs::identity_for_item(tcx, did),
- promoted: None,
- },
- ty,
- )
- }
- }
- }
-
pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
match c.kind() {
ty::ConstKind::Value(valtree) => {
@@ -592,7 +506,7 @@ impl<'tcx> TyCtxt<'tcx> {
let caller = self.sess.source_map().lookup_char_pos(topmost.lo());
self.const_caller_location(
rustc_span::symbol::Symbol::intern(
- &caller.file.name.for_codegen(&self.sess).to_string_lossy(),
+ &caller.file.name.for_codegen(self.sess).to_string_lossy(),
),
caller.line as u32,
caller.col_display as u32 + 1,
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index 08d377a86..ec5edceb2 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -17,6 +17,8 @@ rustc_index::newtype_index! {
/// Note that LLVM handles counter IDs as `uint32_t`, so there is no need
/// to use a larger representation on the Rust side.
#[derive(HashStable)]
+ #[encodable]
+ #[orderable]
#[max = 0xFFFF_FFFF]
#[debug_format = "CounterId({})"]
pub struct CounterId {}
@@ -37,6 +39,8 @@ rustc_index::newtype_index! {
/// Note that LLVM handles expression IDs as `uint32_t`, so there is no need
/// to use a larger representation on the Rust side.
#[derive(HashStable)]
+ #[encodable]
+ #[orderable]
#[max = 0xFFFF_FFFF]
#[debug_format = "ExpressionId({})"]
pub struct ExpressionId {}
@@ -72,6 +76,13 @@ impl Debug for CovTerm {
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
pub enum CoverageKind {
+ /// Marks a span that might otherwise not be represented in MIR, so that
+ /// coverage instrumentation can associate it with its enclosing block/BCB.
+ ///
+ /// Only used by the `InstrumentCoverage` pass, and has no effect during
+ /// codegen.
+ SpanMarker,
+
/// Marks the point in MIR control flow represented by a coverage counter.
///
/// This is eventually lowered to `llvm.instrprof.increment` in LLVM IR.
@@ -95,6 +106,7 @@ impl Debug for CoverageKind {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
use CoverageKind::*;
match self {
+ SpanMarker => write!(fmt, "SpanMarker"),
CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()),
ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()),
}
diff --git a/compiler/rustc_middle/src/mir/generic_graph.rs b/compiler/rustc_middle/src/mir/generic_graph.rs
index d1753427e..51e26ab79 100644
--- a/compiler/rustc_middle/src/mir/generic_graph.rs
+++ b/compiler/rustc_middle/src/mir/generic_graph.rs
@@ -1,7 +1,5 @@
use gsgdt::{Edge, Graph, Node, NodeStyle};
-use rustc_hir::def_id::DefId;
use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
/// Convert an MIR function into a gsgdt Graph
pub fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Graph {
diff --git a/compiler/rustc_middle/src/mir/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs
index 5c7de8644..96bef40da 100644
--- a/compiler/rustc_middle/src/mir/graphviz.rs
+++ b/compiler/rustc_middle/src/mir/graphviz.rs
@@ -1,9 +1,6 @@
use gsgdt::GraphvizSettings;
use rustc_graphviz as dot;
-use rustc_hir::def_id::DefId;
use rustc_middle::mir::*;
-use rustc_middle::ty::{self, TyCtxt};
-use std::fmt::Debug;
use std::io::{self, Write};
use super::generic_graph::mir_fn_to_generic_graph;
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index aded3e495..2a9e0847f 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -18,9 +18,9 @@ use rustc_span::DUMMY_SP;
use rustc_target::abi::{Align, HasDataLayout, Size};
use super::{
- read_target_uint, write_target_uint, AllocId, BadBytesAccess, InterpError, InterpResult,
- Pointer, PointerArithmetic, Provenance, ResourceExhaustionInfo, Scalar, ScalarSizeMismatch,
- UndefinedBehaviorInfo, UnsupportedOpInfo,
+ read_target_uint, write_target_uint, AllocId, BadBytesAccess, CtfeProvenance, InterpError,
+ InterpResult, Pointer, PointerArithmetic, Provenance, ResourceExhaustionInfo, Scalar,
+ ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo,
};
use crate::ty;
use init_mask::*;
@@ -63,7 +63,7 @@ impl AllocBytes for Box<[u8]> {
// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
#[derive(Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
#[derive(HashStable)]
-pub struct Allocation<Prov: Provenance = AllocId, Extra = (), Bytes = Box<[u8]>> {
+pub struct Allocation<Prov: Provenance = CtfeProvenance, Extra = (), Bytes = Box<[u8]>> {
/// The actual bytes of the allocation.
/// Note that the bytes of a pointer represent the offset of the pointer.
bytes: Bytes,
@@ -315,7 +315,7 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
pub fn try_uninit<'tcx>(size: Size, align: Align) -> InterpResult<'tcx, Self> {
Self::uninit_inner(size, align, || {
ty::tls::with(|tcx| {
- tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpretation")
+ tcx.sess.span_delayed_bug(DUMMY_SP, "exhausted memory during interpretation")
});
InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted).into()
})
@@ -336,14 +336,14 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
}
}
-impl<Bytes: AllocBytes> Allocation<AllocId, (), Bytes> {
- /// Adjust allocation from the ones in tcx to a custom Machine instance
- /// with a different Provenance and Extra type.
+impl<Bytes: AllocBytes> Allocation<CtfeProvenance, (), Bytes> {
+ /// Adjust allocation from the ones in `tcx` to a custom Machine instance
+ /// with a different `Provenance` and `Extra` type.
pub fn adjust_from_tcx<Prov: Provenance, Extra, Err>(
self,
cx: &impl HasDataLayout,
extra: Extra,
- mut adjust_ptr: impl FnMut(Pointer<AllocId>) -> Result<Pointer<Prov>, Err>,
+ mut adjust_ptr: impl FnMut(Pointer<CtfeProvenance>) -> Result<Pointer<Prov>, Err>,
) -> Result<Allocation<Prov, Extra, Bytes>, Err> {
let mut bytes = self.bytes;
// Adjust provenance of pointers stored in this allocation.
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 d504af6b7..9459af490 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -6,14 +6,14 @@ use std::cmp;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_target::abi::{HasDataLayout, Size};
-use super::{alloc_range, AllocError, AllocId, AllocRange, AllocResult, Provenance};
+use super::{alloc_range, AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
/// Stores the provenance information of pointers stored in memory.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
#[derive(HashStable)]
-pub struct ProvenanceMap<Prov = AllocId> {
- /// Provenance in this map applies from the given offset for an entire pointer-size worth of
+pub struct ProvenanceMap<Prov = CtfeProvenance> {
+ /// `Provenance` in this map applies from the given offset for an entire pointer-size worth of
/// 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.
@@ -22,18 +22,19 @@ pub struct ProvenanceMap<Prov = AllocId> {
bytes: Option<Box<SortedMap<Size, Prov>>>,
}
+// These impls are generic over `Prov` since `CtfeProvenance` is only decodable/encodable
+// for some particular `D`/`S`.
impl<D: Decoder, Prov: Provenance + Decodable<D>> Decodable<D> for ProvenanceMap<Prov> {
fn decode(d: &mut D) -> Self {
- assert!(!Prov::OFFSET_IS_ADDR); // only `AllocId` is ever serialized
+ assert!(!Prov::OFFSET_IS_ADDR); // only `CtfeProvenance` is ever serialized
Self { ptrs: Decodable::decode(d), bytes: None }
}
}
-
impl<S: Encoder, Prov: Provenance + Encodable<S>> Encodable<S> for ProvenanceMap<Prov> {
fn encode(&self, s: &mut S) {
let Self { ptrs, bytes } = self;
- assert!(!Prov::OFFSET_IS_ADDR); // only `AllocId` is ever serialized
- debug_assert!(bytes.is_none());
+ assert!(!Prov::OFFSET_IS_ADDR); // only `CtfeProvenance` is ever serialized
+ debug_assert!(bytes.is_none()); // without `OFFSET_IS_ADDR`, this is always empty
ptrs.encode(s)
}
}
@@ -54,10 +55,10 @@ impl ProvenanceMap {
/// Give access to the ptr-sized provenances (which can also be thought of as relocations, and
/// indeed that is how codegen treats them).
///
- /// Only exposed with `AllocId` provenance, since it panics if there is bytewise provenance.
+ /// Only exposed with `CtfeProvenance` provenance, since it panics if there is bytewise provenance.
#[inline]
- pub fn ptrs(&self) -> &SortedMap<Size, AllocId> {
- debug_assert!(self.bytes.is_none()); // `AllocId::OFFSET_IS_ADDR` is false so this cannot fail
+ pub fn ptrs(&self) -> &SortedMap<Size, CtfeProvenance> {
+ debug_assert!(self.bytes.is_none()); // `CtfeProvenance::OFFSET_IS_ADDR` is false so this cannot fail
&self.ptrs
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 44b22e2d3..413867939 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -290,7 +290,7 @@ macro_rules! impl_into_diagnostic_arg_through_debug {
// These types have nice `Debug` output so we can just use them in diagnostics.
impl_into_diagnostic_arg_through_debug! {
AllocId,
- Pointer,
+ Pointer<AllocId>,
AllocRange,
}
@@ -323,7 +323,7 @@ pub enum UndefinedBehaviorInfo<'tcx> {
/// Invalid metadata in a wide pointer
InvalidMeta(InvalidMetaKind),
/// Reading a C string that does not end within its allocation.
- UnterminatedCString(Pointer),
+ UnterminatedCString(Pointer<AllocId>),
/// Using a pointer after it got freed.
PointerUseAfterFree(AllocId, CheckInAllocMsg),
/// Used a pointer outside the bounds it is valid for.
@@ -350,11 +350,11 @@ pub enum UndefinedBehaviorInfo<'tcx> {
/// Using a non-character `u32` as character.
InvalidChar(u32),
/// The tag of an enum does not encode an actual discriminant.
- InvalidTag(Scalar),
+ InvalidTag(Scalar<AllocId>),
/// Using a pointer-not-to-a-function as function pointer.
- InvalidFunctionPointer(Pointer),
+ InvalidFunctionPointer(Pointer<AllocId>),
/// Using a pointer-not-to-a-vtable as vtable pointer.
- InvalidVTablePointer(Pointer),
+ InvalidVTablePointer(Pointer<AllocId>),
/// Using a string that is not valid UTF-8,
InvalidStr(std::str::Utf8Error),
/// Using uninitialized data where it is not allowed.
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index e360fb3ea..2db560085 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -157,7 +157,7 @@ pub use self::allocation::{
InitChunk, InitChunkIter,
};
-pub use self::pointer::{Pointer, PointerArithmetic, Provenance};
+pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance};
/// Uniquely identifies one of the following:
/// - A constant
@@ -199,7 +199,7 @@ pub struct LitToConstInput<'tcx> {
#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable)]
pub enum LitToConstError {
/// The literal's inferred type did not match the expected `ty` in the input.
- /// This is used for graceful error handling (`delay_span_bug`) in
+ /// This is used for graceful error handling (`span_delayed_bug`) in
/// type checking (`Const::from_anon_const`).
TypeError,
Reported(ErrorGuaranteed),
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index 1c9ce1cb1..689338773 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -3,7 +3,7 @@ use super::{AllocId, InterpResult};
use rustc_macros::HashStable;
use rustc_target::abi::{HasDataLayout, Size};
-use std::fmt;
+use std::{fmt, num::NonZeroU64};
////////////////////////////////////////////////////////////////////////////////
// Pointer arithmetic
@@ -114,22 +114,7 @@ pub trait Provenance: Copy + fmt::Debug + 'static {
const OFFSET_IS_ADDR: bool;
/// Determines how a pointer should be printed.
- ///
- /// Default impl is only good for when `OFFSET_IS_ADDR == true`.
- fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result
- where
- Self: Sized,
- {
- assert!(Self::OFFSET_IS_ADDR);
- let (prov, addr) = ptr.into_parts(); // address is absolute
- write!(f, "{:#x}", addr.bytes())?;
- if f.alternate() {
- write!(f, "{prov:#?}")?;
- } else {
- write!(f, "{prov:?}")?;
- }
- Ok(())
- }
+ fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result;
/// If `OFFSET_IS_ADDR == false`, provenance must always be able to
/// identify the allocation this ptr points to (i.e., this must return `Some`).
@@ -141,6 +126,80 @@ pub trait Provenance: Copy + fmt::Debug + 'static {
fn join(left: Option<Self>, right: Option<Self>) -> Option<Self>;
}
+/// The type of provenance in the compile-time interpreter.
+/// This is a packed representation of an `AllocId` and an `immutable: bool`.
+#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub struct CtfeProvenance(NonZeroU64);
+
+impl From<AllocId> for CtfeProvenance {
+ fn from(value: AllocId) -> Self {
+ let prov = CtfeProvenance(value.0);
+ assert!(!prov.immutable(), "`AllocId` with the highest bit set cannot be used in CTFE");
+ prov
+ }
+}
+
+impl fmt::Debug for CtfeProvenance {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&self.alloc_id(), f)?; // propagates `alternate` flag
+ if self.immutable() {
+ write!(f, "<imm>")?;
+ }
+ Ok(())
+ }
+}
+
+const IMMUTABLE_MASK: u64 = 1 << 63; // the highest bit
+
+impl CtfeProvenance {
+ /// Returns the `AllocId` of this provenance.
+ #[inline(always)]
+ pub fn alloc_id(self) -> AllocId {
+ AllocId(NonZeroU64::new(self.0.get() & !IMMUTABLE_MASK).unwrap())
+ }
+
+ /// Returns whether this provenance is immutable.
+ #[inline]
+ pub fn immutable(self) -> bool {
+ self.0.get() & IMMUTABLE_MASK != 0
+ }
+
+ /// Returns an immutable version of this provenance.
+ #[inline]
+ pub fn as_immutable(self) -> Self {
+ CtfeProvenance(self.0 | IMMUTABLE_MASK)
+ }
+}
+
+impl Provenance for CtfeProvenance {
+ // With the `AllocId` as provenance, the `offset` is interpreted *relative to the allocation*,
+ // so ptr-to-int casts are not possible (since we do not know the global physical offset).
+ const OFFSET_IS_ADDR: bool = false;
+
+ fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Print AllocId.
+ fmt::Debug::fmt(&ptr.provenance.alloc_id(), f)?; // propagates `alternate` flag
+ // Print offset only if it is non-zero.
+ if ptr.offset.bytes() > 0 {
+ write!(f, "+{:#x}", ptr.offset.bytes())?;
+ }
+ // Print immutable status.
+ if ptr.provenance.immutable() {
+ write!(f, "<imm>")?;
+ }
+ Ok(())
+ }
+
+ fn get_alloc_id(self) -> Option<AllocId> {
+ Some(self.alloc_id())
+ }
+
+ fn join(_left: Option<Self>, _right: Option<Self>) -> Option<Self> {
+ panic!("merging provenance is not supported when `OFFSET_IS_ADDR` is false")
+ }
+}
+
+// We also need this impl so that one can debug-print `Pointer<AllocId>`
impl Provenance for AllocId {
// With the `AllocId` as provenance, the `offset` is interpreted *relative to the allocation*,
// so ptr-to-int casts are not possible (since we do not know the global physical offset).
@@ -174,7 +233,7 @@ impl Provenance for AllocId {
/// Pointers are "tagged" with provenance information; typically the `AllocId` they belong to.
#[derive(Copy, Clone, Eq, PartialEq, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable)]
-pub struct Pointer<Prov = AllocId> {
+pub struct Pointer<Prov = CtfeProvenance> {
pub(super) offset: Size, // kept private to avoid accidental misinterpretation (meaning depends on `Prov` type)
pub provenance: Prov,
}
@@ -182,7 +241,7 @@ pub struct Pointer<Prov = AllocId> {
static_assert_size!(Pointer, 16);
// `Option<Prov>` pointers are also passed around quite a bit
// (but not stored in permanent machine state).
-static_assert_size!(Pointer<Option<AllocId>>, 16);
+static_assert_size!(Pointer<Option<CtfeProvenance>>, 16);
// We want the `Debug` output to be readable as it is used by `derive(Debug)` for
// all the Miri types.
@@ -215,7 +274,7 @@ impl<Prov: Provenance> fmt::Display for Pointer<Option<Prov>> {
impl From<AllocId> for Pointer {
#[inline(always)]
fn from(alloc_id: AllocId) -> Self {
- Pointer::new(alloc_id, Size::ZERO)
+ Pointer::new(alloc_id.into(), Size::ZERO)
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index fbf6403ea..092b59dee 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -110,10 +110,10 @@ impl<'tcx> TyCtxt<'tcx> {
let Some(local_def_id) = ct.def.as_local() else { return };
self.struct_span_lint_hir(
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
- self.hir().local_def_id_to_hir_id(local_def_id),
+ self.local_def_id_to_hir_id(local_def_id),
self.def_span(ct.def),
"cannot use constants which depend on generic parameters in types",
- |err| err,
+ |_| {},
)
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 0d548f886..5ecff04f3 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -11,7 +11,10 @@ use rustc_target::abi::{HasDataLayout, Size};
use crate::ty::ScalarInt;
-use super::{AllocId, InterpResult, Pointer, PointerArithmetic, Provenance, ScalarSizeMismatch};
+use super::{
+ AllocId, CtfeProvenance, InterpResult, Pointer, PointerArithmetic, Provenance,
+ ScalarSizeMismatch,
+};
/// A `Scalar` represents an immediate, primitive value existing outside of a
/// `memory::Allocation`. It is in many ways like a small chunk of an `Allocation`, up to 16 bytes in
@@ -22,7 +25,7 @@ use super::{AllocId, InterpResult, Pointer, PointerArithmetic, Provenance, Scala
/// Do *not* match on a `Scalar`! Use the various `to_*` methods instead.
#[derive(Clone, Copy, Eq, PartialEq, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable)]
-pub enum Scalar<Prov = AllocId> {
+pub enum Scalar<Prov = CtfeProvenance> {
/// The raw bytes of a simple value.
Int(ScalarInt),
@@ -267,6 +270,9 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Will perform ptr-to-int casts if needed and possible.
/// If that fails, we know the offset is relative, so we return an "erased" Scalar
/// (which is useful for error messages but not much else).
+ ///
+ /// The error type is `AllocId`, not `CtfeProvenance`, since `AllocId` is the "minimal"
+ /// component all provenance types must have.
#[inline]
pub fn try_to_int(self) -> Result<ScalarInt, Scalar<AllocId>> {
match self {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 7054cede2..1e5a7401c 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -736,6 +736,8 @@ impl SourceInfo {
rustc_index::newtype_index! {
#[derive(HashStable)]
+ #[encodable]
+ #[orderable]
#[debug_format = "_{}"]
pub struct Local {
const RETURN_PLACE = 0;
@@ -973,7 +975,7 @@ pub enum LocalInfo<'tcx> {
impl<'tcx> LocalDecl<'tcx> {
pub fn local_info(&self) -> &LocalInfo<'tcx> {
- &self.local_info.as_ref().assert_crate_local()
+ self.local_info.as_ref().assert_crate_local()
}
/// Returns `true` only if local is a binding that can itself be
@@ -1171,6 +1173,8 @@ rustc_index::newtype_index! {
/// [`CriticalCallEdges`]: ../../rustc_const_eval/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
/// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/
#[derive(HashStable)]
+ #[encodable]
+ #[orderable]
#[debug_format = "bb{}"]
pub struct BasicBlock {
const START_BLOCK = 0;
@@ -1305,6 +1309,7 @@ impl<'tcx> BasicBlockData<'tcx> {
rustc_index::newtype_index! {
#[derive(HashStable)]
+ #[encodable]
#[debug_format = "scope[{}]"]
pub struct SourceScope {
const OUTERMOST_SOURCE_SCOPE = 0;
@@ -1533,6 +1538,8 @@ impl UserTypeProjection {
rustc_index::newtype_index! {
#[derive(HashStable)]
+ #[encodable]
+ #[orderable]
#[debug_format = "promoted[{}]"]
pub struct Promoted {}
}
@@ -1611,14 +1618,29 @@ impl Location {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum DefLocation {
Argument,
- Body(Location),
+ Assignment(Location),
+ CallReturn { call: BasicBlock, target: Option<BasicBlock> },
}
impl DefLocation {
pub fn dominates(self, location: Location, dominators: &Dominators<BasicBlock>) -> bool {
match self {
DefLocation::Argument => true,
- DefLocation::Body(def) => def.successor_within_block().dominates(location, dominators),
+ DefLocation::Assignment(def) => {
+ def.successor_within_block().dominates(location, dominators)
+ }
+ DefLocation::CallReturn { target: None, .. } => false,
+ DefLocation::CallReturn { call, target: Some(target) } => {
+ // The definition occurs on the call -> target edge. The definition dominates a use
+ // if and only if the edge is on all paths from the entry to the use.
+ //
+ // Note that a call terminator has only one edge that can reach the target, so when
+ // the call strongly dominates the target, all paths from the entry to the target
+ // go through the call -> target edge.
+ call != target
+ && dominators.dominates(call, target)
+ && dominators.dominates(target, location.block)
+ }
}
}
}
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index eb4aa9eb9..b81e9fa1a 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -1,7 +1,4 @@
-use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::*;
-use rustc_middle::ty::Ty;
-use rustc_span::Span;
/// This struct represents a patch to MIR, which can add
/// new statements and basic blocks and patch over block
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index a13248584..071c6a755 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -1,23 +1,18 @@
use std::collections::BTreeSet;
-use std::fmt::{self, Debug, Display, Write as _};
+use std::fmt::{Display, Write as _};
use std::fs;
use std::io::{self, Write as _};
use std::path::{Path, PathBuf};
use super::graphviz::write_mir_fn_graphviz;
use super::spanview::write_mir_fn_spanview;
-use either::Either;
use rustc_ast::InlineAsmTemplatePiece;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::DefId;
-use rustc_index::Idx;
use rustc_middle::mir::interpret::{
- alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, ConstAllocation, GlobalAlloc,
- Pointer, Provenance,
+ alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer,
+ Provenance,
};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, *};
-use rustc_middle::ty::{self, TyCtxt};
use rustc_target::abi::Size;
const INDENT: &str = " ";
@@ -1337,13 +1332,13 @@ pub fn write_allocations<'tcx>(
fn alloc_ids_from_alloc(
alloc: ConstAllocation<'_>,
) -> impl DoubleEndedIterator<Item = AllocId> + '_ {
- alloc.inner().provenance().ptrs().values().map(|id| *id)
+ alloc.inner().provenance().ptrs().values().map(|p| p.alloc_id())
}
fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
match val {
ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => {
- Either::Left(std::iter::once(ptr.provenance))
+ Either::Left(std::iter::once(ptr.provenance.alloc_id()))
}
ConstValue::Scalar(interpret::Scalar::Int { .. }) => Either::Right(std::iter::empty()),
ConstValue::ZeroSized => Either::Right(std::iter::empty()),
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 0540eb0ef..98642adc1 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -27,7 +27,7 @@ pub enum UnsafetyViolationKind {
UnsafeFn,
}
-#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
+#[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
pub enum UnsafetyViolationDetails {
CallToUnsafeFunction,
UseOfInlineAssembly,
@@ -39,68 +39,17 @@ pub enum UnsafetyViolationDetails {
AccessToUnionField,
MutationOfLayoutConstrainedField,
BorrowOfLayoutConstrainedField,
- CallToFunctionWith,
+ CallToFunctionWith {
+ /// Target features enabled in callee's `#[target_feature]` but missing in
+ /// caller's `#[target_feature]`.
+ missing: Vec<Symbol>,
+ /// Target features in `missing` that are enabled at compile time
+ /// (e.g., with `-C target-feature`).
+ build_enabled: Vec<Symbol>,
+ },
}
-impl UnsafetyViolationDetails {
- pub fn description_and_note(&self) -> (&'static str, &'static str) {
- use UnsafetyViolationDetails::*;
- match self {
- CallToUnsafeFunction => (
- "call to unsafe function",
- "consult the function's documentation for information on how to avoid undefined \
- behavior",
- ),
- UseOfInlineAssembly => (
- "use of inline assembly",
- "inline assembly is entirely unchecked and can cause undefined behavior",
- ),
- InitializingTypeWith => (
- "initializing type with `rustc_layout_scalar_valid_range` attr",
- "initializing a layout restricted type's field with a value outside the valid \
- range is undefined behavior",
- ),
- CastOfPointerToInt => {
- ("cast of pointer to int", "casting pointers to integers in constants")
- }
- UseOfMutableStatic => (
- "use of mutable static",
- "mutable statics can be mutated by multiple threads: aliasing violations or data \
- races will cause undefined behavior",
- ),
- UseOfExternStatic => (
- "use of extern static",
- "extern statics are not controlled by the Rust type system: invalid data, \
- aliasing violations or data races will cause undefined behavior",
- ),
- DerefOfRawPointer => (
- "dereference of raw pointer",
- "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
- and cause data races: all of these are undefined behavior",
- ),
- AccessToUnionField => (
- "access to union field",
- "the field may not be properly initialized: using uninitialized data will cause \
- undefined behavior",
- ),
- MutationOfLayoutConstrainedField => (
- "mutation of layout constrained field",
- "mutating layout constrained fields cannot statically be checked for valid values",
- ),
- BorrowOfLayoutConstrainedField => (
- "borrow of layout constrained field with interior mutability",
- "references to fields of layout constrained fields lose the constraints. Coupled \
- with interior mutability, the field can be changed to invalid values",
- ),
- CallToFunctionWith => (
- "call to function with `#[target_feature]`",
- "can only be called if the required target features are available",
- ),
- }
- }
-}
-
-#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
+#[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
pub struct UnsafetyViolation {
pub source_info: SourceInfo,
pub lint_root: hir::HirId,
@@ -132,6 +81,7 @@ pub struct UnsafetyCheckResult {
rustc_index::newtype_index! {
#[derive(HashStable)]
+ #[encodable]
#[debug_format = "_{}"]
pub struct CoroutineSavedLocal {}
}
@@ -341,7 +291,11 @@ pub enum ConstraintCategory<'tcx> {
UseAsConst,
UseAsStatic,
TypeAnnotation,
- Cast,
+ Cast {
+ /// Whether this is an unsizing cast and if yes, this contains the target type.
+ /// Region variables are erased to ReErased.
+ unsize_to: Option<Ty<'tcx>>,
+ },
/// A constraint that came from checking the body of a closure.
///
@@ -416,7 +370,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
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 };
- ty::Region::new_late_bound(tcx, depth, br)
+ ty::Region::new_bound(tcx, depth, br)
}
_ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
});
@@ -430,7 +384,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>,
) -> Ty<'tcx> {
tcx.fold_regions(self.inner, |r, depth| match r.kind() {
- ty::ReLateBound(debruijn, br) => {
+ ty::ReBound(debruijn, br) => {
debug_assert_eq!(debruijn, depth);
map(ty::RegionVid::new(br.var.index()))
}
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index a5358687c..cb9fc0d37 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -1,9 +1,7 @@
-use rustc_hir::def_id::DefId;
use rustc_middle::hir;
use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
use rustc_session::config::MirSpanview;
-use rustc_span::{BytePos, Pos, Span};
+use rustc_span::{BytePos, Pos};
use std::cmp;
use std::io::{self, Write};
@@ -369,7 +367,7 @@ where
debug_indent, span, viewable.span
);
from_pos = span.hi();
- make_html_snippet(tcx, span, Some(&viewable))
+ make_html_snippet(tcx, span, Some(viewable))
} else {
None
};
@@ -439,7 +437,7 @@ where
tcx,
from_pos,
to_pos,
- &remaining_viewables,
+ remaining_viewables,
subalt,
layer + 1,
w,
@@ -472,7 +470,7 @@ where
"{}After overlaps, writing (end span?) {:?} of viewable.span {:?}",
debug_indent, span, viewable.span
);
- if let Some(ref html_snippet) = make_html_snippet(tcx, span, Some(&viewable)) {
+ if let Some(ref html_snippet) = make_html_snippet(tcx, span, Some(viewable)) {
from_pos = span.hi();
write_span(html_snippet, &viewable.tooltip, alt, layer, w)?;
}
@@ -507,11 +505,7 @@ fn write_span<W>(
where
W: Write,
{
- let maybe_alt_class = if layer > 0 {
- if alt { " odd" } else { " even" }
- } else {
- ""
- };
+ let maybe_alt_class = if layer > 0 { if alt { " odd" } else { " even" } } else { "" };
let maybe_title_attr = if !tooltip.is_empty() {
format!(" title=\"{}\"", escape_attr(tooltip))
} else {
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index 3471d620e..f929a5cec 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -159,7 +159,7 @@ impl<'tcx> Place<'tcx> {
#[inline]
pub fn as_ref(&self) -> PlaceRef<'tcx> {
- PlaceRef { local: self.local, projection: &self.projection }
+ PlaceRef { local: self.local, projection: self.projection }
}
/// Iterate over the projections in evaluation order, i.e., the first element is the base with
@@ -381,7 +381,7 @@ impl<'tcx> Operand<'tcx> {
impl<'tcx> ConstOperand<'tcx> {
pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
match self.const_.try_to_scalar() {
- Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) {
+ Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance.alloc_id()) {
GlobalAlloc::Static(def_id) => {
assert!(!tcx.is_thread_local_static(def_id));
Some(def_id)
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 7b0f27f9b..8cf9e55f0 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1404,18 +1404,18 @@ pub enum BinOp {
BitOr,
/// The `<<` operator (shift left)
///
- /// The offset is truncated to the size of the first operand before shifting.
+ /// The offset is truncated to the size of the first operand and made unsigned before shifting.
Shl,
- /// Like `Shl`, but is UB if the RHS >= LHS::BITS
+ /// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0
ShlUnchecked,
/// The `>>` operator (shift right)
///
- /// The offset is truncated to the size of the first operand before shifting.
+ /// The offset is truncated to the size of the first operand and made unsigned before shifting.
///
/// This is an arithmetic shift if the LHS is signed
/// and a logical shift if the LHS is unsigned.
Shr,
- /// Like `Shl`, but is UB if the RHS >= LHS::BITS
+ /// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0
ShrUnchecked,
/// The `==` operator (equality)
Eq,
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 6ab2da23a..f9b2a6ee8 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -4,9 +4,7 @@
*/
use crate::mir::*;
-use crate::ty::{self, Ty, TyCtxt};
use rustc_hir as hir;
-use rustc_target::abi::{FieldIdx, VariantIdx};
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct PlaceTy<'tcx> {
@@ -40,7 +38,7 @@ impl<'tcx> PlaceTy<'tcx> {
None => adt_def.non_enum_variant(),
Some(variant_index) => {
assert!(adt_def.is_enum());
- &adt_def.variant(variant_index)
+ adt_def.variant(variant_index)
}
};
let field_def = &variant_def.fields[f];
@@ -95,9 +93,7 @@ impl<'tcx> PlaceTy<'tcx> {
ProjectionElem::Subslice { from, to, from_end } => {
PlaceTy::from_ty(match self.ty.kind() {
ty::Slice(..) => self.ty,
- ty::Array(inner, _) if !from_end => {
- Ty::new_array(tcx, *inner, (to - from) as u64)
- }
+ ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from),
ty::Array(inner, size) if from_end => {
let size = size.eval_target_usize(tcx, param_env);
let len = size - from - to;
@@ -143,7 +139,7 @@ impl<'tcx> Place<'tcx> {
where
D: HasLocalDecls<'tcx>,
{
- Place::ty_from(self.local, &self.projection, local_decls, tcx)
+ Place::ty_from(self.local, self.projection, local_decls, tcx)
}
}
@@ -152,7 +148,7 @@ impl<'tcx> PlaceRef<'tcx> {
where
D: HasLocalDecls<'tcx>,
{
- Place::ty_from(self.local, &self.projection, local_decls, tcx)
+ Place::ty_from(self.local, self.projection, local_decls, tcx)
}
}
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 9dfbe1733..98e3a1f60 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -2,9 +2,8 @@
use rustc_hir::LangItem;
use smallvec::SmallVec;
-use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction};
+use super::TerminatorKind;
use rustc_macros::HashStable;
-use std::iter;
use std::slice;
use super::*;
@@ -28,7 +27,9 @@ impl SwitchTargets {
/// Inverse of `SwitchTargets::static_if`.
pub fn as_static_if(&self) -> Option<(u128, BasicBlock, BasicBlock)> {
- if let &[value] = &self.values[..] && let &[then, else_] = &self.targets[..] {
+ if let &[value] = &self.values[..]
+ && let &[then, else_] = &self.targets[..]
+ {
Some((value, then, else_))
} else {
None
@@ -148,11 +149,17 @@ impl<O> AssertKind<O> {
RemainderByZero(_) => "attempt to calculate the remainder with a divisor of zero",
ResumedAfterReturn(CoroutineKind::Coroutine) => "coroutine resumed after completion",
ResumedAfterReturn(CoroutineKind::Async(_)) => "`async fn` resumed after completion",
+ ResumedAfterReturn(CoroutineKind::AsyncGen(_)) => {
+ "`async gen fn` resumed after completion"
+ }
ResumedAfterReturn(CoroutineKind::Gen(_)) => {
"`gen fn` should just keep returning `None` after completion"
}
ResumedAfterPanic(CoroutineKind::Coroutine) => "coroutine resumed after panicking",
ResumedAfterPanic(CoroutineKind::Async(_)) => "`async fn` resumed after panicking",
+ ResumedAfterPanic(CoroutineKind::AsyncGen(_)) => {
+ "`async gen fn` resumed after panicking"
+ }
ResumedAfterPanic(CoroutineKind::Gen(_)) => {
"`gen fn` should just keep returning `None` after panicking"
}
@@ -243,6 +250,7 @@ impl<O> AssertKind<O> {
DivisionByZero(_) => middle_assert_divide_by_zero,
RemainderByZero(_) => middle_assert_remainder_by_zero,
ResumedAfterReturn(CoroutineKind::Async(_)) => middle_assert_async_resume_after_return,
+ ResumedAfterReturn(CoroutineKind::AsyncGen(_)) => todo!(),
ResumedAfterReturn(CoroutineKind::Gen(_)) => {
bug!("gen blocks can be resumed after they return and will keep returning `None`")
}
@@ -250,6 +258,7 @@ impl<O> AssertKind<O> {
middle_assert_coroutine_resume_after_return
}
ResumedAfterPanic(CoroutineKind::Async(_)) => middle_assert_async_resume_after_panic,
+ ResumedAfterPanic(CoroutineKind::AsyncGen(_)) => todo!(),
ResumedAfterPanic(CoroutineKind::Gen(_)) => middle_assert_gen_resume_after_panic,
ResumedAfterPanic(CoroutineKind::Coroutine) => {
middle_assert_coroutine_resume_after_panic
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index d5c81b6cd..93a9bbf64 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -3,7 +3,6 @@
use rustc_ast::InlineAsmTemplatePiece;
use super::*;
-use crate::ty;
TrivialTypeTraversalImpls! {
BlockTailInfo,
@@ -16,7 +15,6 @@ TrivialTypeTraversalImpls! {
UserTypeAnnotationIndex,
BorrowKind,
CastKind,
- hir::Movability,
BasicBlock,
SwitchTargets,
CoroutineKind,
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index d47cfd571..9059936f4 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -63,9 +63,7 @@
//! `is_cleanup` above.
use crate::mir::*;
-use crate::ty::GenericArgsRef;
-use crate::ty::{self, CanonicalUserTypeAnnotation, Ty};
-use rustc_span::Span;
+use crate::ty::CanonicalUserTypeAnnotation;
macro_rules! make_mir_visitor {
($visitor_trait_name:ident, $($mutability:ident)?) => {
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index cdde6a596..b9200f1ab 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -264,6 +264,7 @@ trivial! {
rustc_middle::middle::stability::DeprecationEntry,
rustc_middle::mir::ConstQualifs,
rustc_middle::mir::interpret::AllocId,
+ rustc_middle::mir::interpret::CtfeProvenance,
rustc_middle::mir::interpret::ErrorHandled,
rustc_middle::mir::interpret::LitToConstError,
rustc_middle::thir::ExprId,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index f9ec36836..3a54f5f6b 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -61,7 +61,6 @@ 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;
-use rustc_data_structures::sync::WorkerLocal;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
@@ -70,7 +69,7 @@ use rustc_hir::def_id::{
CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId,
};
use rustc_hir::lang_items::{LangItem, LanguageItems};
-use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
+use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, TraitCandidate};
use rustc_index::IndexVec;
use rustc_query_system::ich::StableHashingContext;
use rustc_query_system::query::{try_get_cached, CacheSelector, QueryCache, QueryMode, QueryState};
@@ -109,10 +108,12 @@ pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsure, TyCtxtEnsureWithValue
// Queries marked with `fatal_cycle` do not need the latter implementation,
// as they will raise an fatal error on query cycles instead.
rustc_queries! {
- query trigger_delay_span_bug(key: DefId) -> () {
- desc { "triggering a delay span bug" }
+ /// This exists purely for testing the interactions between span_delayed_bug and incremental.
+ query trigger_span_delayed_bug(key: DefId) -> () {
+ desc { "triggering a span delayed bug for testing incremental" }
}
+ /// Collects the list of all tools registered using `#![register_tool]`.
query registered_tools(_: ()) -> &'tcx ty::RegisteredTools {
arena_cache
desc { "compute registered tools for crate" }
@@ -286,6 +287,7 @@ rustc_queries! {
}
}
+ /// The root query triggering all analysis passes like typeck or borrowck.
query analysis(key: ()) -> Result<(), ErrorGuaranteed> {
eval_always
desc { "running analysis passes on this crate" }
@@ -564,7 +566,7 @@ rustc_queries! {
separate_provide_extern
}
- query check_coroutine_obligations(key: LocalDefId) {
+ query check_coroutine_obligations(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
desc { |tcx| "verify auto trait bounds for coroutine interior type `{}`", tcx.def_path_str(key) }
}
@@ -1149,7 +1151,7 @@ rustc_queries! {
cache_on_disk_if { true }
}
- query opt_def_kind(def_id: DefId) -> Option<DefKind> {
+ query def_kind(def_id: DefId) -> DefKind {
desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
@@ -1488,7 +1490,7 @@ rustc_queries! {
desc { "computing whether impls specialize one another" }
}
query in_scope_traits_map(_: hir::OwnerId)
- -> Option<&'tcx FxHashMap<ItemLocalId, Box<[TraitCandidate]>>> {
+ -> Option<&'tcx ItemLocalMap<Box<[TraitCandidate]>>> {
desc { "getting traits in scope at a block" }
}
@@ -1732,13 +1734,10 @@ rustc_queries! {
desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id) }
}
- query lib_features(_: ()) -> &'tcx LibFeatures {
- arena_cache
- desc { "calculating the lib features map" }
- }
- query defined_lib_features(_: CrateNum) -> &'tcx [(Symbol, Option<Symbol>)] {
+ query lib_features(_: CrateNum) -> &'tcx LibFeatures {
desc { "calculating the lib features defined in a crate" }
separate_provide_extern
+ arena_cache
}
query stability_implications(_: CrateNum) -> &'tcx FxHashMap<Symbol, Symbol> {
arena_cache
@@ -1781,10 +1780,17 @@ rustc_queries! {
desc { "calculating the missing lang items in a crate" }
separate_provide_extern
}
+
+ /// The visible parent map is a map from every item to a visible parent.
+ /// It prefers the shortest visible path to an item.
+ /// Used for diagnostics, for example path trimming.
+ /// The parents are modules, enums or traits.
query visible_parent_map(_: ()) -> &'tcx DefIdMap<DefId> {
arena_cache
desc { "calculating the visible parent map" }
}
+ /// Collects the "trimmed", shortest accessible paths to all items for diagnostics.
+ /// See the [provider docs](`rustc_middle::ty::print::trimmed_def_paths`) for more info.
query trimmed_def_paths(_: ()) -> &'tcx FxHashMap<DefId, Symbol> {
arena_cache
desc { "calculating trimmed def paths" }
@@ -2171,7 +2177,9 @@ 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 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> {
+ query check_tys_might_be_eq(
+ arg: Canonical<'tcx, ty::ParamEnvAnd<'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/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 280f5d0a8..f37cfe8b0 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -25,7 +25,6 @@ use rustc_span::source_map::{SourceMap, StableSourceFileId};
use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span};
use rustc_span::{CachingSourceMapView, Symbol};
use std::collections::hash_map::Entry;
-use std::io;
use std::mem;
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
@@ -246,7 +245,7 @@ impl<'sess> OnDiskCache<'sess> {
let index = SourceFileIndex(index as u32);
let file_ptr: *const SourceFile = &**file as *const _;
file_to_file_index.insert(file_ptr, index);
- let source_file_id = EncodedSourceFileId::new(tcx, &file);
+ let source_file_id = EncodedSourceFileId::new(tcx, file);
file_index_to_stable_id.insert(index, source_file_id);
}
@@ -482,13 +481,8 @@ pub struct CacheDecoder<'a, 'tcx> {
impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
#[inline]
fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> {
- let CacheDecoder {
- tcx,
- ref file_index_to_file,
- ref file_index_to_stable_id,
- ref source_map,
- ..
- } = *self;
+ let CacheDecoder { tcx, file_index_to_file, file_index_to_stable_id, source_map, .. } =
+ *self;
file_index_to_file
.borrow_mut()
@@ -867,7 +861,7 @@ impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
}
#[inline]
- fn finish(self) -> Result<usize, io::Error> {
+ fn finish(mut self) -> FileEncodeResult {
self.encoder.finish()
}
}
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index f4a8ada8f..0d1f3c1f8 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -11,7 +11,7 @@ use field_offset::FieldOffset;
use measureme::StringId;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::AtomicU64;
-use rustc_hir::def::DefKind;
+use rustc_data_structures::sync::WorkerLocal;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::hir_id::OwnerId;
use rustc_query_system::dep_graph::DepNodeIndex;
@@ -71,7 +71,7 @@ pub struct QuerySystemFns<'tcx> {
pub struct QuerySystem<'tcx> {
pub states: QueryStates<'tcx>,
- pub arenas: QueryArenas<'tcx>,
+ pub arenas: WorkerLocal<QueryArenas<'tcx>>,
pub caches: QueryCaches<'tcx>,
pub dynamic_queries: DynamicQueries<'tcx>,
@@ -370,7 +370,7 @@ macro_rules! define_callbacks {
pub struct QueryArenas<'tcx> {
$($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*]
- (WorkerLocal<TypedArena<<$V as Deref>::Target>>)
+ (TypedArena<<$V as Deref>::Target>)
()
),)*
}
@@ -379,7 +379,7 @@ macro_rules! define_callbacks {
fn default() -> Self {
Self {
$($name: query_if_arena!([$($modifiers)*]
- (WorkerLocal::new(|_| Default::default()))
+ (Default::default())
()
),)*
}
@@ -551,7 +551,7 @@ macro_rules! define_feedable {
// We have an inconsistency. This can happen if one of the two
// results is tainted by errors. In this case, delay a bug to
// ensure compilation is doomed, and keep the `old` value.
- tcx.sess.delay_span_bug(DUMMY_SP, format!(
+ tcx.sess.span_delayed_bug(DUMMY_SP, format!(
"Trying to feed an already recorded value for query {} key={key:?}:\n\
old value: {old:?}\nnew value: {value:?}",
stringify!($name),
@@ -667,21 +667,5 @@ mod sealed {
pub use sealed::IntoQueryParam;
-impl<'tcx> TyCtxt<'tcx> {
- pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
- let def_id = def_id.into_query_param();
- self.opt_def_kind(def_id)
- .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
- }
-}
-
-impl<'tcx> TyCtxtAt<'tcx> {
- pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
- let def_id = def_id.into_query_param();
- self.opt_def_kind(def_id)
- .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
- }
-}
-
#[derive(Copy, Clone, Debug, HashStable)]
pub struct CyclePlaceholder(pub ErrorGuaranteed);
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 3086082fe..b6759d352 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -134,7 +134,6 @@ pub struct Block {
/// This does *not* include labels on loops, e.g. `'label: loop {}`.
pub targeted_by_break: bool,
pub region_scope: region::Scope,
- pub opt_destruction_scope: Option<region::Scope>,
/// The span of the block, including the opening braces,
/// the label, and the `unsafe` keyword, if present.
pub span: Span,
@@ -193,7 +192,6 @@ pub enum BlockSafety {
#[derive(Clone, Debug, HashStable)]
pub struct Stmt<'tcx> {
pub kind: StmtKind<'tcx>,
- pub opt_destruction_scope: Option<region::Scope>,
}
#[derive(Clone, Debug, HashStable)]
@@ -635,7 +633,12 @@ impl<'tcx> Pat<'tcx> {
use PatKind::*;
match &self.kind {
- Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } | Error(_) => {}
+ Wild
+ | Never
+ | Range(..)
+ | Binding { subpattern: None, .. }
+ | Constant { .. }
+ | Error(_) => {}
AscribeUserType { subpattern, .. }
| Binding { subpattern: Some(subpattern), .. }
| Deref { subpattern }
@@ -655,7 +658,9 @@ impl<'tcx> Pat<'tcx> {
pub fn pat_error_reported(&self) -> Result<(), ErrorGuaranteed> {
let mut error = None;
self.walk(|pat| {
- if let PatKind::Error(e) = pat.kind && error.is_none() {
+ if let PatKind::Error(e) = pat.kind
+ && error.is_none()
+ {
error = Some(e);
}
error.is_none()
@@ -807,6 +812,9 @@ pub enum PatKind<'tcx> {
pats: Box<[Box<Pat<'tcx>>]>,
},
+ /// A never pattern `!`.
+ Never,
+
/// An error has been encountered during lowering. We probably shouldn't report more lints
/// related to this pattern.
Error(ErrorGuaranteed),
@@ -1067,6 +1075,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
match self.kind {
PatKind::Wild => write!(f, "_"),
+ PatKind::Never => write!(f, "!"),
PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{subpattern}: _"),
PatKind::Binding { mutability, name, mode, ref subpattern, .. } => {
let is_mut = match mode {
@@ -1213,12 +1222,12 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
mod size_asserts {
use super::*;
// tidy-alphabetical-start
- static_assert_size!(Block, 56);
+ static_assert_size!(Block, 48);
static_assert_size!(Expr<'_>, 64);
static_assert_size!(ExprKind<'_>, 40);
static_assert_size!(Pat<'_>, 64);
static_assert_size!(PatKind<'_>, 48);
- static_assert_size!(Stmt<'_>, 56);
+ static_assert_size!(Stmt<'_>, 48);
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 8feefb4c0..4943c1184 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -226,8 +226,8 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'
ty: _,
is_primary: _,
name: _,
- } => visitor.visit_pat(&subpattern),
- Binding { .. } | Wild | Error(_) => {}
+ } => visitor.visit_pat(subpattern),
+ Binding { .. } | Wild | Never | Error(_) => {}
Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => {
for subpattern in subpatterns {
visitor.visit_pat(&subpattern.pattern);
@@ -249,7 +249,7 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'
}
Or { pats } => {
for pat in pats.iter() {
- visitor.visit_pat(&pat);
+ visitor.visit_pat(pat);
}
}
};
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 6cd75e087..5d0187a85 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -250,9 +250,6 @@ pub enum ObligationCauseCode<'tcx> {
/// A tuple is WF only if its middle elements are `Sized`.
TupleElem,
- /// This is the trait reference from the given projection.
- ProjectionWf(ty::AliasTy<'tcx>),
-
/// Must satisfy all of the where-clause predicates of the
/// given item.
ItemObligation(DefId),
@@ -343,7 +340,8 @@ pub enum ObligationCauseCode<'tcx> {
parent_code: InternedObligationCauseCode<'tcx>,
},
- /// Error derived when matching traits/impls; see ObligationCause for more details
+ /// Error derived when checking an impl item is compatible with
+ /// its corresponding trait item's definition
CompareImplItemObligation {
impl_item_def_id: LocalDefId,
trait_item_def_id: DefId,
@@ -372,9 +370,6 @@ pub enum ObligationCauseCode<'tcx> {
origin_expr: bool,
},
- /// Constants in patterns must have `Structural` type.
- ConstPatternStructural,
-
/// Computing common supertype in an if expression
IfExpression(Box<IfExpressionCause<'tcx>>),
@@ -407,9 +402,6 @@ pub enum ObligationCauseCode<'tcx> {
/// `return` with an expression
ReturnValue(hir::HirId),
- /// Return type of this function
- ReturnType,
-
/// Opaque return type of this function
OpaqueReturnType(Option<(Ty<'tcx>, Span)>),
@@ -419,10 +411,7 @@ pub enum ObligationCauseCode<'tcx> {
/// #[feature(trivial_bounds)] is not enabled
TrivialBound,
- /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y`
- OpaqueType,
-
- AwaitableExpr(Option<hir::HirId>),
+ AwaitableExpr(hir::HirId),
ForLoopIterator,
@@ -686,7 +675,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
pub fn borrow_nested_obligations(&self) -> &[N] {
match self {
ImplSource::UserDefined(i) => &i.nested,
- ImplSource::Param(n) | ImplSource::Builtin(_, n) => &n,
+ ImplSource::Param(n) | ImplSource::Builtin(_, n) => n,
}
}
@@ -843,50 +832,31 @@ impl ObjectSafetyViolation {
}
}
- pub fn solution(&self, err: &mut Diagnostic) {
+ pub fn solution(&self) -> ObjectSafetyViolationSolution {
match self {
ObjectSafetyViolation::SizedSelf(_)
| ObjectSafetyViolation::SupertraitSelf(_)
- | ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => {}
+ | ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => {
+ ObjectSafetyViolationSolution::None
+ }
ObjectSafetyViolation::Method(
name,
MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
_,
- ) => {
- err.span_suggestion(
- add_self_sugg.1,
- format!(
- "consider turning `{name}` into a method by giving it a `&self` argument"
- ),
- add_self_sugg.0.to_string(),
- Applicability::MaybeIncorrect,
- );
- err.span_suggestion(
- make_sized_sugg.1,
- format!(
- "alternatively, consider constraining `{name}` so it does not apply to \
- trait objects"
- ),
- make_sized_sugg.0.to_string(),
- Applicability::MaybeIncorrect,
- );
- }
+ ) => ObjectSafetyViolationSolution::AddSelfOrMakeSized {
+ name: *name,
+ add_self_sugg: add_self_sugg.clone(),
+ make_sized_sugg: make_sized_sugg.clone(),
+ },
ObjectSafetyViolation::Method(
name,
MethodViolationCode::UndispatchableReceiver(Some(span)),
_,
- ) => {
- err.span_suggestion(
- *span,
- format!("consider changing method `{name}`'s `self` parameter to be `&self`"),
- "&Self",
- Applicability::MachineApplicable,
- );
- }
+ ) => ObjectSafetyViolationSolution::ChangeToRefSelf(*name, *span),
ObjectSafetyViolation::AssocConst(name, _)
| ObjectSafetyViolation::GAT(name, _)
| ObjectSafetyViolation::Method(name, ..) => {
- err.help(format!("consider moving `{name}` to another trait"));
+ ObjectSafetyViolationSolution::MoveToAnotherTrait(*name)
}
}
}
@@ -910,6 +880,60 @@ impl ObjectSafetyViolation {
}
}
+#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum ObjectSafetyViolationSolution {
+ None,
+ AddSelfOrMakeSized {
+ name: Symbol,
+ add_self_sugg: (String, Span),
+ make_sized_sugg: (String, Span),
+ },
+ ChangeToRefSelf(Symbol, Span),
+ MoveToAnotherTrait(Symbol),
+}
+
+impl ObjectSafetyViolationSolution {
+ pub fn add_to(self, err: &mut Diagnostic) {
+ match self {
+ ObjectSafetyViolationSolution::None => {}
+ ObjectSafetyViolationSolution::AddSelfOrMakeSized {
+ name,
+ add_self_sugg,
+ make_sized_sugg,
+ } => {
+ err.span_suggestion(
+ add_self_sugg.1,
+ format!(
+ "consider turning `{name}` into a method by giving it a `&self` argument"
+ ),
+ add_self_sugg.0,
+ Applicability::MaybeIncorrect,
+ );
+ err.span_suggestion(
+ make_sized_sugg.1,
+ format!(
+ "alternatively, consider constraining `{name}` so it does not apply to \
+ trait objects"
+ ),
+ make_sized_sugg.0,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ ObjectSafetyViolationSolution::ChangeToRefSelf(name, span) => {
+ err.span_suggestion(
+ span,
+ format!("consider changing method `{name}`'s `self` parameter to be `&self`"),
+ "&Self",
+ Applicability::MachineApplicable,
+ );
+ }
+ ObjectSafetyViolationSolution::MoveToAnotherTrait(name) => {
+ err.help(format!("consider moving `{name}` to another trait"));
+ }
+ }
+ }
+}
+
/// Reasons a method might not be object-safe.
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
pub enum MethodViolationCode {
@@ -956,13 +980,26 @@ pub enum CodegenObligationError {
FulfillmentError,
}
+/// Defines the treatment of opaque types in a given inference context.
+///
+/// This affects both what opaques are allowed to be defined, but also whether
+/// opaques are replaced with inference vars eagerly in the old solver (e.g.
+/// in projection, and in the signature during function type-checking).
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
pub enum DefiningAnchor {
- /// `DefId` of the item.
+ /// Define opaques which are in-scope of the `LocalDefId`. Also, eagerly
+ /// replace opaque types in `replace_opaque_types_with_inference_vars`.
Bind(LocalDefId),
- /// When opaque types are not resolved, we `Bubble` up, meaning
- /// return the opaque/hidden type pair from query, for caller of query to handle it.
+ /// In contexts where we don't currently know what opaques are allowed to be
+ /// defined, such as (old solver) canonical queries, we will simply allow
+ /// opaques to be defined, but "bubble" them up in the canonical response or
+ /// otherwise treat them to be handled later.
+ ///
+ /// We do not eagerly replace opaque types in `replace_opaque_types_with_inference_vars`,
+ /// which may affect what predicates pass and fail in the old trait solver.
Bubble,
- /// Used to catch type mismatch errors when handling opaque types.
+ /// Do not allow any opaques to be defined. This is used to catch type mismatch
+ /// errors when handling opaque types, and also should be used when we would
+ /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode).
Error,
}
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 3cceb8b2c..34c56eb0d 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -108,17 +108,6 @@ impl<'tcx> DropckOutlivesResult<'tcx> {
tcx.sess.emit_err(DropCheckOverflow { span, ty, overflow_ty: *overflow_ty });
}
}
-
- pub fn into_kinds_reporting_overflows(
- self,
- tcx: TyCtxt<'tcx>,
- span: Span,
- ty: Ty<'tcx>,
- ) -> Vec<GenericArg<'tcx>> {
- self.report_overflows(tcx, span, ty);
- let DropckOutlivesResult { kinds, overflows: _ } = self;
- kinds
- }
}
/// A set of constraints that need to be satisfied in order for
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index f33421bba..734c2b61c 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -125,10 +125,8 @@ pub enum SelectionCandidate<'tcx> {
/// This is a trait matching with a projected type as `Self`, and we found
/// an applicable bound in the trait definition. The `usize` is an index
- /// into the list returned by `tcx.item_bounds`. The constness is the
- /// constness of the bound in the trait.
- // FIXME(effects) do we need this constness
- ProjectionCandidate(usize, ty::BoundConstness),
+ /// into the list returned by `tcx.item_bounds`.
+ ProjectionCandidate(usize),
/// Implementation of a `Fn`-family trait by one of the anonymous types
/// generated for an `||` expression.
@@ -144,14 +142,18 @@ pub enum SelectionCandidate<'tcx> {
/// generated for an async construct.
FutureCandidate,
- /// Implementation of an `Iterator` trait by one of the generator types
- /// generated for a gen construct.
+ /// Implementation of an `Iterator` trait by one of the coroutine types
+ /// generated for a `gen` construct.
IteratorCandidate,
+ /// Implementation of an `AsyncIterator` trait by one of the coroutine types
+ /// generated for a `async gen` construct.
+ AsyncIteratorCandidate,
+
/// Implementation of a `Fn`-family trait by one of the anonymous
/// types generated for a fn pointer type (e.g., `fn(int) -> int`)
FnPointerCandidate {
- is_const: bool,
+ fn_host_effect: ty::Const<'tcx>,
},
TraitAliasCandidate,
@@ -180,8 +182,8 @@ pub enum SelectionCandidate<'tcx> {
///
/// The evaluation results are ordered:
/// - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions`
-/// implies `EvaluatedToAmbig` implies `EvaluatedToUnknown`
-/// - `EvaluatedToErr` implies `EvaluatedToRecur`
+/// implies `EvaluatedToAmbig` implies `EvaluatedToAmbigStackDependent`
+/// - `EvaluatedToErr` implies `EvaluatedToErrStackDependent`
/// - the "union" of evaluation results is equal to their maximum -
/// all the "potential success" candidates can potentially succeed,
/// so they are noops when unioned with a definite error, and within
@@ -199,7 +201,7 @@ pub enum EvaluationResult {
/// Evaluation is known to be ambiguous -- it *might* hold for some
/// assignment of inference variables, but it might not.
///
- /// While this has the same meaning as `EvaluatedToUnknown` -- we can't
+ /// While this has the same meaning as `EvaluatedToAmbigStackDependent` -- we can't
/// know whether this obligation holds or not -- it is the result we
/// would get with an empty stack, and therefore is cacheable.
EvaluatedToAmbig,
@@ -207,8 +209,8 @@ pub enum EvaluationResult {
/// variables. We are somewhat imprecise there, so we don't actually
/// know the real result.
///
- /// This can't be trivially cached for the same reason as `EvaluatedToRecur`.
- EvaluatedToUnknown,
+ /// This can't be trivially cached for the same reason as `EvaluatedToErrStackDependent`.
+ EvaluatedToAmbigStackDependent,
/// Evaluation failed because we encountered an obligation we are already
/// trying to prove on this branch.
///
@@ -247,12 +249,12 @@ pub enum EvaluationResult {
/// does not hold, because of the bound (which can indeed be satisfied
/// by `SomeUnsizedType` from another crate).
//
- // FIXME: when an `EvaluatedToRecur` goes past its parent root, we
+ // FIXME: when an `EvaluatedToErrStackDependent` goes past its parent root, we
// ought to convert it to an `EvaluatedToErr`, because we know
// there definitely isn't a proof tree for that obligation. Not
// doing so is still sound -- there isn't any proof tree, so the
// branch still can't be a part of a minimal one -- but does not re-enable caching.
- EvaluatedToRecur,
+ EvaluatedToErrStackDependent,
/// Evaluation failed.
EvaluatedToErr,
}
@@ -276,15 +278,15 @@ impl EvaluationResult {
| EvaluatedToOk
| EvaluatedToOkModuloRegions
| EvaluatedToAmbig
- | EvaluatedToUnknown => true,
+ | EvaluatedToAmbigStackDependent => true,
- EvaluatedToErr | EvaluatedToRecur => false,
+ EvaluatedToErr | EvaluatedToErrStackDependent => false,
}
}
pub fn is_stack_dependent(self) -> bool {
match self {
- EvaluatedToUnknown | EvaluatedToRecur => true,
+ EvaluatedToAmbigStackDependent | EvaluatedToErrStackDependent => true,
EvaluatedToOkModuloOpaqueTypes
| EvaluatedToOk
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index 27a1e64a7..048df367b 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -233,6 +233,27 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
}
}
+/// Why a specific goal has to be proven.
+///
+/// This is necessary as we treat nested goals different depending on
+/// their source.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum GoalSource {
+ Misc,
+ /// We're proving a where-bound of an impl.
+ ///
+ /// FIXME(-Znext-solver=coinductive): Explain how and why this
+ /// changes whether cycles are coinductive.
+ ///
+ /// This also impacts whether we erase constraints on overflow.
+ /// Erasing constraints is generally very useful for perf and also
+ /// results in better error messages by avoiding spurious errors.
+ /// We do not erase overflow constraints in `normalizes-to` goals unless
+ /// they are from an impl where-clause. This is necessary due to
+ /// backwards compatability, cc trait-system-refactor-initiatitive#70.
+ ImplWhereBound,
+}
+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
pub enum IsNormalizesToHack {
Yes,
diff --git a/compiler/rustc_middle/src/traits/solve/cache.rs b/compiler/rustc_middle/src/traits/solve/cache.rs
index e9e9cc418..4f90af0a2 100644
--- a/compiler/rustc_middle/src/traits/solve/cache.rs
+++ b/compiler/rustc_middle/src/traits/solve/cache.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::sync::Lock;
use rustc_query_system::cache::WithDepNode;
use rustc_query_system::dep_graph::DepNodeIndex;
use rustc_session::Limit;
-/// The trait solver cache used by `-Ztrait-solver=next`.
+/// The trait solver cache used by `-Znext-solver`.
///
/// FIXME(@lcnr): link to some official documentation of how
/// this works.
diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs
index a5916c4ab..77d112d0a 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect.rs
@@ -19,8 +19,8 @@
//! [canonicalized]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
use super::{
- CandidateSource, Canonical, CanonicalInput, Certainty, Goal, IsNormalizesToHack, NoSolution,
- QueryInput, QueryResult,
+ CandidateSource, Canonical, CanonicalInput, Certainty, Goal, GoalSource, IsNormalizesToHack,
+ NoSolution, QueryInput, QueryResult,
};
use crate::{infer::canonical::CanonicalVarValues, ty};
use format::ProofTreeFormatter;
@@ -115,13 +115,15 @@ impl Debug for Probe<'_> {
pub enum ProbeStep<'tcx> {
/// We added a goal to the `EvalCtxt` which will get proven
/// the next time `EvalCtxt::try_evaluate_added_goals` is called.
- AddGoal(CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>),
+ AddGoal(GoalSource, CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>),
/// The inside of a `EvalCtxt::try_evaluate_added_goals` call.
EvaluateGoals(AddedGoalsEvaluation<'tcx>),
/// A call to `probe` while proving the current goal. This is
/// used whenever there are multiple candidates to prove the
/// current goalby .
NestedProbe(Probe<'tcx>),
+ CommitIfOkStart,
+ CommitIfOkSuccess,
}
/// What kind of probe we're in. In case the probe represents a candidate, or
@@ -142,6 +144,9 @@ pub enum ProbeKind<'tcx> {
/// Used in the probe that wraps normalizing the non-self type for the unsize
/// trait, which is also structurally matched on.
UnsizeAssembly,
+ /// A call to `EvalCtxt::commit_if_ok` which failed, causing the work
+ /// to be discarded.
+ CommitIfOk,
/// During upcasting from some source object to target object type, used to
/// do a probe to find out what projection type(s) may be used to prove that
/// the source type upholds all of the target type's object bounds.
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index 4b73d8e41..4e2207ed5 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -109,6 +109,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
ProbeKind::UpcastProjectionCompatibility => {
writeln!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:")
}
+ ProbeKind::CommitIfOk => {
+ writeln!(self.f, "COMMIT_IF_OK:")
+ }
ProbeKind::MiscCandidate { name, result } => {
writeln!(self.f, "CANDIDATE {name}: {result:?}")
}
@@ -120,9 +123,17 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
self.nested(|this| {
for step in &probe.steps {
match step {
- ProbeStep::AddGoal(goal) => writeln!(this.f, "ADDED GOAL: {goal:?}")?,
+ ProbeStep::AddGoal(source, goal) => {
+ let source = match source {
+ GoalSource::Misc => "misc",
+ GoalSource::ImplWhereBound => "impl where-bound",
+ };
+ writeln!(this.f, "ADDED GOAL ({source}): {goal:?}")?
+ }
ProbeStep::EvaluateGoals(eval) => this.format_added_goals_evaluation(eval)?,
ProbeStep::NestedProbe(probe) => this.format_probe(probe)?,
+ ProbeStep::CommitIfOkStart => writeln!(this.f, "COMMIT_IF_OK START")?,
+ ProbeStep::CommitIfOkSuccess => writeln!(this.f, "COMMIT_IF_OK SUCCESS")?,
}
}
Ok(())
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index e48b46d12..6db427064 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -72,7 +72,7 @@ impl OverlapMode {
.as_local()
.into_iter()
.flat_map(|local_def_id| {
- tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(local_def_id))
+ tcx.hir().attrs(tcx.local_def_id_to_hir_id(local_def_id))
})
.find(|attr| attr.has_name(sym::rustc_strict_coherence))
.map(|attr| attr.span);
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index 85181720d..a2794a100 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -20,12 +20,11 @@ use crate::ty::{self, InferConst, Ty, TyCtxt};
/// affects any type variables or unification state.
pub struct MatchAgainstFreshVars<'tcx> {
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
}
impl<'tcx> MatchAgainstFreshVars<'tcx> {
- pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> MatchAgainstFreshVars<'tcx> {
- MatchAgainstFreshVars { tcx, param_env }
+ pub fn new(tcx: TyCtxt<'tcx>) -> MatchAgainstFreshVars<'tcx> {
+ MatchAgainstFreshVars { tcx }
}
}
@@ -33,13 +32,11 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> {
fn tag(&self) -> &'static str {
"MatchAgainstFreshVars"
}
+
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env
- }
fn a_is_expected(&self) -> bool {
true
} // irrelevant
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index f50969dd9..1d9a25628 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -99,7 +99,7 @@ pub struct AdtDefData {
impl PartialOrd for AdtDefData {
fn partial_cmp(&self, other: &AdtDefData) -> Option<Ordering> {
- Some(self.cmp(&other))
+ Some(self.cmp(other))
}
}
@@ -375,7 +375,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(FIRST_VARIANT)
+ self.variant(FIRST_VARIANT)
}
#[inline]
@@ -481,7 +481,7 @@ impl<'tcx> AdtDef<'tcx> {
ErrorHandled::Reported(..) => "enum discriminant evaluation failed",
ErrorHandled::TooGeneric(..) => "enum discriminant depends on generics",
};
- tcx.sess.delay_span_bug(tcx.def_span(expr_did), msg);
+ tcx.sess.span_delayed_bug(tcx.def_span(expr_did), msg);
None
}
}
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 74bdd07a1..8c29bc5a4 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -7,14 +7,13 @@ use std::fmt::Write;
use crate::query::Providers;
use rustc_data_structures::fx::FxIndexMap;
-use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::{self as hir, LangItem};
+use rustc_hir as hir;
+use rustc_hir::def_id::LocalDefId;
use rustc_span::def_id::LocalDefIdMap;
use rustc_span::symbol::Ident;
use rustc_span::{Span, Symbol};
-use super::{Ty, TyCtxt};
+use super::TyCtxt;
use self::BorrowKind::*;
@@ -73,72 +72,6 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<hir::HirId, MinCaptureLis
/// Part of `MinCaptureInformationMap`; List of `CapturePlace`s.
pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>;
-/// Represents the various closure traits in the language. This
-/// will determine the type of the environment (`self`, in the
-/// desugaring) argument that the closure expects.
-///
-/// You can get the environment type of a closure using
-/// `tcx.closure_env_ty()`.
-#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable)]
-pub enum ClosureKind {
- // Warning: Ordering is significant here! The ordering is chosen
- // because the trait Fn is a subtrait of FnMut and so in turn, and
- // hence we order it so that Fn < FnMut < FnOnce.
- Fn,
- FnMut,
- FnOnce,
-}
-
-impl ClosureKind {
- /// This is the initial value used when doing upvar inference.
- pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn;
-
- pub const fn as_str(self) -> &'static str {
- match self {
- ClosureKind::Fn => "Fn",
- ClosureKind::FnMut => "FnMut",
- ClosureKind::FnOnce => "FnOnce",
- }
- }
-
- /// Returns `true` if a type that impls this closure kind
- /// must also implement `other`.
- pub fn extends(self, other: ty::ClosureKind) -> bool {
- self <= other
- }
-
- /// Converts `self` to a [`DefId`] of the corresponding trait.
- ///
- /// Note: the inverse of this function is [`TyCtxt::fn_trait_kind_from_def_id`].
- pub fn to_def_id(&self, tcx: TyCtxt<'_>) -> DefId {
- tcx.require_lang_item(
- match self {
- ClosureKind::Fn => LangItem::Fn,
- ClosureKind::FnMut => LangItem::FnMut,
- ClosureKind::FnOnce => LangItem::FnOnce,
- },
- None,
- )
- }
-
- /// Returns the representative scalar type for this closure kind.
- /// See `Ty::to_opt_closure_kind` for more details.
- pub fn to_ty<'tcx>(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- match self {
- ClosureKind::Fn => tcx.types.i8,
- ClosureKind::FnMut => tcx.types.i16,
- ClosureKind::FnOnce => tcx.types.i32,
- }
- }
-}
-
-impl IntoDiagnosticArg for ClosureKind {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- DiagnosticArgValue::Str(self.as_str().into())
- }
-}
-
/// A composite describing a `Place` that is captured by a closure.
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
@@ -247,6 +180,13 @@ impl<'tcx> CapturedPlace<'tcx> {
.span
}
}
+
+ pub fn is_by_ref(&self) -> bool {
+ match self.info.capture_kind {
+ ty::UpvarCapture::ByValue => false,
+ ty::UpvarCapture::ByRef(..) => true,
+ }
+ }
}
#[derive(Copy, Clone, Debug, HashStable)]
@@ -262,7 +202,7 @@ fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo
let user_provided_sig = typeck_results.user_provided_sigs[&def];
let captures = typeck_results.closure_min_captures_flattened(def);
let captures = tcx.arena.alloc_from_iter(captures);
- let hir_id = tcx.hir().local_def_id_to_hir_id(def);
+ let hir_id = tcx.local_def_id_to_hir_id(def);
let kind_origin = typeck_results.closure_kind_origins().get(hir_id);
ClosureTypeInfo { user_provided_sig, captures, kind_origin }
}
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 8b67e3966..69ae05ca8 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -8,6 +8,7 @@
use crate::arena::ArenaAllocatable;
use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
+use crate::mir::interpret::CtfeProvenance;
use crate::mir::{
self,
interpret::{AllocId, ConstAllocation},
@@ -164,6 +165,13 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AllocId {
}
}
+impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for CtfeProvenance {
+ fn encode(&self, e: &mut E) {
+ self.alloc_id().encode(e);
+ self.immutable().encode(e);
+ }
+}
+
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::ParamEnv<'tcx> {
fn encode(&self, e: &mut E) {
self.caller_bounds().encode(e);
@@ -295,9 +303,18 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AllocId {
}
}
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for CtfeProvenance {
+ fn decode(decoder: &mut D) -> Self {
+ let alloc_id: AllocId = Decodable::decode(decoder);
+ let prov = CtfeProvenance::from(alloc_id);
+ let immutable: bool = Decodable::decode(decoder);
+ if immutable { prov.as_immutable() } else { prov }
+ }
+}
+
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::SymbolName<'tcx> {
fn decode(decoder: &mut D) -> Self {
- ty::SymbolName::new(decoder.interner(), &decoder.read_str())
+ ty::SymbolName::new(decoder.interner(), decoder.read_str())
}
}
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index af5ffc20d..2d3ee3348 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,5 +1,5 @@
use crate::middle::resolve_bound_vars as rbv;
-use crate::mir::interpret::{AllocId, ErrorHandled, LitToConstInput, Scalar};
+use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar};
use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
use rustc_data_structures::intern::Interned;
use rustc_error_messages::MultiSpan;
@@ -7,6 +7,7 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_macros::HashStable;
+use rustc_type_ir::{ConstTy, IntoKind, TypeFlags, WithCachedTypeInfo};
mod int;
mod kind;
@@ -23,10 +24,25 @@ use super::sty::ConstKind;
/// Use this rather than `ConstData`, whenever possible.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
#[rustc_pass_by_value]
-pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
+pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>);
+
+impl<'tcx> IntoKind for Const<'tcx> {
+ type Kind = ConstKind<'tcx>;
+
+ fn kind(self) -> ConstKind<'tcx> {
+ self.kind()
+ }
+}
+
+impl<'tcx> ConstTy<TyCtxt<'tcx>> for Const<'tcx> {
+ fn ty(self) -> Ty<'tcx> {
+ self.ty()
+ }
+}
/// Typed constant value.
-#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(HashStable, TyEncodable, TyDecodable)]
pub struct ConstData<'tcx> {
pub ty: Ty<'tcx>,
pub kind: ConstKind<'tcx>,
@@ -43,7 +59,17 @@ impl<'tcx> Const<'tcx> {
#[inline]
pub fn kind(self) -> ConstKind<'tcx> {
- self.0.kind.clone()
+ self.0.kind
+ }
+
+ #[inline]
+ pub fn flags(self) -> TypeFlags {
+ self.0.flags
+ }
+
+ #[inline]
+ pub fn outer_exclusive_binder(self) -> ty::DebruijnIndex {
+ self.0.outer_exclusive_binder
}
#[inline]
@@ -133,7 +159,7 @@ impl<'tcx> Const<'tcx> {
span: S,
msg: &'static str,
) -> Const<'tcx> {
- let reported = tcx.sess.delay_span_bug(span, msg);
+ let reported = tcx.sess.span_delayed_bug(span, msg);
Const::new_error(tcx, reported, ty)
}
@@ -141,7 +167,7 @@ impl<'tcx> Const<'tcx> {
/// becomes `Unevaluated`.
#[instrument(skip(tcx), level = "debug")]
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
- let body_id = match tcx.hir().get_by_def_id(def) {
+ let body_id = match tcx.hir_node_by_def_id(def) {
hir::Node::AnonConst(ac) => ac.body,
_ => span_bug!(
tcx.def_span(def.to_def_id()),
@@ -183,11 +209,9 @@ impl<'tcx> Const<'tcx> {
};
let lit_input = match expr.kind {
- hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
- hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
- hir::ExprKind::Lit(ref lit) => {
- Some(LitToConstInput { lit: &lit.node, ty, neg: true })
- }
+ hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
+ hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
+ hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
_ => None,
},
_ => None,
@@ -199,7 +223,7 @@ impl<'tcx> Const<'tcx> {
match tcx.at(expr.span).lit_to_const(lit_input) {
Ok(c) => return Some(c),
Err(e) => {
- tcx.sess.delay_span_bug(
+ tcx.sess.span_delayed_bug(
expr.span,
format!("Const::from_anon_const: couldn't lit_to_const {e:?}"),
);
@@ -207,6 +231,10 @@ impl<'tcx> Const<'tcx> {
}
}
+ // FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
+ // does not provide the parents generics to anonymous constants. We still allow generic const
+ // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
+ // ever try to substitute the generic parameters in their bodies.
match expr.kind {
hir::ExprKind::Path(hir::QPath::Resolved(
_,
@@ -291,8 +319,16 @@ impl<'tcx> Const<'tcx> {
let (param_env, unevaluated) = unevaluated.prepare_for_eval(tcx, param_env);
// try to resolve e.g. associated constants to their definition on an impl, and then
// evaluate the const.
- let c = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)?;
- Ok(c.expect("`ty::Const::eval` called on a non-valtree-compatible type"))
+ let Some(c) = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)?
+ else {
+ // This can happen when we run on ill-typed code.
+ let e = tcx.sess.span_delayed_bug(
+ span.unwrap_or(DUMMY_SP),
+ "`ty::Const::eval` called on a non-valtree-compatible type",
+ );
+ return Err(e.into());
+ };
+ Ok(c)
}
ConstKind::Value(val) => Ok(val),
ConstKind::Error(g) => Err(g.into()),
@@ -392,7 +428,7 @@ impl<'tcx> Const<'tcx> {
}
#[inline]
- pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
+ pub fn try_to_scalar(self) -> Option<Scalar> {
self.try_to_valtree()?.try_to_scalar()
}
@@ -407,7 +443,7 @@ impl<'tcx> Const<'tcx> {
}
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) {
+ let default_def_id = match tcx.hir_node_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 9d99344d5..310cf113b 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -71,7 +71,7 @@ impl std::fmt::Debug for ConstInt {
(4, _) => write!(fmt, "_i32")?,
(8, _) => write!(fmt, "_i64")?,
(16, _) => write!(fmt, "_i128")?,
- _ => bug!(),
+ (sz, _) => bug!("unexpected int size i{sz}"),
}
}
Ok(())
@@ -105,7 +105,7 @@ impl std::fmt::Debug for ConstInt {
(4, _) => write!(fmt, "_u32")?,
(8, _) => write!(fmt, "_u64")?,
(16, _) => write!(fmt, "_u128")?,
- _ => bug!(),
+ (sz, _) => bug!("unexpected unsigned int size u{sz}"),
}
}
Ok(())
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 4af841fcf..16e7b16a0 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -3,7 +3,6 @@ use crate::mir;
use crate::ty::abstract_const::CastKind;
use crate::ty::GenericArgsRef;
use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
@@ -77,28 +76,3 @@ static_assert_size!(Expr<'_>, 24);
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(super::ConstKind<'_>, 32);
-
-/// An inference variable for a const, for use in const generics.
-#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
-pub enum InferConst {
- /// Infer the value of the const.
- Var(ty::ConstVid),
- /// Infer the value of the effect.
- ///
- /// For why this is separate from the `Var` variant above, see the
- /// documentation on `EffectVid`.
- EffectVar(ty::EffectVid),
- /// A fresh const variable. See `infer::freshen` for more details.
- Fresh(u32),
-}
-
-impl<CTX> HashStable<CTX> for InferConst {
- fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
- match self {
- InferConst::Var(_) | InferConst::EffectVar(_) => {
- panic!("const variables should not be hashed: {self:?}")
- }
- InferConst::Fresh(i) => i.hash_stable(hcx, hasher),
- }
- }
-}
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index fb7bf78ba..ffa0e89c4 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -1,5 +1,5 @@
use super::ScalarInt;
-use crate::mir::interpret::{AllocId, Scalar};
+use crate::mir::interpret::Scalar;
use crate::ty::{self, Ty, TyCtxt};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
@@ -67,7 +67,7 @@ impl<'tcx> ValTree<'tcx> {
Self::Leaf(i)
}
- pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
+ pub fn try_to_scalar(self) -> Option<Scalar> {
self.try_to_scalar_int().map(Scalar::Int)
}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 551c4a15d..b5ca700c2 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -6,7 +6,7 @@ pub mod tls;
use crate::arena::Arena;
use crate::dep_graph::{DepGraph, DepKindStruct};
-use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
+use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarInfo, CanonicalVarInfos};
use crate::lint::struct_lint_level;
use crate::metadata::ModChild;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
@@ -26,9 +26,9 @@ use crate::traits::solve::{
};
use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind,
- ImplPolarity, InferTy, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig,
- Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind,
- TyVid, TypeAndMut, Visibility,
+ ImplPolarity, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate,
+ PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid,
+ Visibility,
};
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
use rustc_ast::{self as ast, attr};
@@ -39,7 +39,9 @@ use rustc_data_structures::profiling::SelfProfilerRef;
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, FreezeReadGuard, Lock, Lrc, WorkerLocal};
+use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, WorkerLocal};
+#[cfg(parallel_compiler)]
+use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
@@ -69,7 +71,6 @@ use rustc_type_ir::TyKind::*;
use rustc_type_ir::WithCachedTypeInfo;
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
-use std::any::Any;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::fmt;
@@ -87,7 +88,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type Term = ty::Term<'tcx>;
type Binder<T> = Binder<'tcx, T>;
- type TypeAndMut = TypeAndMut<'tcx>;
type CanonicalVars = CanonicalVarInfos<'tcx>;
type Ty = Ty<'tcx>;
@@ -96,7 +96,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type ParamTy = ParamTy;
type BoundTy = ty::BoundTy;
type PlaceholderTy = ty::PlaceholderType;
- type InferTy = InferTy;
type ErrorGuaranteed = ErrorGuaranteed;
type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>;
@@ -104,7 +103,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type AllocId = crate::mir::interpret::AllocId;
type Const = ty::Const<'tcx>;
- type InferConst = ty::InferConst;
type AliasConst = ty::UnevaluatedConst<'tcx>;
type PlaceholderConst = ty::PlaceholderConst;
type ParamConst = ty::ParamConst;
@@ -113,9 +111,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type ExprConst = ty::Expr<'tcx>;
type Region = Region<'tcx>;
- type EarlyBoundRegion = ty::EarlyBoundRegion;
+ type EarlyParamRegion = ty::EarlyParamRegion;
type BoundRegion = ty::BoundRegion;
- type FreeRegion = ty::FreeRegion;
+ type LateParamRegion = ty::LateParamRegion;
type InferRegion = ty::RegionVid;
type PlaceholderRegion = ty::PlaceholderRegion;
@@ -124,14 +122,34 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>;
type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>;
type ProjectionPredicate = ty::ProjectionPredicate<'tcx>;
+ type NormalizesTo = ty::NormalizesTo<'tcx>;
type SubtypePredicate = ty::SubtypePredicate<'tcx>;
type CoercePredicate = ty::CoercePredicate<'tcx>;
type ClosureKind = ty::ClosureKind;
- fn ty_and_mut_to_parts(
- TypeAndMut { ty, mutbl }: TypeAndMut<'tcx>,
- ) -> (Self::Ty, ty::Mutability) {
- (ty, mutbl)
+ fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
+ self.mk_canonical_var_infos(infos)
+ }
+
+ fn mk_bound_ty(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Ty {
+ Ty::new_bound(self, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
+ }
+
+ fn mk_bound_region(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Region {
+ Region::new_bound(
+ self,
+ debruijn,
+ ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon },
+ )
+ }
+
+ fn mk_bound_const(
+ self,
+ debruijn: ty::DebruijnIndex,
+ var: ty::BoundVar,
+ ty: Self::Ty,
+ ) -> Self::Const {
+ Const::new_bound(self, debruijn, var, ty)
}
}
@@ -154,7 +172,7 @@ pub struct CtxtInterners<'tcx> {
clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
- const_: InternedSet<'tcx, ConstData<'tcx>>,
+ const_: InternedSet<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>,
const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
layout: InternedSet<'tcx, LayoutS<FieldIdx, VariantIdx>>,
@@ -215,6 +233,32 @@ impl<'tcx> CtxtInterners<'tcx> {
))
}
+ /// Interns a const. (Use `mk_*` functions instead, where possible.)
+ #[allow(rustc::usage_of_ty_tykind)]
+ #[inline(never)]
+ fn intern_const(
+ &self,
+ data: ty::ConstData<'tcx>,
+ sess: &Session,
+ untracked: &Untracked,
+ ) -> Const<'tcx> {
+ Const(Interned::new_unchecked(
+ self.const_
+ .intern(data, |data: ConstData<'_>| {
+ let flags = super::flags::FlagComputation::for_const(&data.kind, data.ty);
+ let stable_hash = self.stable_hash(&flags, sess, untracked, &data);
+
+ InternedInSet(self.arena.alloc(WithCachedTypeInfo {
+ internee: data,
+ stable_hash,
+ flags: flags.flags,
+ outer_exclusive_binder: flags.outer_exclusive_binder,
+ }))
+ })
+ .0,
+ ))
+ }
+
fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>(
&self,
flags: &ty::flags::FlagComputation,
@@ -327,7 +371,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 })`
+ /// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })`
/// for small values of `i` and `v`.
pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
}
@@ -402,7 +446,7 @@ impl<'tcx> CommonLifetimes<'tcx> {
.map(|i| {
(0..NUM_PREINTERNED_RE_LATE_BOUNDS_V)
.map(|v| {
- mk(ty::ReLateBound(
+ mk(ty::ReBound(
ty::DebruijnIndex::from(i),
ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon },
))
@@ -421,11 +465,17 @@ impl<'tcx> CommonLifetimes<'tcx> {
}
impl<'tcx> CommonConsts<'tcx> {
- fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> {
+ fn new(
+ interners: &CtxtInterners<'tcx>,
+ types: &CommonTypes<'tcx>,
+ sess: &Session,
+ untracked: &Untracked,
+ ) -> CommonConsts<'tcx> {
let mk_const = |c| {
- Const(Interned::new_unchecked(
- interners.const_.intern(c, |c| InternedInSet(interners.arena.alloc(c))).0,
- ))
+ interners.intern_const(
+ c, sess, // This is only used to create a stable hashing context.
+ untracked,
+ )
};
CommonConsts {
@@ -445,14 +495,14 @@ impl<'tcx> CommonConsts<'tcx> {
}
}
-/// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime
-/// conflict.
+/// This struct contains information regarding a free parameter region,
+/// either a `ReEarlyParam` or `ReLateParam`.
#[derive(Debug)]
pub struct FreeRegionInfo {
- /// `LocalDefId` corresponding to FreeRegion
+ /// `LocalDefId` of the free region.
pub def_id: LocalDefId,
- /// the bound region corresponding to FreeRegion
- pub boundregion: ty::BoundRegionKind,
+ /// the bound region corresponding to free region.
+ pub bound_region: ty::BoundRegionKind,
/// checks if bound region is in Impl Item
pub is_impl_item: bool,
}
@@ -472,6 +522,9 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
}
+ pub fn feed_local_def_id(self, key: LocalDefId) -> TyCtxtFeed<'tcx, LocalDefId> {
+ TyCtxtFeed { tcx: self, key }
+ }
/// In order to break cycles involving `AnonConst`, we need to set the expected type by side
/// effect. However, we do not want this as a general capability, so this interface restricts
@@ -520,6 +573,16 @@ pub struct TyCtxt<'tcx> {
gcx: &'tcx GlobalCtxt<'tcx>,
}
+// Explicitly implement `DynSync` and `DynSend` for `TyCtxt` to short circuit trait resolution.
+#[cfg(parallel_compiler)]
+unsafe impl DynSend for TyCtxt<'_> {}
+#[cfg(parallel_compiler)]
+unsafe impl DynSync for TyCtxt<'_> {}
+fn _assert_tcx_fields() {
+ sync::assert_dyn_sync::<&'_ GlobalCtxt<'_>>();
+ sync::assert_dyn_send::<&'_ GlobalCtxt<'_>>();
+}
+
impl<'tcx> Deref for TyCtxt<'tcx> {
type Target = &'tcx GlobalCtxt<'tcx>;
#[inline(always)]
@@ -544,12 +607,6 @@ pub struct GlobalCtxt<'tcx> {
/// `rustc_symbol_mangling` crate for more information.
stable_crate_id: StableCrateId,
- /// This only ever stores a `LintStore` but we don't want a dependency on that type here.
- ///
- /// FIXME(Centril): consider `dyn LintStoreMarker` once
- /// we can upcast to `Any` for some additional type safety.
- pub lint_store: Lrc<dyn Any + sync::DynSync + sync::DynSend>,
-
pub dep_graph: DepGraph,
pub prof: SelfProfilerRef,
@@ -589,6 +646,8 @@ pub struct GlobalCtxt<'tcx> {
pub new_solver_evaluation_cache: solve::EvaluationCache<'tcx>,
pub new_solver_coherence_evaluation_cache: solve::EvaluationCache<'tcx>,
+ pub canonical_param_env_cache: CanonicalParamEnvCache<'tcx>,
+
/// Data layout specification for the current target.
pub data_layout: TargetDataLayout,
@@ -606,6 +665,10 @@ impl<'tcx> GlobalCtxt<'tcx> {
let icx = tls::ImplicitCtxt::new(self);
tls::enter_context(&icx, || f(icx.tcx))
}
+
+ pub fn finish(&self) -> FileEncodeResult {
+ self.dep_graph.finish_encoding(&self.sess.prof)
+ }
}
impl<'tcx> TyCtxt<'tcx> {
@@ -684,8 +747,10 @@ impl<'tcx> TyCtxt<'tcx> {
{
Bound::Included(a)
} else {
- self.sess
- .delay_span_bug(attr.span, "invalid rustc_layout_scalar_valid_range attribute");
+ self.sess.span_delayed_bug(
+ attr.span,
+ "invalid rustc_layout_scalar_valid_range attribute",
+ );
Bound::Unbounded
}
};
@@ -709,7 +774,6 @@ impl<'tcx> TyCtxt<'tcx> {
s: &'tcx Session,
crate_types: Vec<CrateType>,
stable_crate_id: StableCrateId,
- lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
untracked: Untracked,
@@ -724,13 +788,12 @@ impl<'tcx> TyCtxt<'tcx> {
let interners = CtxtInterners::new(arena);
let common_types = CommonTypes::new(&interners, s, &untracked);
let common_lifetimes = CommonLifetimes::new(&interners);
- let common_consts = CommonConsts::new(&interners, &common_types);
+ let common_consts = CommonConsts::new(&interners, &common_types, s, &untracked);
GlobalCtxt {
sess: s,
crate_types,
stable_crate_id,
- lint_store,
arena,
hir_arena,
interners,
@@ -749,6 +812,7 @@ impl<'tcx> TyCtxt<'tcx> {
evaluation_cache: Default::default(),
new_solver_evaluation_cache: Default::default(),
new_solver_coherence_evaluation_cache: Default::default(),
+ canonical_param_env_cache: Default::default(),
data_layout,
alloc_map: Lock::new(interpret::AllocMap::new()),
}
@@ -779,6 +843,10 @@ impl<'tcx> TyCtxt<'tcx> {
self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did)
}
+ pub fn is_coroutine(self, def_id: DefId) -> bool {
+ self.coroutine_kind(def_id).is_some()
+ }
+
/// Returns `true` if the node pointed to by `def_id` is a coroutine for an async construct.
pub fn coroutine_is_async(self, def_id: DefId) -> bool {
matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::Async(_)))
@@ -790,11 +858,16 @@ impl<'tcx> TyCtxt<'tcx> {
matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::Coroutine))
}
- /// Returns `true` if the node pointed to by `def_id` is a coroutine for a gen construct.
+ /// Returns `true` if the node pointed to by `def_id` is a coroutine for a `gen` construct.
pub fn coroutine_is_gen(self, def_id: DefId) -> bool {
matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::Gen(_)))
}
+ /// Returns `true` if the node pointed to by `def_id` is a coroutine for a `async gen` construct.
+ pub fn coroutine_is_async_gen(self, def_id: DefId) -> bool {
+ matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::AsyncGen(_)))
+ }
+
pub fn stability(self) -> &'tcx stability::Index {
self.stability_index(())
}
@@ -943,7 +1016,8 @@ impl<'tcx> TyCtxtAt<'tcx> {
pub fn create_def(
self,
parent: LocalDefId,
- data: hir::definitions::DefPathData,
+ name: Symbol,
+ def_kind: DefKind,
) -> TyCtxtFeed<'tcx, LocalDefId> {
// This function modifies `self.definitions` using a side-effect.
// We need to ensure that these side effects are re-run by the incr. comp. engine.
@@ -965,15 +1039,34 @@ impl<'tcx> TyCtxtAt<'tcx> {
// This is fine because:
// - those queries are `eval_always` so we won't miss their result changing;
// - this write will have happened before these queries are called.
- let key = self.untracked.definitions.write().create_def(parent, data);
+ let def_id = self.tcx.create_def(parent, name, def_kind);
- let feed = TyCtxtFeed { tcx: self.tcx, key };
+ let feed = self.tcx.feed_local_def_id(def_id);
feed.def_span(self.span);
feed
}
}
impl<'tcx> TyCtxt<'tcx> {
+ /// `tcx`-dependent operations performed for every created definition.
+ pub fn create_def(self, parent: LocalDefId, name: Symbol, def_kind: DefKind) -> LocalDefId {
+ let data = def_kind.def_path_data(name);
+ let def_id = self.untracked.definitions.write().create_def(parent, data);
+
+ let feed = self.feed_local_def_id(def_id);
+ feed.def_kind(def_kind);
+ // Unique types created for closures participate in type privacy checking.
+ // They have visibilities inherited from the module they are defined in.
+ // Visibilities for opaque types are meaningless, but still provided
+ // so that all items have visibilities.
+ if matches!(def_kind, DefKind::Closure | DefKind::OpaqueTy) {
+ let parent_mod = self.parent_module_from_def_id(def_id).to_def_id();
+ feed.visibility(ty::Visibility::Restricted(parent_mod));
+ }
+
+ def_id
+ }
+
pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx {
// Create a dependency to the red node to be sure we re-execute this when the amount of
// definitions change.
@@ -1080,8 +1173,8 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn is_suitable_region(self, mut region: Region<'tcx>) -> Option<FreeRegionInfo> {
let (suitable_region_binding_scope, bound_region) = loop {
let def_id = match region.kind() {
- ty::ReFree(fr) => fr.bound_region.get_id()?.as_local()?,
- ty::ReEarlyBound(ebr) => ebr.def_id.expect_local(),
+ ty::ReLateParam(fr) => fr.bound_region.get_id()?.as_local()?,
+ ty::ReEarlyParam(ebr) => ebr.def_id.expect_local(),
_ => return None, // not a free region
};
let scope = self.local_parent(def_id);
@@ -1094,7 +1187,7 @@ impl<'tcx> TyCtxt<'tcx> {
break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into())));
};
- let is_impl_item = match self.hir().find_by_def_id(suitable_region_binding_scope) {
+ let is_impl_item = match self.opt_hir_node_by_def_id(suitable_region_binding_scope) {
Some(Node::Item(..) | Node::TraitItem(..)) => false,
Some(Node::ImplItem(..)) => {
self.is_bound_region_in_impl_item(suitable_region_binding_scope)
@@ -1102,11 +1195,7 @@ impl<'tcx> TyCtxt<'tcx> {
_ => false,
};
- Some(FreeRegionInfo {
- def_id: suitable_region_binding_scope,
- boundregion: bound_region,
- is_impl_item,
- })
+ Some(FreeRegionInfo { def_id: suitable_region_binding_scope, bound_region, is_impl_item })
}
/// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type.
@@ -1114,7 +1203,7 @@ impl<'tcx> TyCtxt<'tcx> {
self,
scope_def_id: LocalDefId,
) -> Vec<&'tcx hir::Ty<'tcx>> {
- let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
+ let hir_id = self.local_def_id_to_hir_id(scope_def_id);
let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) =
self.hir().fn_decl_by_hir_id(hir_id)
else {
@@ -1133,7 +1222,7 @@ impl<'tcx> TyCtxt<'tcx> {
self,
scope_def_id: LocalDefId,
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> {
- let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
+ let hir_id = self.local_def_id_to_hir_id(scope_def_id);
let mut v = TraitObjectVisitor(vec![], self.hir());
// when the return type is a type alias
if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id)
@@ -1141,8 +1230,8 @@ impl<'tcx> TyCtxt<'tcx> {
None,
hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind
&& let Some(local_id) = def_id.as_local()
- && let Some(alias_ty) = self.hir().get_by_def_id(local_id).alias_ty() // it is type alias
- && let Some(alias_generics) = self.hir().get_by_def_id(local_id).generics()
+ && let Some(alias_ty) = self.hir_node_by_def_id(local_id).alias_ty() // it is type alias
+ && let Some(alias_generics) = self.hir_node_by_def_id(local_id).generics()
{
v.visit_ty(alias_ty);
if !v.0.is_empty() {
@@ -1548,7 +1637,6 @@ macro_rules! direct_interners {
// crate only, and have a corresponding `mk_` function.
direct_interners! {
region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
- const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>,
const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
layout: pub mk_layout(LayoutS<FieldIdx, VariantIdx>): Layout -> Layout<'tcx>,
adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
@@ -1725,7 +1813,12 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
- self.intern_const(ty::ConstData { kind, ty })
+ self.interners.intern_const(
+ ty::ConstData { kind, ty },
+ self.sess,
+ // This is only used to create a stable hashing context.
+ &self.untracked,
+ )
}
// Avoid this in favour of more specific `Ty::new_*` methods, where possible.
@@ -1743,7 +1836,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
match param.kind {
GenericParamDefKind::Lifetime => {
- ty::Region::new_early_bound(self, param.to_early_bound_region_data()).into()
+ ty::Region::new_early_param(self, param.to_early_bound_region_data()).into()
}
GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(),
GenericParamDefKind::Const { .. } => ty::Const::new_param(
@@ -1954,14 +2047,12 @@ impl<'tcx> TyCtxt<'tcx> {
let msg = decorator.msg();
let (level, src) = self.lint_level_at_node(lint, hir_id);
struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| {
- decorator.decorate_lint(diag)
+ decorator.decorate_lint(diag);
})
}
/// Emit a lint at the appropriate level for a hir node, with an associated span.
///
- /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
- ///
/// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
@@ -1971,9 +2062,7 @@ impl<'tcx> TyCtxt<'tcx> {
hir_id: HirId,
span: impl Into<MultiSpan>,
msg: impl Into<DiagnosticMessage>,
- decorate: impl for<'a, 'b> FnOnce(
- &'b mut DiagnosticBuilder<'a, ()>,
- ) -> &'b mut DiagnosticBuilder<'a, ()>,
+ decorate: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>),
) {
let (level, src) = self.lint_level_at_node(lint, hir_id);
struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
@@ -1988,13 +2077,13 @@ impl<'tcx> TyCtxt<'tcx> {
id: HirId,
decorator: impl for<'a> DecorateLint<'a, ()>,
) {
- self.struct_lint_node(lint, id, decorator.msg(), |diag| decorator.decorate_lint(diag))
+ self.struct_lint_node(lint, id, decorator.msg(), |diag| {
+ decorator.decorate_lint(diag);
+ })
}
/// Emit a lint at the appropriate level for a hir node.
///
- /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
- ///
/// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
@@ -2003,9 +2092,7 @@ impl<'tcx> TyCtxt<'tcx> {
lint: &'static Lint,
id: HirId,
msg: impl Into<DiagnosticMessage>,
- decorate: impl for<'a, 'b> FnOnce(
- &'b mut DiagnosticBuilder<'a, ()>,
- ) -> &'b mut DiagnosticBuilder<'a, ()>,
+ decorate: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>),
) {
let (level, src) = self.lint_level_at_node(lint, id);
struct_lint_level(self.sess, lint, level, src, None, msg, decorate);
@@ -2040,7 +2127,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Given the def-id of an early-bound lifetime on an RPIT corresponding to
/// a duplicated captured lifetime, map it back to the early- or late-bound
/// lifetime of the function from which it originally as captured. If it is
- /// a late-bound lifetime, this will represent the liberated (`ReFree`) lifetime
+ /// a late-bound lifetime, this will represent the liberated (`ReLateParam`) lifetime
/// of the signature.
// FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just
// re-use the generics of the opaque, this function will need to be tweaked slightly.
@@ -2057,7 +2144,7 @@ impl<'tcx> TyCtxt<'tcx> {
loop {
let parent = self.local_parent(rpit_lifetime_param_def_id);
let hir::OpaqueTy { lifetime_mapping, .. } =
- self.hir().get_by_def_id(parent).expect_item().expect_opaque_ty();
+ self.hir_node_by_def_id(parent).expect_item().expect_opaque_ty();
let Some((lifetime, _)) = lifetime_mapping
.iter()
@@ -2079,9 +2166,9 @@ impl<'tcx> TyCtxt<'tcx> {
}
let generics = self.generics_of(new_parent);
- return ty::Region::new_early_bound(
+ return ty::Region::new_early_param(
self,
- ty::EarlyBoundRegion {
+ ty::EarlyParamRegion {
def_id: ebv,
index: generics
.param_def_id_to_index(self, ebv)
@@ -2092,7 +2179,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => {
let new_parent = self.parent(lbv);
- return ty::Region::new_free(
+ return ty::Region::new_late_param(
self,
new_parent,
ty::BoundRegionKind::BrNamed(
@@ -2141,15 +2228,14 @@ impl<'tcx> TyCtxt<'tcx> {
/// Whether the trait impl is marked const. This does not consider stability or feature gates.
pub fn is_const_trait_impl_raw(self, def_id: DefId) -> bool {
let Some(local_def_id) = def_id.as_local() else { return false };
- let hir_id = self.local_def_id_to_hir_id(local_def_id);
- let node = self.hir().get(hir_id);
+ let node = self.hir_node_by_def_id(local_def_id);
matches!(
node,
hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { generics, .. }),
..
- }) if generics.params.iter().any(|p| self.has_attr(p.def_id, sym::rustc_host))
+ }) if generics.params.iter().any(|p| matches!(p.kind, hir::GenericParamKind::Const { is_host_effect: true, .. }))
)
}
@@ -2158,15 +2244,11 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn next_trait_solver_globally(self) -> bool {
- self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
+ self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally)
}
pub fn next_trait_solver_in_coherence(self) -> bool {
- matches!(
- self.sess.opts.unstable_opts.trait_solver,
- rustc_session::config::TraitSolver::Next
- | rustc_session::config::TraitSolver::NextCoherence
- )
+ self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.coherence)
}
pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index 3371ea3be..cfd36fd8c 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -53,16 +53,11 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
- // because late-bound regions affect subtyping, we can't
- // erase the bound/free distinction, but we can replace
- // all free regions with 'erased.
- //
- // Note that we *CAN* replace early-bound regions -- the
- // type system never "sees" those, they get substituted
- // away. In codegen, they will always be erased to 'erased
- // whenever a substitution occurs.
+ // We must not erase bound regions. `for<'a> fn(&'a ())` and
+ // `fn(&'free ())` are different types: they may implement different
+ // traits and have a different `TypeId`.
match *r {
- ty::ReLateBound(..) => r,
+ ty::ReBound(..) => r,
_ => self.tcx.lifetimes.re_erased,
}
}
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 738bb5e8b..0e4487852 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -7,8 +7,7 @@ use rustc_hir::def_id::DefId;
use rustc_span::symbol::Symbol;
use rustc_target::spec::abi;
use std::borrow::Cow;
-use std::collections::hash_map::DefaultHasher;
-use std::hash::{Hash, Hasher};
+use std::hash::{DefaultHasher, Hash, Hasher};
use std::path::PathBuf;
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
@@ -236,7 +235,7 @@ impl<'tcx> Ty<'tcx> {
_ => "fn item".into(),
},
ty::FnPtr(_) => "fn pointer".into(),
- ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
+ ty::Dynamic(inner, ..) if let Some(principal) = inner.principal() => {
format!("`dyn {}`", tcx.def_path_str(principal.def_id())).into()
}
ty::Dynamic(..) => "trait object".into(),
@@ -282,7 +281,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Float(_)
| ty::Str
| ty::Never => "type".into(),
- ty::Tuple(ref tys) if tys.is_empty() => "unit type".into(),
+ ty::Tuple(tys) if tys.is_empty() => "unit type".into(),
ty::Adt(def, _) => def.descr().into(),
ty::Foreign(_) => "extern type".into(),
ty::Array(..) => "array".into(),
@@ -346,33 +345,35 @@ impl<'tcx> TyCtxt<'tcx> {
short
}
- pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
+ pub fn short_ty_string(self, ty: Ty<'tcx>, path: &mut Option<PathBuf>) -> String {
let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
cx.pretty_print_type(ty)
})
.expect("could not write to `String`");
if !self.sess.opts.unstable_opts.write_long_types_to_disk {
- return (regular, None);
+ return regular;
}
let width = self.sess.diagnostic_width();
let length_limit = width.saturating_sub(30);
if regular.len() <= width {
- return (regular, None);
+ return regular;
}
let short = self.ty_string_with_limit(ty, length_limit);
if regular == short {
- return (regular, None);
+ return regular;
}
- // Multiple types might be shortened in a single error, ensure we create a file for each.
+ // Ensure we create an unique file for the type passed in when we create a file.
let mut s = DefaultHasher::new();
ty.hash(&mut s);
let hash = s.finish();
- let path = self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None);
- match std::fs::write(&path, &regular) {
- Ok(_) => (short, Some(path)),
- Err(_) => (regular, None),
+ *path = Some(path.take().unwrap_or_else(|| {
+ self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None)
+ }));
+ match std::fs::write(path.as_ref().unwrap(), &format!("{regular}\n")) {
+ Ok(_) => short,
+ Err(_) => regular,
}
}
}
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 75ea53195..38a9cabca 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -62,7 +62,7 @@ pub enum TreatParams {
///
/// N.B. during deep rejection, this acts identically to `ForLookup`.
///
- /// FIXME(-Ztrait-solver=next): Remove this variant and cleanup
+ /// FIXME(-Znext-solver): Remove this variant and cleanup
/// the code.
NextSolverLookup,
}
@@ -189,14 +189,14 @@ pub struct DeepRejectCtxt {
}
impl DeepRejectCtxt {
- pub fn args_refs_may_unify<'tcx>(
+ pub fn args_may_unify<'tcx>(
self,
obligation_args: GenericArgsRef<'tcx>,
impl_args: GenericArgsRef<'tcx>,
) -> bool {
iter::zip(obligation_args, impl_args).all(|(obl, imp)| {
match (obl.unpack(), imp.unpack()) {
- // We don't fast reject based on regions for now.
+ // We don't fast reject based on regions.
(GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true,
(GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => {
self.types_may_unify(obl, imp)
@@ -231,7 +231,7 @@ impl DeepRejectCtxt {
| ty::Never
| ty::Tuple(..)
| ty::FnPtr(..)
- | ty::Foreign(..) => {}
+ | ty::Foreign(..) => debug_assert!(impl_ty.is_known_rigid()),
ty::FnDef(..)
| ty::Closure(..)
| ty::Coroutine(..)
@@ -260,7 +260,7 @@ impl DeepRejectCtxt {
},
ty::Adt(obl_def, obl_args) => match k {
&ty::Adt(impl_def, impl_args) => {
- obl_def == impl_def && self.args_refs_may_unify(obl_args, impl_args)
+ obl_def == impl_def && self.args_may_unify(obl_args, impl_args)
}
_ => false,
},
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index ec36bdc5a..f9a2385b1 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -28,10 +28,11 @@ impl FlagComputation {
result
}
- pub fn for_const(c: ty::Const<'_>) -> TypeFlags {
+ pub fn for_const(c: &ty::ConstKind<'_>, t: Ty<'_>) -> FlagComputation {
let mut result = FlagComputation::new();
- result.add_const(c);
- result.flags
+ result.add_const_kind(c);
+ result.add_ty(t);
+ result
}
fn add_flags(&mut self, flags: TypeFlags) {
@@ -137,7 +138,7 @@ impl FlagComputation {
&ty::Bound(debruijn, _) => {
self.add_bound_var(debruijn);
- self.add_flags(TypeFlags::HAS_TY_LATE_BOUND);
+ self.add_flags(TypeFlags::HAS_TY_BOUND);
}
&ty::Placeholder(..) => {
@@ -263,9 +264,6 @@ impl FlagComputation {
self.add_args(slice::from_ref(&arg));
}
ty::PredicateKind::ObjectSafe(_def_id) => {}
- ty::PredicateKind::ClosureKind(_def_id, args, _kind) => {
- self.add_args(args);
- }
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
self.add_const(uv);
}
@@ -274,6 +272,10 @@ impl FlagComputation {
self.add_const(found);
}
ty::PredicateKind::Ambiguous => {}
+ ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => {
+ self.add_alias_ty(alias);
+ self.add_term(term);
+ }
ty::PredicateKind::AliasRelate(t1, t2, _) => {
self.add_term(t1);
self.add_term(t2);
@@ -294,14 +296,18 @@ impl FlagComputation {
fn add_region(&mut self, r: ty::Region<'_>) {
self.add_flags(r.type_flags());
- if let ty::ReLateBound(debruijn, _) = *r {
+ if let ty::ReBound(debruijn, _) = *r {
self.add_bound_var(debruijn);
}
}
fn add_const(&mut self, c: ty::Const<'_>) {
- self.add_ty(c.ty());
- match c.kind() {
+ self.add_flags(c.flags());
+ self.add_exclusive_binder(c.outer_exclusive_binder());
+ }
+
+ fn add_const_kind(&mut self, c: &ty::ConstKind<'_>) {
+ match *c {
ty::ConstKind::Unevaluated(uv) => {
self.add_args(uv.args);
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
@@ -317,7 +323,7 @@ impl FlagComputation {
}
ty::ConstKind::Bound(debruijn, _) => {
self.add_bound_var(debruijn);
- self.add_flags(TypeFlags::HAS_CT_LATE_BOUND);
+ self.add_flags(TypeFlags::HAS_CT_BOUND);
}
ty::ConstKind::Param(_) => {
self.add_flags(TypeFlags::HAS_CT_PARAM);
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 00529a1e0..3e64f9a2a 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -68,12 +68,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// Folds over the substructure of a type, visiting its component
/// types and all regions that occur *free* within it.
///
-/// That is, `Ty` can contain function or method types that bind
-/// regions at the call site (`ReLateBound`), and occurrences of
-/// regions (aka "lifetimes") that are bound within a type are not
-/// visited by this folder; only regions that occur free will be
+/// That is, function pointer types and trait object can introduce
+/// new bound regions which are not visited by this visitors as
+/// they are not free; only regions that occur free will be
/// visited by `fld_r`.
-
pub struct RegionFolder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
@@ -117,7 +115,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
#[instrument(skip(self), level = "debug", ret)]
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
- ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
+ ty::ReBound(debruijn, _) if debruijn < self.current_index => {
debug!(?self.current_index, "skipped bound region");
r
}
@@ -205,15 +203,15 @@ where
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
- ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
+ ty::ReBound(debruijn, br) if debruijn == self.current_index => {
let region = self.delegate.replace_region(br);
- if let ty::ReLateBound(debruijn1, br) = *region {
- // If the callback returns a late-bound region,
+ if let ty::ReBound(debruijn1, br) = *region {
+ // If the callback returns a bound region,
// that region should always use the INNERMOST
// debruijn index. Then we adjust it to the
// correct depth.
assert_eq!(debruijn1, ty::INNERMOST);
- ty::Region::new_late_bound(self.tcx, debruijn, br)
+ ty::Region::new_bound(self.tcx, debruijn, br)
} else {
region
}
@@ -252,7 +250,7 @@ impl<'tcx> TyCtxt<'tcx> {
///
/// This method only replaces late bound regions. Any types or
/// constants bound by `value` will cause an ICE.
- pub fn replace_late_bound_regions<T, F>(
+ pub fn instantiate_bound_regions<T, F>(
self,
value: Binder<'tcx, T>,
mut fld_r: F,
@@ -263,11 +261,11 @@ impl<'tcx> TyCtxt<'tcx> {
{
let mut region_map = BTreeMap::new();
let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
- let value = self.replace_late_bound_regions_uncached(value, real_fld_r);
+ let value = self.instantiate_bound_regions_uncached(value, real_fld_r);
(value, region_map)
}
- pub fn replace_late_bound_regions_uncached<T, F>(
+ pub fn instantiate_bound_regions_uncached<T, F>(
self,
value: Binder<'tcx, T>,
mut replace_regions: F,
@@ -327,8 +325,8 @@ impl<'tcx> TyCtxt<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
- self.replace_late_bound_regions_uncached(value, |br| {
- ty::Region::new_free(self, all_outlive_scope, br.kind)
+ self.instantiate_bound_regions_uncached(value, |br| {
+ ty::Region::new_late_param(self, all_outlive_scope, br.kind)
})
}
@@ -341,7 +339,7 @@ impl<'tcx> TyCtxt<'tcx> {
value,
FnMutDelegate {
regions: &mut |r: ty::BoundRegion| {
- ty::Region::new_late_bound(
+ ty::Region::new_bound(
self,
ty::INNERMOST,
ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
@@ -363,11 +361,11 @@ impl<'tcx> TyCtxt<'tcx> {
/// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also
/// method lookup and a few other places where precise region relationships are not required.
- pub fn erase_late_bound_regions<T>(self, value: Binder<'tcx, T>) -> T
+ pub fn instantiate_bound_regions_with_erased<T>(self, value: Binder<'tcx, T>) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
- self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
+ self.instantiate_bound_regions(value, |_| self.lifetimes.re_erased).0
}
/// Anonymize all bound variables in `value`, this is mostly used to improve caching.
@@ -388,7 +386,7 @@ impl<'tcx> TyCtxt<'tcx> {
.or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon))
.expect_region();
let br = ty::BoundRegion { var, kind };
- ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br)
+ ty::Region::new_bound(self.tcx, ty::INNERMOST, br)
}
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
let entry = self.map.entry(bt.var);
@@ -454,9 +452,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
- ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
+ ty::ReBound(debruijn, br) if debruijn >= self.current_index => {
let debruijn = debruijn.shifted_in(self.amount);
- ty::Region::new_late_bound(self.tcx, debruijn, br)
+ ty::Region::new_bound(self.tcx, debruijn, br)
}
_ => r,
}
@@ -496,8 +494,8 @@ pub fn shift_region<'tcx>(
amount: u32,
) -> ty::Region<'tcx> {
match *region {
- ty::ReLateBound(debruijn, br) if amount > 0 => {
- ty::Region::new_late_bound(tcx, debruijn.shifted_in(amount), br)
+ ty::ReBound(debruijn, br) if amount > 0 => {
+ ty::Region::new_bound(tcx, debruijn.shifted_in(amount), br)
}
_ => region,
}
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 41a1bf04e..63f4bab79 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -10,7 +10,7 @@ use rustc_data_structures::intern::Interned;
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
-use rustc_serialize::{self, Decodable, Encodable};
+use rustc_serialize::{Decodable, Encodable};
use rustc_type_ir::WithCachedTypeInfo;
use smallvec::SmallVec;
@@ -70,7 +70,7 @@ impl<'tcx> GenericArgKind<'tcx> {
GenericArgKind::Const(ct) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
- (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
+ (CONST_TAG, ct.0.0 as *const WithCachedTypeInfo<ty::ConstData<'tcx>> as usize)
}
};
@@ -86,7 +86,7 @@ impl<'tcx> Ord for GenericArg<'tcx> {
impl<'tcx> PartialOrd for GenericArg<'tcx> {
fn partial_cmp(&self, other: &GenericArg<'tcx>) -> Option<Ordering> {
- Some(self.cmp(&other))
+ Some(self.cmp(other))
}
}
@@ -136,7 +136,7 @@ impl<'tcx> GenericArg<'tcx> {
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
))),
CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
- &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
+ &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::ConstData<'tcx>>),
))),
_ => intrinsics::unreachable(),
}
@@ -604,13 +604,6 @@ impl<T> EarlyBinder<Option<T>> {
}
}
-impl<T, U> EarlyBinder<(T, U)> {
- pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) {
- let EarlyBinder { value: (lhs, rhs) } = self;
- (EarlyBinder { value: lhs }, EarlyBinder { value: rhs })
- }
-}
-
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
where
I::Item: TypeFoldable<TyCtxt<'tcx>>,
@@ -809,7 +802,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
#[cold]
#[inline(never)]
- fn region_param_out_of_range(data: ty::EarlyBoundRegion, args: &[GenericArg<'_>]) -> ! {
+ fn region_param_out_of_range(data: ty::EarlyParamRegion, args: &[GenericArg<'_>]) -> ! {
bug!(
"Region parameter out of range when substituting in region {} (index={}, args = {:?})",
data.name,
@@ -820,7 +813,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
#[cold]
#[inline(never)]
- fn region_param_invalid(data: ty::EarlyBoundRegion, other: GenericArgKind<'_>) -> ! {
+ fn region_param_invalid(data: ty::EarlyParamRegion, other: GenericArgKind<'_>) -> ! {
bug!(
"Unexpected parameter {:?} when substituting in region {} (index={})",
other,
@@ -835,7 +828,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
// regions that appear in a function signature is done using
// the specialized routine `ty::replace_late_regions()`.
match *r {
- ty::ReEarlyBound(data) => {
+ ty::ReEarlyParam(data) => {
let rk = self.args.get(data.index as usize).map(|k| k.unpack());
match rk {
Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt),
@@ -843,8 +836,8 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
None => region_param_out_of_range(data, self.args),
}
}
- ty::ReLateBound(..)
- | ty::ReFree(_)
+ ty::ReBound(..)
+ | ty::ReLateParam(_)
| ty::ReStatic
| ty::RePlaceholder(_)
| ty::ReErased
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 888ee1d23..c3699b114 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
-use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
+use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum GenericParamDefKind {
@@ -62,9 +62,9 @@ pub struct GenericParamDef {
}
impl GenericParamDef {
- pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
+ pub fn to_early_bound_region_data(&self) -> ty::EarlyParamRegion {
if let GenericParamDefKind::Lifetime = self.kind {
- ty::EarlyBoundRegion { def_id: self.def_id, index: self.index, name: self.name }
+ ty::EarlyParamRegion { def_id: self.def_id, index: self.index, name: self.name }
} else {
bug!("cannot convert a non-lifetime parameter def to an early bound region")
}
@@ -260,10 +260,10 @@ impl<'tcx> Generics {
}
}
- /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`.
+ /// Returns the `GenericParamDef` associated with this `EarlyParamRegion`.
pub fn region_param(
&'tcx self,
- param: &EarlyBoundRegion,
+ param: &ty::EarlyParamRegion,
tcx: TyCtxt<'tcx>,
) -> &'tcx GenericParamDef {
let param = self.param_at(param.index as usize, tcx);
@@ -326,6 +326,8 @@ impl<'tcx> Generics {
own_params.start = 1;
}
+ let verbose = tcx.sess.verbose();
+
// Filter the default arguments.
//
// This currently uses structural equality instead
@@ -340,6 +342,8 @@ impl<'tcx> Generics {
param.default_value(tcx).is_some_and(|default| {
default.instantiate(tcx, args) == args[param.index as usize]
})
+ // filter out trailing effect params, if we're not in `-Zverbose`.
+ || (!verbose && matches!(param.kind, GenericParamDefKind::Const { is_host_effect: true, .. }))
})
.count();
@@ -354,7 +358,7 @@ impl<'tcx> Generics {
args: &'tcx [ty::GenericArg<'tcx>],
) -> &'tcx [ty::GenericArg<'tcx>] {
let own = &args[self.parent_count..][..self.params.len()];
- if self.has_self && self.parent.is_none() { &own[1..] } else { &own }
+ if self.has_self && self.parent.is_none() { &own[1..] } else { own }
}
}
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index b03874a90..129d94769 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -29,7 +29,7 @@ where
}
let mut hasher = StableHasher::new();
- (&self[..]).hash_stable(hcx, &mut hasher);
+ self[..].hash_stable(hcx, &mut hasher);
let hash: Fingerprint = hasher.finish();
cache.borrow_mut().insert(key, hash);
@@ -84,6 +84,14 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
}
}
+// CtfeProvenance is an AllocId and a bool.
+impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::CtfeProvenance {
+ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+ self.alloc_id().hash_stable(hcx, hasher);
+ self.immutable().hash_stable(hcx, hasher);
+ }
+}
+
impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
type KeyType = region::Scope;
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index f278cace9..ae1794278 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -1,3 +1,5 @@
+use smallvec::SmallVec;
+
use crate::ty::context::TyCtxt;
use crate::ty::{self, DefId, ParamEnv, Ty};
@@ -31,27 +33,31 @@ impl<'tcx> InhabitedPredicate<'tcx> {
/// Returns true if the corresponding type is inhabited in the given
/// `ParamEnv` and module
pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id: DefId) -> bool {
- let Ok(result) = self
- .apply_inner::<!>(tcx, param_env, &|id| Ok(tcx.is_descendant_of(module_def_id, id)));
+ let Ok(result) = self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|id| {
+ Ok(tcx.is_descendant_of(module_def_id, id))
+ });
result
}
/// Same as `apply`, but returns `None` if self contains a module predicate
pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
- self.apply_inner(tcx, param_env, &|_| Err(())).ok()
+ self.apply_inner(tcx, param_env, &mut Default::default(), &|_| Err(())).ok()
}
/// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is,
/// privately uninhabited types are considered always uninhabited.
pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> bool {
- let Ok(result) = self.apply_inner::<!>(tcx, param_env, &|_| Ok(true));
+ let Ok(result) =
+ self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|_| Ok(true));
result
}
- fn apply_inner<E>(
+ #[instrument(level = "debug", skip(tcx, param_env, in_module), ret)]
+ fn apply_inner<E: std::fmt::Debug>(
self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
+ eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection
in_module: &impl Fn(DefId) -> Result<bool, E>,
) -> Result<bool, E> {
match self {
@@ -71,11 +77,25 @@ impl<'tcx> InhabitedPredicate<'tcx> {
match normalized_pred {
// We don't have more information than we started with, so consider inhabited.
Self::GenericType(_) => Ok(true),
- pred => pred.apply_inner(tcx, param_env, in_module),
+ pred => {
+ // A type which is cyclic when monomorphized can happen here since the
+ // layout error would only trigger later. See e.g. `tests/ui/sized/recursive-type-2.rs`.
+ if eval_stack.contains(&t) {
+ return Ok(true); // Recover; this will error later.
+ }
+ eval_stack.push(t);
+ let ret = pred.apply_inner(tcx, param_env, eval_stack, in_module);
+ eval_stack.pop();
+ ret
+ }
}
}
- Self::And([a, b]) => try_and(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
- Self::Or([a, b]) => try_or(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
+ Self::And([a, b]) => {
+ try_and(a, b, |x| x.apply_inner(tcx, param_env, eval_stack, in_module))
+ }
+ Self::Or([a, b]) => {
+ try_or(a, b, |x| x.apply_inner(tcx, param_env, eval_stack, in_module))
+ }
}
}
@@ -197,7 +217,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
// this is basically like `f(a)? && f(b)?` but different in the case of
// `Ok(false) && Err(_) -> Ok(false)`
-fn try_and<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E> {
+fn try_and<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> {
let a = f(a);
if matches!(a, Ok(false)) {
return Ok(false);
@@ -209,7 +229,7 @@ fn try_and<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E
}
}
-fn try_or<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E> {
+fn try_or<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> {
let a = f(a);
if matches!(a, Ok(true)) {
return Ok(true);
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 68ac54e89..d67fb9fd0 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -103,6 +103,7 @@ impl<'tcx> VariantDef {
}
impl<'tcx> Ty<'tcx> {
+ #[instrument(level = "debug", skip(tcx), ret)]
pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> {
match self.kind() {
// For now, unions are always considered inhabited
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index cebefbccc..1c7a7545e 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -215,7 +215,7 @@ impl<'tcx> InstanceDef<'tcx> {
};
matches!(
tcx.def_key(def_id).disambiguated_data.data,
- DefPathData::Ctor | DefPathData::ClosureExpr
+ DefPathData::Ctor | DefPathData::Closure
)
}
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 4223e503f..225dd2178 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -2,10 +2,10 @@ use crate::error::UnsupportedFnAbi;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::query::TyCtxtAt;
use crate::ty::normalize_erasing_regions::NormalizationError;
-use crate::ty::{self, ConstKind, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt};
use rustc_error_messages::DiagnosticMessage;
use rustc_errors::{
- DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg,
+ DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, IntoDiagnostic, IntoDiagnosticArg,
};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
@@ -215,7 +215,7 @@ pub enum LayoutError<'tcx> {
SizeOverflow(Ty<'tcx>),
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
ReferencesError(ErrorGuaranteed),
- Cycle,
+ Cycle(ErrorGuaranteed),
}
impl<'tcx> LayoutError<'tcx> {
@@ -226,7 +226,7 @@ impl<'tcx> LayoutError<'tcx> {
Unknown(_) => middle_unknown_layout,
SizeOverflow(_) => middle_values_too_big,
NormalizationFailure(_, _) => middle_cannot_be_normalized,
- Cycle => middle_cycle,
+ Cycle(_) => middle_cycle,
ReferencesError(_) => middle_layout_references_error,
}
}
@@ -240,7 +240,7 @@ impl<'tcx> LayoutError<'tcx> {
NormalizationFailure(ty, e) => {
E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() }
}
- Cycle => E::Cycle,
+ Cycle(_) => E::Cycle,
ReferencesError(_) => E::ReferencesError,
}
}
@@ -261,7 +261,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
t,
e.get_type_for_failure()
),
- LayoutError::Cycle => write!(f, "a cycle occurred during layout computation"),
+ LayoutError::Cycle(_) => write!(f, "a cycle occurred during layout computation"),
LayoutError::ReferencesError(_) => write!(f, "the type has an unknown layout"),
}
}
@@ -282,8 +282,8 @@ pub struct LayoutCx<'tcx, C> {
impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
type TargetDataLayoutRef = &'tcx TargetDataLayout;
- fn delay_bug(&self, txt: String) {
- self.tcx.sess.delay_span_bug(DUMMY_SP, txt);
+ fn delayed_bug(&self, txt: String) {
+ self.tcx.sess.span_delayed_bug(DUMMY_SP, txt);
}
fn current_data_layout(&self) -> Self::TargetDataLayoutRef {
@@ -333,7 +333,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
Err(err @ LayoutError::Unknown(_)) => err,
// We can't extract SizeSkeleton info from other layout errors
Err(
- e @ LayoutError::Cycle
+ e @ LayoutError::Cycle(_)
| e @ LayoutError::SizeOverflow(_)
| e @ LayoutError::NormalizationFailure(..)
| e @ LayoutError::ReferencesError(_),
@@ -899,13 +899,13 @@ where
ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8),
// Tuples, coroutines and closures.
- ty::Closure(_, ref args) => field_ty_or_layout(
+ ty::Closure(_, args) => field_ty_or_layout(
TyAndLayout { ty: args.as_closure().tupled_upvars_ty(), ..this },
cx,
i,
),
- ty::Coroutine(def_id, ref args, _) => match this.variants {
+ ty::Coroutine(def_id, args, _) => match this.variants {
Variants::Single { index } => TyMaybeWithLayout::Ty(
args.as_coroutine()
.state_tys(def_id, tcx)
@@ -1273,13 +1273,13 @@ pub enum FnAbiError<'tcx> {
}
impl<'a, 'b> IntoDiagnostic<'a, !> for FnAbiError<'b> {
- fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
+ fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, !> {
match self {
- Self::Layout(e) => e.into_diagnostic().into_diagnostic(handler),
+ Self::Layout(e) => e.into_diagnostic().into_diagnostic(dcx),
Self::AdjustForForeignAbi(call::AdjustForForeignAbiError::Unsupported {
arch,
abi,
- }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(handler),
+ }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(dcx),
}
}
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index e1c616ba0..35c135830 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -42,7 +42,6 @@ use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
-use rustc_hir::Node;
use rustc_index::IndexVec;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
@@ -66,27 +65,20 @@ use std::ops::ControlFlow;
use std::{fmt, str};
pub use crate::ty::diagnostics::*;
-pub use rustc_type_ir::AliasKind::*;
pub use rustc_type_ir::ConstKind::{
Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt,
Placeholder as PlaceholderCt, Unevaluated, Value,
};
-pub use rustc_type_ir::DynKind::*;
-pub use rustc_type_ir::InferTy::*;
-pub use rustc_type_ir::RegionKind::*;
-pub use rustc_type_ir::TyKind::*;
pub use rustc_type_ir::*;
pub use self::binding::BindingMode;
pub use self::binding::BindingMode::*;
pub use self::closure::{
is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
- CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
+ CapturedPlace, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL,
};
-pub use self::consts::{
- Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
-};
+pub use self::consts::{Const, ConstData, ConstInt, Expr, ScalarInt, UnevaluatedConst, ValTree};
pub use self::context::{
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
};
@@ -96,13 +88,13 @@ pub use self::parameterized::ParameterizedOverTcx;
pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::BoundRegionKind::*;
pub use self::sty::{
- AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
+ AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind,
BoundVariableKind, CanonicalPolyFnSig, ClauseKind, ClosureArgs, ClosureArgsParts, ConstKind,
- ConstVid, CoroutineArgs, CoroutineArgsParts, EarlyBoundRegion, EffectVid, ExistentialPredicate,
- ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, InlineConstArgs,
- InlineConstArgsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection,
- PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, PredicateKind, Region,
- RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
+ CoroutineArgs, CoroutineArgsParts, EarlyParamRegion, ExistentialPredicate,
+ ExistentialProjection, ExistentialTraitRef, FnSig, GenSig, InlineConstArgs,
+ InlineConstArgsParts, LateParamRegion, ParamConst, ParamTy, PolyExistentialPredicate,
+ PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyTraitRef, PredicateKind,
+ Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
};
pub use self::trait_def::TraitDef;
pub use self::typeck_results::{
@@ -160,7 +152,7 @@ pub struct ResolverOutputs {
#[derive(Debug)]
pub struct ResolverGlobalCtxt {
- pub visibilities: FxHashMap<LocalDefId, Visibility>,
+ pub visibilities_for_hashing: Vec<(LocalDefId, Visibility)>,
/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
pub effective_visibilities: EffectiveVisibilities,
@@ -200,13 +192,10 @@ pub struct ResolverAstLowering {
pub next_node_id: ast::NodeId,
- pub node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>,
+ pub node_id_to_def_id: NodeMap<LocalDefId>,
pub def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
pub trait_map: NodeMap<Vec<hir::TraitCandidate>>,
- /// A small map keeping true kinds of built-in macros that appear to be fn-like on
- /// the surface (`macro` items in libcore), but are actually attributes or derives.
- pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
/// List functions and methods for which lifetime elision was successful.
pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
@@ -301,6 +290,23 @@ pub enum Visibility<Id = LocalDefId> {
Restricted(Id),
}
+impl Visibility {
+ pub fn to_string(self, def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
+ match self {
+ ty::Visibility::Restricted(restricted_id) => {
+ if restricted_id.is_top_level_module() {
+ "pub(crate)".to_string()
+ } else if restricted_id == tcx.parent_module_from_def_id(def_id).to_local_def_id() {
+ "pub(self)".to_string()
+ } else {
+ format!("pub({})", tcx.item_name(restricted_id.to_def_id()))
+ }
+ }
+ ty::Visibility::Public => "pub".to_string(),
+ }
+ }
+}
+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
pub enum BoundConstness {
/// `T: Trait`
@@ -463,7 +469,15 @@ pub struct CReaderCacheKey {
#[rustc_pass_by_value]
pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
-impl ty::EarlyBoundRegion {
+impl<'tcx> IntoKind for Ty<'tcx> {
+ type Kind = TyKind<'tcx>;
+
+ fn kind(self) -> TyKind<'tcx> {
+ *self.kind()
+ }
+}
+
+impl EarlyParamRegion {
/// Does this early bound region have a name? Early bound regions normally
/// always have names except when using anonymous lifetimes (`'_`).
pub fn has_name(&self) -> bool {
@@ -542,6 +556,10 @@ impl<'tcx> Predicate<'tcx> {
pub fn allow_normalization(self) -> bool {
match self.kind().skip_binder() {
PredicateKind::Clause(ClauseKind::WellFormed(_)) => false,
+ // `NormalizesTo` is only used in the new solver, so this shouldn't
+ // matter. Normalizing `term` would be 'wrong' however, as it changes whether
+ // `normalizes-to(<T as Trait>::Assoc, <T as Trait>::Assoc)` holds.
+ PredicateKind::NormalizesTo(..) => false,
PredicateKind::Clause(ClauseKind::Trait(_))
| PredicateKind::Clause(ClauseKind::RegionOutlives(_))
| PredicateKind::Clause(ClauseKind::TypeOutlives(_))
@@ -549,7 +567,6 @@ impl<'tcx> Predicate<'tcx> {
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::ObjectSafe(_)
- | PredicateKind::ClosureKind(_, _, _)
| PredicateKind::Subtype(_)
| PredicateKind::Coerce(_)
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
@@ -902,7 +919,7 @@ impl<'tcx> Term<'tcx> {
&*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
))),
CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
- &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
+ &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::ConstData<'tcx>>),
))),
_ => core::intrinsics::unreachable(),
}
@@ -969,7 +986,7 @@ impl<'tcx> TermKind<'tcx> {
TermKind::Const(ct) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
- (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
+ (CONST_TAG, ct.0.0 as *const WithCachedTypeInfo<ty::ConstData<'tcx>> as usize)
}
};
@@ -1083,6 +1100,33 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
}
}
+/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be
+/// proven by actually normalizing `alias`.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct NormalizesTo<'tcx> {
+ pub alias: AliasTy<'tcx>,
+ pub term: Term<'tcx>,
+}
+
+impl<'tcx> NormalizesTo<'tcx> {
+ pub fn self_ty(self) -> Ty<'tcx> {
+ self.alias.self_ty()
+ }
+
+ pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> {
+ Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
+ }
+
+ pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
+ self.alias.trait_def_id(tcx)
+ }
+
+ pub fn def_id(self) -> DefId {
+ self.alias.def_id
+ }
+}
+
pub trait ToPolyTraitRef<'tcx> {
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
}
@@ -1264,6 +1308,12 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
}
}
+impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> {
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ PredicateKind::NormalizesTo(self).to_predicate(tcx)
+ }
+}
+
impl<'tcx> Predicate<'tcx> {
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
let predicate = self.kind();
@@ -1271,13 +1321,13 @@ impl<'tcx> Predicate<'tcx> {
PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(ClauseKind::Projection(..))
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
+ | PredicateKind::NormalizesTo(..)
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
| PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
- | PredicateKind::ClosureKind(..)
| PredicateKind::Clause(ClauseKind::TypeOutlives(..))
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
@@ -1291,13 +1341,13 @@ impl<'tcx> Predicate<'tcx> {
PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(ClauseKind::Trait(..))
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
+ | PredicateKind::NormalizesTo(..)
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
| PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
- | PredicateKind::ClosureKind(..)
| PredicateKind::Clause(ClauseKind::TypeOutlives(..))
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
@@ -1305,26 +1355,6 @@ impl<'tcx> Predicate<'tcx> {
}
}
- pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
- let predicate = self.kind();
- match predicate.skip_binder() {
- PredicateKind::Clause(ClauseKind::TypeOutlives(data)) => Some(predicate.rebind(data)),
- PredicateKind::Clause(ClauseKind::Trait(..))
- | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
- | PredicateKind::Clause(ClauseKind::Projection(..))
- | PredicateKind::AliasRelate(..)
- | PredicateKind::Subtype(..)
- | PredicateKind::Coerce(..)
- | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
- | PredicateKind::Clause(ClauseKind::WellFormed(..))
- | PredicateKind::ObjectSafe(..)
- | PredicateKind::ClosureKind(..)
- | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
- | PredicateKind::ConstEquate(..)
- | PredicateKind::Ambiguous => None,
- }
- }
-
/// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`.
pub fn as_clause(self) -> Option<Clause<'tcx>> {
match self.kind().skip_binder() {
@@ -1377,7 +1407,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
}
pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
- (&self).into_iter()
+ self.into_iter()
}
}
@@ -1454,7 +1484,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
if let Some(diag) = tcx
.sess
- .diagnostic()
+ .dcx()
.steal_diagnostic(tcx.def_span(opaque_def_id), StashKey::OpaqueHiddenTypeMismatch)
{
diag.cancel();
@@ -1518,8 +1548,44 @@ pub struct Placeholder<T> {
pub type PlaceholderRegion = Placeholder<BoundRegion>;
+impl PlaceholderLike for PlaceholderRegion {
+ fn universe(self) -> UniverseIndex {
+ self.universe
+ }
+
+ fn var(self) -> BoundVar {
+ self.bound.var
+ }
+
+ fn with_updated_universe(self, ui: UniverseIndex) -> Self {
+ Placeholder { universe: ui, ..self }
+ }
+
+ fn new(ui: UniverseIndex, var: BoundVar) -> Self {
+ Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::BrAnon } }
+ }
+}
+
pub type PlaceholderType = Placeholder<BoundTy>;
+impl PlaceholderLike for PlaceholderType {
+ fn universe(self) -> UniverseIndex {
+ self.universe
+ }
+
+ fn var(self) -> BoundVar {
+ self.bound.var
+ }
+
+ fn with_updated_universe(self, ui: UniverseIndex) -> Self {
+ Placeholder { universe: ui, ..self }
+ }
+
+ fn new(ui: UniverseIndex, var: BoundVar) -> Self {
+ Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } }
+ }
+}
+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
pub struct BoundConst<'tcx> {
@@ -1529,6 +1595,24 @@ pub struct BoundConst<'tcx> {
pub type PlaceholderConst = Placeholder<BoundVar>;
+impl PlaceholderLike for PlaceholderConst {
+ fn universe(self) -> UniverseIndex {
+ self.universe
+ }
+
+ fn var(self) -> BoundVar {
+ self.bound
+ }
+
+ fn with_updated_universe(self, ui: UniverseIndex) -> Self {
+ Placeholder { universe: ui, ..self }
+ }
+
+ fn new(ui: UniverseIndex, var: BoundVar) -> Self {
+ Placeholder { universe: ui, bound: var }
+ }
+}
+
/// When type checking, we use the `ParamEnv` to track
/// details about the set of where-clauses that are in scope at this
/// particular point.
@@ -2021,7 +2105,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
for attr in self.get_attrs(did, sym::repr) {
- for r in attr::parse_repr_attr(&self.sess, attr) {
+ for r in attr::parse_repr_attr(self.sess, attr) {
flags.insert(match r {
attr::ReprRust => ReprFlags::empty(),
attr::ReprC => ReprFlags::IS_C,
@@ -2256,7 +2340,7 @@ impl<'tcx> TyCtxt<'tcx> {
// FIXME(@lcnr): Remove this function.
pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [ast::Attribute] {
if let Some(did) = did.as_local() {
- self.hir().attrs(self.hir().local_def_id_to_hir_id(did))
+ self.hir().attrs(self.local_def_id_to_hir_id(did))
} else {
self.item_attrs(did)
}
@@ -2271,7 +2355,7 @@ impl<'tcx> TyCtxt<'tcx> {
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)
+ self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
} else if cfg!(debug_assertions) && rustc_feature::is_builtin_only_local(attr) {
bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr);
} else {
@@ -2287,9 +2371,9 @@ impl<'tcx> TyCtxt<'tcx> {
where
'tcx: 'attr,
{
- let filter_fn = move |a: &&ast::Attribute| a.path_matches(&attr);
+ let filter_fn = move |a: &&ast::Attribute| a.path_matches(attr);
if let Some(did) = did.as_local() {
- self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn)
+ self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn)
} else {
self.item_attrs(did).iter().filter(filter_fn)
}
@@ -2495,22 +2579,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
-/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition.
-pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<LocalDefId> {
- let def_id = def_id.as_local()?;
- if let Node::Item(item) = tcx.hir().get_by_def_id(def_id) {
- if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind {
- return match opaque_ty.origin {
- hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
- Some(parent)
- }
- hir::OpaqueTyOrigin::TyAlias { .. } => None,
- };
- }
- }
- None
-}
-
pub fn int_ty(ity: ast::IntTy) -> IntTy {
match ity {
ast::IntTy::Isize => IntTy::Isize,
@@ -2599,9 +2667,7 @@ pub struct SymbolName<'tcx> {
impl<'tcx> SymbolName<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> {
- SymbolName {
- name: unsafe { str::from_utf8_unchecked(tcx.arena.alloc_slice(name.as_bytes())) },
- }
+ SymbolName { name: tcx.arena.alloc_str(name) }
}
}
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index fd125af20..27c436c82 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -97,6 +97,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// N.B., currently, higher-ranked type bounds inhibit
/// normalization. Therefore, each time we erase them in
/// codegen, we need to normalize the contents.
+ // FIXME(@lcnr): This method should not be necessary, we now normalize
+ // inside of binders. We should be able to only use
+ // `tcx.instantiate_bound_regions_with_erased`. Same for the `try_X`
+ // variant.
#[tracing::instrument(level = "debug", skip(self, param_env))]
pub fn normalize_erasing_late_bound_regions<T>(
self,
@@ -106,7 +110,7 @@ impl<'tcx> TyCtxt<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
- let value = self.erase_late_bound_regions(value);
+ let value = self.instantiate_bound_regions_with_erased(value);
self.normalize_erasing_regions(param_env, value)
}
@@ -126,7 +130,7 @@ impl<'tcx> TyCtxt<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
- let value = self.erase_late_bound_regions(value);
+ let value = self.instantiate_bound_regions_with_erased(value);
self.try_normalize_erasing_regions(param_env, value)
}
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 8d895732d..1305f63bd 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -102,8 +102,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
// Ignore bound regions and `'static` regions that appear in the
// type, we only need to remap regions that reference lifetimes
// from the function declaration.
- // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
- ty::ReLateBound(..) | ty::ReStatic => return r,
+ //
+ // E.g. We ignore `'r` in a type like `for<'r> fn(&'r u32)`.
+ ty::ReBound(..) | ty::ReStatic => return r,
// If regions have been erased (by writeback), don't try to unerase
// them.
@@ -112,7 +113,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
ty::ReError(_) => return r,
// The regions that we expect from borrow checking.
- ty::ReEarlyBound(_) | ty::ReFree(_) => {}
+ ty::ReEarlyParam(_) | ty::ReLateParam(_) => {}
ty::RePlaceholder(_) | ty::ReVar(_) => {
// All of the regions in the type should either have been
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 9afa50cf5..a63a4eff5 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -59,6 +59,7 @@ trivially_parameterized_over_tcx! {
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
crate::middle::debugger_visualizer::DebuggerVisualizerFile,
crate::middle::exported_symbols::SymbolExportInfo,
+ crate::middle::lib_features::FeatureStability,
crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
crate::mir::ConstQualifs,
ty::AssocItemContainer,
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 6bbc8f70f..5e0915478 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -131,7 +131,7 @@ pub trait Printer<'tcx>: Sized {
match key.disambiguated_data.data {
// Closures' own generics are only captures, don't print them.
- DefPathData::ClosureExpr => {}
+ DefPathData::Closure => {}
// This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
// Anon consts doesn't have their own generics, and inline consts' own
// generics are their inferred types, so don't print them.
@@ -250,7 +250,7 @@ fn characteristic_def_id_of_type_cached<'a>(
ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited),
- ty::Tuple(ref tys) => tys.iter().find_map(|ty| {
+ ty::Tuple(tys) => tys.iter().find_map(|ty| {
if visited.insert(ty) {
return characteristic_def_id_of_type_cached(ty, visited);
}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index baf160bcc..8e045397b 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2,23 +2,22 @@ use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar
use crate::query::IntoQueryParam;
use crate::query::Providers;
use crate::traits::util::supertraits_for_pretty_printing;
+use crate::ty::GenericArgKind;
use crate::ty::{
- self, ConstInt, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
- TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+ ConstInt, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable,
+ TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
-use crate::ty::{GenericArg, GenericArgKind};
use rustc_apfloat::ieee::{Double, Single};
+use rustc_apfloat::Float;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_data_structures::sso::SsoHashSet;
use rustc_hir as hir;
use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
-use rustc_hir::def_id::{DefId, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPathData, DefPathDataName, DisambiguatedDefPathData};
+use rustc_hir::def_id::{DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::definitions::{DefKey, DefPathDataName};
use rustc_hir::LangItem;
use rustc_session::config::TrimmedDefPaths;
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
use rustc_session::Limit;
-use rustc_span::sym;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::FileNameDisplayPreference;
use rustc_target::abi::Size;
@@ -282,7 +281,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
/// from at least one local module, and returns `true`. If the crate defining `def_id` is
/// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> {
- if NO_VISIBLE_PATH.with(|flag| flag.get()) {
+ if with_no_visible_paths() {
return Ok(false);
}
@@ -322,7 +321,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
&& let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id)
{
// If `Assoc` is unique, we don't want to talk about `Trait::Assoc`.
- self.write_str(get_local_name(&self, *symbol, def_id, key).as_str())?;
+ self.write_str(get_local_name(self, *symbol, def_id, key).as_str())?;
return Ok(true);
}
if let Some(symbol) = key.get_opt_name() {
@@ -332,7 +331,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
&& let Some(symbol) = parent_key.get_opt_name()
{
// Trait
- self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?;
+ self.write_str(get_local_name(self, symbol, parent, parent_key).as_str())?;
self.write_str("::")?;
} else if let DefKind::Variant = kind
&& let Some(parent) = self.tcx().opt_parent(def_id)
@@ -343,7 +342,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
// For associated items and variants, we want the "full" path, namely, include
// the parent type in the path. For example, `Iterator::Item`.
- self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?;
+ self.write_str(get_local_name(self, symbol, parent, parent_key).as_str())?;
self.write_str("::")?;
} else if let DefKind::Struct
| DefKind::Union
@@ -358,7 +357,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
// If not covered above, like for example items out of `impl` blocks, fallback.
return Ok(false);
}
- self.write_str(get_local_name(&self, symbol, def_id, key).as_str())?;
+ self.write_str(get_local_name(self, symbol, def_id, key).as_str())?;
return Ok(true);
}
Ok(false)
@@ -366,7 +365,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
/// Try to see if this path can be trimmed to a unique symbol name.
fn try_print_trimmed_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> {
- if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ if with_forced_trimmed_paths() {
let trimmed = self.force_print_trimmed_def_path(def_id)?;
if trimmed {
return Ok(true);
@@ -374,8 +373,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
}
if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths
|| matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never)
- || NO_TRIMMED_PATH.with(|flag| flag.get())
- || SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get())
+ || with_no_trimmed_paths()
+ || with_crate_prefix()
{
return Ok(false);
}
@@ -660,7 +659,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
p!(print(ty::TypeAndMut { ty, mutbl }))
}
ty::Never => p!("!"),
- ty::Tuple(ref tys) => {
+ ty::Tuple(tys) => {
p!("(", comma_sep(tys.iter()));
if tys.len() == 1 {
p!(",");
@@ -860,7 +859,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
p!("@", print_def_path(did.to_def_id(), args));
} else {
let span = self.tcx().def_span(did);
- let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ let preference = if with_forced_trimmed_paths() {
FileNameDisplayPreference::Short
} else {
FileNameDisplayPreference::Remapped
@@ -1101,7 +1100,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
write!(self, "Sized")?;
}
- if !FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ if !with_forced_trimmed_paths() {
for re in lifetimes {
write!(self, " + ")?;
self.print_region(re)?;
@@ -1409,14 +1408,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
) -> Result<(), PrintError> {
define_scoped_cx!(self);
- let (alloc_id, offset) = ptr.into_parts();
+ let (prov, offset) = ptr.into_parts();
match ty.kind() {
// Byte strings (&[u8; N])
ty::Ref(_, inner, _) => {
if let ty::Array(elem, len) = inner.kind() {
if let ty::Uint(ty::UintTy::U8) = elem.kind() {
if let ty::ConstKind::Value(ty::ValTree::Leaf(int)) = len.kind() {
- match self.tcx().try_get_global_alloc(alloc_id) {
+ match self.tcx().try_get_global_alloc(prov.alloc_id()) {
Some(GlobalAlloc::Memory(alloc)) => {
let len = int.assert_bits(self.tcx().data_layout.pointer_size);
let range =
@@ -1446,7 +1445,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
// FIXME: We should probably have a helper method to share code with the "Byte strings"
// printing above (which also has to handle pointers to all sorts of things).
if let Some(GlobalAlloc::Function(instance)) =
- self.tcx().try_get_global_alloc(alloc_id)
+ self.tcx().try_get_global_alloc(prov.alloc_id())
{
self.typed_value(
|this| this.print_value_path(instance.def_id(), instance.args),
@@ -1477,10 +1476,12 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
ty::Bool if int == ScalarInt::TRUE => p!("true"),
// Float
ty::Float(ty::FloatTy::F32) => {
- p!(write("{}f32", Single::try_from(int).unwrap()))
+ let val = Single::try_from(int).unwrap();
+ p!(write("{}{}f32", val, if val.is_finite() { "" } else { "_" }))
}
ty::Float(ty::FloatTy::F64) => {
- p!(write("{}f64", Double::try_from(int).unwrap()))
+ let val = Double::try_from(int).unwrap();
+ p!(write("{}{}f64", val, if val.is_finite() { "" } else { "_" }))
}
// Int
ty::Uint(_) | ty::Int(_) => {
@@ -1679,7 +1680,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
self.wrap_binder(&sig, |sig, cx| {
define_scoped_cx!(cx);
- p!(print(kind), "(");
+ p!(write("{kind}("));
for (i, arg) in sig.inputs()[0].tuple_fields().iter().enumerate() {
if i > 0 {
p!(", ");
@@ -1801,13 +1802,13 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
// (but also some things just print a `DefId` generally so maybe we need this?)
fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
match tcx.def_key(def_id).disambiguated_data.data {
- DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::ImplTrait => {
+ DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::OpaqueTy => {
Namespace::TypeNS
}
DefPathData::ValueNs(..)
| DefPathData::AnonConst
- | DefPathData::ClosureExpr
+ | DefPathData::Closure
| DefPathData::Ctor => Namespace::ValueNS,
DefPathData::MacroNs(..) => Namespace::MacroNS,
@@ -1883,7 +1884,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
// available, and filename/line-number is mostly uninteresting.
let use_types = !def_id.is_local() || {
// Otherwise, use filename/line-number if forced.
- let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
+ let force_no_types = with_forced_impl_filename_line();
!force_no_types
};
@@ -1948,7 +1949,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
if cnum == LOCAL_CRATE {
if self.tcx.sess.at_least_rust_2018() {
// We add the `crate::` keyword on Rust 2018, only when desired.
- if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
+ if with_crate_prefix() {
write!(self, "{}", kw::Crate)?;
self.empty_path = false;
}
@@ -2031,37 +2032,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
) -> Result<(), PrintError> {
print_prefix(self)?;
- let tcx = self.tcx;
-
- let args = args.iter().copied();
-
- let args: Vec<_> = if !tcx.sess.verbose() {
- // skip host param as those are printed as `~const`
- args.filter(|arg| match arg.unpack() {
- // FIXME(effects) there should be a better way than just matching the name
- GenericArgKind::Const(c)
- if tcx.features().effects
- && matches!(
- c.kind(),
- ty::ConstKind::Param(ty::ParamConst { name: sym::host, .. })
- ) =>
- {
- false
- }
- _ => true,
- })
- .collect()
- } else {
- // If -Zverbose is passed, we should print the host parameter instead
- // of eating it.
- args.collect()
- };
-
if !args.is_empty() {
if self.in_value {
write!(self, "::")?;
}
- self.generic_delimiters(|cx| cx.comma_sep(args.into_iter()))
+ self.generic_delimiters(|cx| cx.comma_sep(args.iter().copied()))
} else {
Ok(())
}
@@ -2151,17 +2126,17 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
return true;
}
- if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ if with_forced_trimmed_paths() {
return false;
}
let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
match *region {
- ty::ReEarlyBound(ref data) => data.has_name(),
+ ty::ReEarlyParam(ref data) => data.has_name(),
- ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
- | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
+ ty::ReBound(_, ty::BoundRegion { kind: br, .. })
+ | ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. })
| ty::RePlaceholder(ty::Placeholder {
bound: ty::BoundRegion { kind: br, .. }, ..
}) => {
@@ -2228,14 +2203,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
// to fit that into a short string. Hence the recommendation to use
// `explain_region()` or `note_and_explain_region()`.
match *region {
- ty::ReEarlyBound(ref data) => {
+ ty::ReEarlyParam(ref data) => {
if data.name != kw::Empty {
p!(write("{}", data.name));
return Ok(());
}
}
- ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
- | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
+ ty::ReBound(_, ty::BoundRegion { kind: br, .. })
+ | ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. })
| ty::RePlaceholder(ty::Placeholder {
bound: ty::BoundRegion { kind: br, .. }, ..
}) => {
@@ -2315,7 +2290,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
let name = &mut self.name;
let region = match *r {
- ty::ReLateBound(db, br) if db >= self.current_index => {
+ ty::ReBound(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 {
@@ -2338,9 +2313,9 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
}
_ => return r,
};
- if let ty::ReLateBound(debruijn1, br) = *region {
+ if let ty::ReBound(debruijn1, br) = *region {
assert_eq!(debruijn1, ty::INNERMOST);
- ty::Region::new_late_bound(self.tcx, self.current_index, br)
+ ty::Region::new_bound(self.tcx, self.current_index, br)
} else {
region
}
@@ -2399,7 +2374,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
let possible_names = ('a'..='z').rev().map(|s| Symbol::intern(&format!("'{s}")));
let mut available_names = possible_names
- .filter(|name| !self.used_region_names.contains(&name))
+ .filter(|name| !self.used_region_names.contains(name))
.collect::<Vec<_>>();
debug!(?available_names);
let num_available = available_names.len();
@@ -2434,7 +2409,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
} else {
let tcx = self.tcx;
- let trim_path = FORCE_TRIMMED_PATH.with(|flag| flag.get());
+ let trim_path = with_forced_trimmed_paths();
// Closure used in `RegionFolder` to create names for anonymous late-bound
// regions. We use two `DebruijnIndex`es (one for the currently folded
// late-bound region and the other for the binder level) to determine
@@ -2445,12 +2420,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
br: ty::BoundRegion| {
let (name, kind) = match br.kind {
ty::BrAnon | ty::BrEnv => {
- let name = next_name(&self);
+ let name = next_name(self);
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name);
- return ty::Region::new_late_bound(
+ return ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
@@ -2461,12 +2436,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
(name, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name))
}
ty::BrNamed(def_id, kw::UnderscoreLifetime | kw::Empty) => {
- let name = next_name(&self);
+ let name = next_name(self);
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = ty::BrNamed(def_id, name);
- return ty::Region::new_late_bound(
+ return ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
@@ -2480,7 +2455,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = br.kind;
- return ty::Region::new_late_bound(
+ return ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
@@ -2496,11 +2471,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
start_or_continue(self, "for<", ", ");
do_continue(self, name);
}
- ty::Region::new_late_bound(
- tcx,
- ty::INNERMOST,
- ty::BoundRegion { var: br.var, kind },
- )
+ ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind })
};
let mut folder = RegionFolder {
tcx,
@@ -2642,6 +2613,23 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
}
/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
+/// the trait path, and additionally tries to "sugar" `Fn(...)` trait bounds.
+#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
+pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>);
+
+impl<'tcx> rustc_errors::IntoDiagnosticArg for TraitRefPrintSugared<'tcx> {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
+impl<'tcx> fmt::Debug for TraitRefPrintSugared<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, f)
+ }
+}
+
+/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
/// the trait name. That is, it will print `Trait` instead of
/// `<T as Trait<U>>`.
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
@@ -2658,6 +2646,10 @@ impl<'tcx> ty::TraitRef<'tcx> {
TraitRefPrintOnlyTraitPath(self)
}
+ pub fn print_trait_sugared(self) -> TraitRefPrintSugared<'tcx> {
+ TraitRefPrintSugared(self)
+ }
+
pub fn print_only_trait_name(self) -> TraitRefPrintOnlyTraitName<'tcx> {
TraitRefPrintOnlyTraitName(self)
}
@@ -2667,6 +2659,10 @@ impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> {
pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> {
self.map_bound(|tr| tr.print_only_trait_path())
}
+
+ pub fn print_trait_sugared(self) -> ty::Binder<'tcx, TraitRefPrintSugared<'tcx>> {
+ self.map_bound(|tr| tr.print_trait_sugared())
+ }
}
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
@@ -2746,6 +2742,7 @@ forward_display_to_print! {
ty::PolyExistentialTraitRef<'tcx>,
ty::Binder<'tcx, ty::TraitRef<'tcx>>,
ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+ ty::Binder<'tcx, TraitRefPrintSugared<'tcx>>,
ty::Binder<'tcx, ty::FnSig<'tcx>>,
ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>>,
@@ -2757,6 +2754,10 @@ forward_display_to_print! {
define_print! {
(self, cx):
+ ty::TypeAndMut<'tcx> {
+ p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
+ }
+
ty::ClauseKind<'tcx> {
match *self {
ty::ClauseKind::Trait(ref data) => {
@@ -2785,15 +2786,11 @@ define_print! {
ty::PredicateKind::ObjectSafe(trait_def_id) => {
p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
}
- ty::PredicateKind::ClosureKind(closure_def_id, _closure_args, kind) => p!(
- "the closure `",
- print_value_path(closure_def_id, &[]),
- write("` implements the trait `{}`", kind)
- ),
ty::PredicateKind::ConstEquate(c1, c2) => {
p!("the constant `", print(c1), "` equals `", print(c2), "`")
}
ty::PredicateKind::Ambiguous => p!("ambiguous"),
+ ty::PredicateKind::NormalizesTo(data) => p!(print(data)),
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
}
}
@@ -2806,10 +2803,6 @@ define_print_and_forward_display! {
p!("{{", comma_sep(self.iter()), "}}")
}
- ty::TypeAndMut<'tcx> {
- p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
- }
-
ty::ExistentialTraitRef<'tcx> {
// Use a type that can't appear in defaults of type parameters.
let dummy_self = Ty::new_fresh(cx.tcx(),0);
@@ -2850,16 +2843,39 @@ define_print_and_forward_display! {
p!(print_def_path(self.0.def_id, self.0.args));
}
+ TraitRefPrintSugared<'tcx> {
+ if !with_no_queries()
+ && let Some(kind) = cx.tcx().fn_trait_kind_from_def_id(self.0.def_id)
+ && let ty::Tuple(args) = self.0.args.type_at(1).kind()
+ {
+ p!(write("{}", kind.as_str()), "(");
+ for (i, arg) in args.iter().enumerate() {
+ if i > 0 {
+ p!(", ");
+ }
+ p!(print(arg));
+ }
+ p!(")");
+ } else {
+ p!(print_def_path(self.0.def_id, self.0.args));
+ }
+ }
+
TraitRefPrintOnlyTraitName<'tcx> {
p!(print_def_path(self.0.def_id, &[]));
}
TraitPredPrintModifiersAndPath<'tcx> {
- // FIXME(effects) print `~const` here
+ if let Some(idx) = cx.tcx().generics_of(self.0.trait_ref.def_id).host_effect_index
+ {
+ let arg = self.0.trait_ref.args.const_at(idx);
+ if arg != cx.tcx().consts.true_ && !arg.has_infer() {
+ p!("~const ");
+ }
+ }
if let ty::ImplPolarity::Negative = self.0.polarity {
p!("!")
}
-
p!(print(self.0.trait_ref.print_only_trait_path()));
}
@@ -2894,11 +2910,10 @@ define_print_and_forward_display! {
p!("~const ");
}
}
- // FIXME(effects) print `~const` here
if let ty::ImplPolarity::Negative = self.polarity {
p!("!");
}
- p!(print(self.trait_ref.print_only_trait_path()))
+ p!(print(self.trait_ref.print_trait_sugared()))
}
ty::ProjectionPredicate<'tcx> {
@@ -2907,6 +2922,12 @@ define_print_and_forward_display! {
p!(print(self.term))
}
+ ty::NormalizesTo<'tcx> {
+ p!(print(self.alias), " normalizes-to ");
+ cx.reset_type_limit();
+ p!(print(self.term))
+ }
+
ty::Term<'tcx> {
match self.unpack() {
ty::TermKind::Ty(ty) => p!(print(ty)),
@@ -2922,10 +2943,6 @@ define_print_and_forward_display! {
}
}
- ty::ClosureKind {
- p!(write("{}", self.as_str()))
- }
-
ty::Predicate<'tcx> {
p!(print(self.kind()))
}
@@ -3022,7 +3039,8 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
/// The implementation uses similar import discovery logic to that of 'use' suggestions.
///
/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`].
-fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
+// this is pub to be able to intra-doc-link it
+pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
let mut map: FxHashMap<DefId, Symbol> = FxHashMap::default();
if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths {
@@ -3030,7 +3048,7 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
//
// For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths`
// wrapper can be used to suppress this query, in exchange for full paths being formatted.
- tcx.sess.delay_good_path_bug(
+ tcx.sess.good_path_delayed_bug(
"trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging",
);
}
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 27e9be37f..9d92f81db 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -23,8 +23,6 @@ pub enum Cause {
pub trait TypeRelation<'tcx>: Sized {
fn tcx(&self) -> TyCtxt<'tcx>;
- fn param_env(&self) -> ty::ParamEnv<'tcx>;
-
/// Returns a static string we can use for printouts.
fn tag(&self) -> &'static str;
@@ -482,7 +480,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
// the (anonymous) type of the same closure expression. So
// all of their regions should be equated.
let args = relate_args_invariantly(relation, a_args, b_args)?;
- Ok(Ty::new_closure(tcx, a_id, &args))
+ Ok(Ty::new_closure(tcx, a_id, args))
}
(&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => {
@@ -505,13 +503,9 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
Err(err) => {
// Check whether the lengths are both concrete/known values,
// but are unequal, for better diagnostics.
- //
- // It might seem dubious to eagerly evaluate these constants here,
- // we however cannot end up with errors in `Relate` during both
- // `type_of` and `predicates_of`. This means that evaluating the
- // constants should not cause cycle errors here.
- let sz_a = sz_a.try_eval_target_usize(tcx, relation.param_env());
- let sz_b = sz_b.try_eval_target_usize(tcx, relation.param_env());
+ let sz_a = sz_a.try_to_target_usize(tcx);
+ let sz_b = sz_b.try_to_target_usize(tcx);
+
match (sz_a, sz_b) {
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err(
TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)),
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 6af68bc5d..1c75d73e5 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -79,9 +79,9 @@ impl fmt::Debug for ty::BoundRegionKind {
}
}
-impl fmt::Debug for ty::FreeRegion {
+impl fmt::Debug for ty::LateParamRegion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region)
+ write!(f, "ReLateParam({:?}, {:?})", self.scope, self.bound_region)
}
}
@@ -173,6 +173,12 @@ impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
}
}
+impl<'tcx> fmt::Debug for ty::NormalizesTo<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
+ }
+}
+
impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.kind())
@@ -202,34 +208,6 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTy<'tcx> {
}
}
-impl fmt::Debug for ty::InferConst {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- InferConst::Var(var) => write!(f, "{var:?}"),
- InferConst::EffectVar(var) => write!(f, "{var:?}"),
- InferConst::Fresh(var) => write!(f, "Fresh({var:?})"),
- }
- }
-}
-impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::InferConst {
- fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
- this: WithInfcx<'_, Infcx, &Self>,
- f: &mut core::fmt::Formatter<'_>,
- ) -> core::fmt::Result {
- use ty::InferConst::*;
- match this.infcx.universe_of_ct(*this.data) {
- None => write!(f, "{:?}", this.data),
- Some(universe) => match *this.data {
- Var(vid) => write!(f, "?{}_{}c", vid.index(), universe.index()),
- EffectVar(vid) => write!(f, "?{}_{}e", vid.index(), universe.index()),
- Fresh(_) => {
- unreachable!()
- }
- },
- }
- }
-}
-
impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
WithInfcx::with_no_infcx(self).fmt(f)
@@ -444,7 +422,7 @@ TrivialTypeTraversalImpls! {
crate::ty::Placeholder<crate::ty::BoundRegion>,
crate::ty::Placeholder<crate::ty::BoundTy>,
crate::ty::Placeholder<ty::BoundVar>,
- crate::ty::FreeRegion,
+ crate::ty::LateParamRegion,
crate::ty::InferTy,
crate::ty::IntVarValue,
crate::ty::adjustment::PointerCoercion,
@@ -462,14 +440,14 @@ TrivialTypeTraversalImpls! {
// interners).
TrivialTypeTraversalAndLiftImpls! {
::rustc_hir::def_id::DefId,
- ::rustc_hir::Mutability,
::rustc_hir::Unsafety,
::rustc_target::spec::abi::Abi,
crate::ty::ClosureKind,
crate::ty::ParamConst,
crate::ty::ParamTy,
- interpret::Scalar,
interpret::AllocId,
+ interpret::CtfeProvenance,
+ interpret::Scalar,
rustc_target::abi::Size,
}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 44592b10d..a0debc8a1 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -6,7 +6,7 @@ use crate::infer::canonical::Canonical;
use crate::ty::visit::ValidateBoundVars;
use crate::ty::InferTy::*;
use crate::ty::{
- self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
+ self, AdtDef, Discr, IntoKind, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt, TypeVisitor,
};
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
@@ -15,7 +15,9 @@ use hir::def::DefKind;
use polonius_engine::Atom;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::intern::Interned;
-use rustc_errors::{DiagnosticArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan};
+use rustc_errors::{
+ DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan,
+};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::LangItem;
@@ -32,6 +34,7 @@ use std::fmt;
use std::ops::{ControlFlow, Deref, Range};
use ty::util::IntTypeExt;
+use rustc_type_ir::BoundVar;
use rustc_type_ir::ClauseKind as IrClauseKind;
use rustc_type_ir::CollectAndApply;
use rustc_type_ir::ConstKind as IrConstKind;
@@ -41,29 +44,24 @@ use rustc_type_ir::PredicateKind as IrPredicateKind;
use rustc_type_ir::RegionKind as IrRegionKind;
use rustc_type_ir::TyKind as IrTyKind;
use rustc_type_ir::TyKind::*;
+use rustc_type_ir::TypeAndMut as IrTypeAndMut;
use super::GenericParamDefKind;
-// Re-export the `TyKind` from `rustc_type_ir` here for convenience
+// Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
#[rustc_diagnostic_item = "TyKind"]
pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>;
pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>;
pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>;
pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>;
pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;
-
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct TypeAndMut<'tcx> {
- pub ty: Ty<'tcx>,
- pub mutbl: hir::Mutability,
-}
+pub type TypeAndMut<'tcx> = IrTypeAndMut<TyCtxt<'tcx>>;
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)]
#[derive(HashStable)]
-/// A "free" region `fr` can be interpreted as "some region
+/// The parameter representation of late-bound function parameters, "some region
/// at least as big as the scope `fr.scope`".
-pub struct FreeRegion {
+pub struct LateParamRegion {
pub scope: DefId,
pub bound_region: BoundRegionKind,
}
@@ -467,16 +465,6 @@ impl<'tcx> CoroutineArgs<'tcx> {
self.split().return_ty.expect_ty()
}
- /// Returns the "coroutine signature", which consists of its yield
- /// and return types.
- ///
- /// N.B., some bits of the code prefers to see this wrapped in a
- /// binder, but it never contains bound regions. Probably this
- /// function should be removed.
- pub fn poly_sig(self) -> PolyGenSig<'tcx> {
- ty::Binder::dummy(self.sig())
- }
-
/// Returns the "coroutine signature", which consists of its resume, yield
/// and return types.
pub fn sig(self) -> GenSig<'tcx> {
@@ -1036,7 +1024,7 @@ impl<'tcx, T> Binder<'tcx, T> {
/// risky thing to do because it's easy to get confused about
/// De Bruijn indices and the like. It is usually better to
/// discharge the binder using `no_bound_vars` or
- /// `replace_late_bound_regions` or something like
+ /// `instantiate_bound_regions` or something like
/// that. `skip_binder` is only valid when you are either
/// extracting data that has nothing to do with bound vars, you
/// are doing some sort of test that does not involve bound
@@ -1245,6 +1233,28 @@ impl<'tcx> AliasTy<'tcx> {
}
}
+ /// Whether this alias type is an opaque.
+ pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool {
+ matches!(self.opt_kind(tcx), Some(ty::AliasKind::Opaque))
+ }
+
+ /// FIXME: rename `AliasTy` to `AliasTerm` and always handle
+ /// constants. This function can then be removed.
+ pub fn opt_kind(self, tcx: TyCtxt<'tcx>) -> Option<ty::AliasKind> {
+ match tcx.def_kind(self.def_id) {
+ DefKind::AssocTy
+ if let DefKind::Impl { of_trait: false } =
+ tcx.def_kind(tcx.parent(self.def_id)) =>
+ {
+ Some(ty::Inherent)
+ }
+ DefKind::AssocTy => Some(ty::Projection),
+ DefKind::OpaqueTy => Some(ty::Opaque),
+ DefKind::TyAlias => Some(ty::Weak),
+ _ => None,
+ }
+ }
+
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
Ty::new_alias(tcx, self.kind(tcx), self)
}
@@ -1329,8 +1339,6 @@ pub struct GenSig<'tcx> {
pub return_ty: Ty<'tcx>,
}
-pub type PolyGenSig<'tcx> = Binder<'tcx, GenSig<'tcx>>;
-
/// Signature of a function type, which we have arbitrarily
/// decided to use to refer to the input/output types.
///
@@ -1466,17 +1474,25 @@ impl ParamConst {
#[rustc_pass_by_value]
pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>);
+impl<'tcx> IntoKind for Region<'tcx> {
+ type Kind = RegionKind<'tcx>;
+
+ fn kind(self) -> RegionKind<'tcx> {
+ *self
+ }
+}
+
impl<'tcx> Region<'tcx> {
#[inline]
- pub fn new_early_bound(
+ pub fn new_early_param(
tcx: TyCtxt<'tcx>,
- early_bound_region: ty::EarlyBoundRegion,
+ early_bound_region: ty::EarlyParamRegion,
) -> Region<'tcx> {
- tcx.intern_region(ty::ReEarlyBound(early_bound_region))
+ tcx.intern_region(ty::ReEarlyParam(early_bound_region))
}
#[inline]
- pub fn new_late_bound(
+ pub fn new_bound(
tcx: TyCtxt<'tcx>,
debruijn: ty::DebruijnIndex,
bound_region: ty::BoundRegion,
@@ -1488,17 +1504,17 @@ impl<'tcx> Region<'tcx> {
{
re
} else {
- tcx.intern_region(ty::ReLateBound(debruijn, bound_region))
+ tcx.intern_region(ty::ReBound(debruijn, bound_region))
}
}
#[inline]
- pub fn new_free(
+ pub fn new_late_param(
tcx: TyCtxt<'tcx>,
scope: DefId,
bound_region: ty::BoundRegionKind,
) -> Region<'tcx> {
- tcx.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
+ tcx.intern_region(ty::ReLateParam(ty::LateParamRegion { scope, bound_region }))
}
#[inline]
@@ -1522,7 +1538,7 @@ impl<'tcx> Region<'tcx> {
tcx.intern_region(ty::ReError(reported))
}
- /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` to ensure it
+ /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` to ensure it
/// gets used.
#[track_caller]
pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> {
@@ -1533,7 +1549,7 @@ impl<'tcx> Region<'tcx> {
)
}
- /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` with the given
+ /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` with the given
/// `msg` to ensure it gets used.
#[track_caller]
pub fn new_error_with_message<S: Into<MultiSpan>>(
@@ -1541,7 +1557,7 @@ impl<'tcx> Region<'tcx> {
span: S,
msg: &'static str,
) -> Region<'tcx> {
- let reported = tcx.sess.delay_span_bug(span, msg);
+ let reported = tcx.sess.span_delayed_bug(span, msg);
Region::new_error(tcx, reported)
}
@@ -1549,10 +1565,10 @@ impl<'tcx> Region<'tcx> {
/// to avoid the cost of the `match`.
pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
match kind {
- ty::ReEarlyBound(region) => Region::new_early_bound(tcx, region),
- ty::ReLateBound(debruijn, region) => Region::new_late_bound(tcx, debruijn, region),
- ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
- Region::new_free(tcx, scope, bound_region)
+ ty::ReEarlyParam(region) => Region::new_early_param(tcx, region),
+ ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region),
+ ty::ReLateParam(ty::LateParamRegion { scope, bound_region }) => {
+ Region::new_late_param(tcx, scope, bound_region)
}
ty::ReStatic => tcx.lifetimes.re_static,
ty::ReVar(vid) => Region::new_var(tcx, vid),
@@ -1568,45 +1584,29 @@ impl<'tcx> Deref for Region<'tcx> {
#[inline]
fn deref(&self) -> &RegionKind<'tcx> {
- &self.0.0
+ self.0.0
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)]
#[derive(HashStable)]
-pub struct EarlyBoundRegion {
+pub struct EarlyParamRegion {
pub def_id: DefId,
pub index: u32,
pub name: Symbol,
}
-impl fmt::Debug for EarlyBoundRegion {
+impl fmt::Debug for EarlyParamRegion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name)
}
}
rustc_index::newtype_index! {
- /// A **`const`** **v**ariable **ID**.
- #[debug_format = "?{}c"]
- pub struct ConstVid {}
-}
-
-rustc_index::newtype_index! {
- /// An **effect** **v**ariable **ID**.
- ///
- /// Handling effect infer variables happens separately from const infer variables
- /// because we do not want to reuse any of the const infer machinery. If we try to
- /// relate an effect variable with a normal one, we would ICE, which can catch bugs
- /// where we are not correctly using the effect var for an effect param. Fallback
- /// is also implemented on top of having separate effect and normal const variables.
- #[debug_format = "?{}e"]
- pub struct EffectVid {}
-}
-
-rustc_index::newtype_index! {
/// A **region** (lifetime) **v**ariable **ID**.
#[derive(HashStable)]
+ #[encodable]
+ #[orderable]
#[debug_format = "'?{}"]
pub struct RegionVid {}
}
@@ -1617,12 +1617,6 @@ impl Atom for RegionVid {
}
}
-rustc_index::newtype_index! {
- #[derive(HashStable)]
- #[debug_format = "{}"]
- pub struct BoundVar {}
-}
-
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub struct BoundTy {
@@ -1722,9 +1716,9 @@ impl<'tcx> Region<'tcx> {
pub fn get_name(self) -> Option<Symbol> {
if self.has_name() {
match *self {
- ty::ReEarlyBound(ebr) => Some(ebr.name),
- ty::ReLateBound(_, br) => br.kind.get_name(),
- ty::ReFree(fr) => fr.bound_region.get_name(),
+ ty::ReEarlyParam(ebr) => Some(ebr.name),
+ ty::ReBound(_, br) => br.kind.get_name(),
+ ty::ReLateParam(fr) => fr.bound_region.get_name(),
ty::ReStatic => Some(kw::StaticLifetime),
ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(),
_ => None,
@@ -1744,9 +1738,9 @@ impl<'tcx> Region<'tcx> {
/// Is this region named by the user?
pub fn has_name(self) -> bool {
match *self {
- ty::ReEarlyBound(ebr) => ebr.has_name(),
- ty::ReLateBound(_, br) => br.kind.is_named(),
- ty::ReFree(fr) => fr.bound_region.is_named(),
+ ty::ReEarlyParam(ebr) => ebr.has_name(),
+ ty::ReBound(_, br) => br.kind.is_named(),
+ ty::ReLateParam(fr) => fr.bound_region.is_named(),
ty::ReStatic => true,
ty::ReVar(..) => false,
ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(),
@@ -1771,8 +1765,8 @@ impl<'tcx> Region<'tcx> {
}
#[inline]
- pub fn is_late_bound(self) -> bool {
- matches!(*self, ty::ReLateBound(..))
+ pub fn is_bound(self) -> bool {
+ matches!(*self, ty::ReBound(..))
}
#[inline]
@@ -1783,7 +1777,7 @@ impl<'tcx> Region<'tcx> {
#[inline]
pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool {
match *self {
- ty::ReLateBound(debruijn, _) => debruijn >= index,
+ ty::ReBound(debruijn, _) => debruijn >= index,
_ => false,
}
}
@@ -1802,20 +1796,20 @@ impl<'tcx> Region<'tcx> {
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
}
- ty::ReEarlyBound(..) => {
+ ty::ReEarlyParam(..) => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
flags = flags | TypeFlags::HAS_RE_PARAM;
}
- ty::ReFree { .. } => {
+ ty::ReLateParam { .. } => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
}
ty::ReStatic => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
}
- ty::ReLateBound(..) => {
- flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
+ ty::ReBound(..) => {
+ flags = flags | TypeFlags::HAS_RE_BOUND;
}
ty::ReErased => {
flags = flags | TypeFlags::HAS_RE_ERASED;
@@ -1851,22 +1845,28 @@ impl<'tcx> Region<'tcx> {
/// function might return the `DefId` of a closure.
pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId {
match *self {
- ty::ReEarlyBound(br) => tcx.parent(br.def_id),
- ty::ReFree(fr) => fr.scope,
+ ty::ReEarlyParam(br) => tcx.parent(br.def_id),
+ ty::ReLateParam(fr) => fr.scope,
_ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self),
}
}
/// True for free regions other than `'static`.
- pub fn is_free(self) -> bool {
- matches!(*self, ty::ReEarlyBound(_) | ty::ReFree(_))
+ pub fn is_param(self) -> bool {
+ matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_))
}
- /// True if `self` is a free region or static.
- pub fn is_free_or_static(self) -> bool {
+ /// True for free region in the current context.
+ ///
+ /// This is the case for `'static` and param regions.
+ pub fn is_free(self) -> bool {
match *self {
- ty::ReStatic => true,
- _ => self.is_free(),
+ ty::ReStatic | ty::ReEarlyParam(..) | ty::ReLateParam(..) => true,
+ ty::ReVar(..)
+ | ty::RePlaceholder(..)
+ | ty::ReBound(..)
+ | ty::ReErased
+ | ty::ReError(..) => false,
}
}
@@ -1990,21 +1990,21 @@ impl<'tcx> Ty<'tcx> {
Ty::new(tcx, Error(reported))
}
- /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
+ /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` to ensure it gets used.
#[track_caller]
pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
Ty::new_error_with_message(tcx, DUMMY_SP, "TyKind::Error constructed but no error reported")
}
- /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
+ /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given `msg` to
/// ensure it gets used.
#[track_caller]
pub fn new_error_with_message<S: Into<MultiSpan>>(
tcx: TyCtxt<'tcx>,
span: S,
- msg: impl Into<String>,
+ msg: impl Into<DiagnosticMessage>,
) -> Ty<'tcx> {
- let reported = tcx.sess.delay_span_bug(span, msg);
+ let reported = tcx.sess.span_delayed_bug(span, msg);
Ty::new(tcx, Error(reported))
}
@@ -2104,7 +2104,7 @@ impl<'tcx> Ty<'tcx> {
#[inline]
pub fn new_tup(tcx: TyCtxt<'tcx>, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
- if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(&ts))) }
+ if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(ts))) }
}
pub fn new_tup_from_iter<I, T>(tcx: TyCtxt<'tcx>, iter: I) -> T::Output
@@ -2260,7 +2260,7 @@ impl<'tcx> Ty<'tcx> {
impl<'tcx> Ty<'tcx> {
#[inline(always)]
pub fn kind(self) -> &'tcx TyKind<'tcx> {
- &self.0.0
+ self.0.0
}
#[inline(always)]
@@ -2271,7 +2271,7 @@ impl<'tcx> Ty<'tcx> {
#[inline]
pub fn is_unit(self) -> bool {
match self.kind() {
- Tuple(ref tys) => tys.is_empty(),
+ Tuple(tys) => tys.is_empty(),
_ => false,
}
}
@@ -2813,6 +2813,15 @@ impl<'tcx> Ty<'tcx> {
}
}
+ /// Inverse of [`Ty::to_opt_closure_kind`].
+ pub fn from_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> {
+ match kind {
+ ty::ClosureKind::Fn => tcx.types.i8,
+ ty::ClosureKind::FnMut => tcx.types.i16,
+ ty::ClosureKind::FnOnce => tcx.types.i32,
+ }
+ }
+
/// Fast path helper for testing if a type is `Sized`.
///
/// Returning true means the type is known to be sized. Returning
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index e9240d1b2..d372c1cd6 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -126,7 +126,7 @@ pub struct TypeckResults<'tcx> {
/// fn(&'a u32) -> u32
/// ```
///
- /// Note that `'a` is not bound (it would be an `ReFree`) and
+ /// Note that `'a` is not bound (it would be an `ReLateParam`) and
/// that the `Foo` opaque type is replaced by its hidden type.
liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
@@ -241,7 +241,7 @@ impl<'tcx> TypeckResults<'tcx> {
/// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res {
match *qpath {
- hir::QPath::Resolved(_, ref path) => path.res,
+ hir::QPath::Resolved(_, path) => path.res,
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
.type_dependent_def(id)
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
@@ -391,7 +391,7 @@ impl<'tcx> TypeckResults<'tcx> {
pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> {
self.pat_binding_modes().get(id).copied().or_else(|| {
- s.delay_span_bug(sp, "missing binding mode");
+ s.span_delayed_bug(sp, "missing binding mode");
None
})
}
@@ -578,6 +578,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
rustc_index::newtype_index! {
#[derive(HashStable)]
+ #[encodable]
#[debug_format = "UserType({})"]
pub struct UserTypeAnnotationIndex {
const START_INDEX = 0;
@@ -638,7 +639,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
},
GenericArgKind::Lifetime(r) => match *r {
- ty::ReLateBound(debruijn, br) => {
+ ty::ReBound(debruijn, br) => {
// We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(debruijn, ty::INNERMOST);
cvar == br.var
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index a251518d1..8b2b76764 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -35,12 +35,14 @@ pub struct Discr<'tcx> {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum CheckRegions {
No,
- /// Only permit early bound regions. This is useful for Adts which
- /// can never have late bound regions.
- OnlyEarlyBound,
- /// Permit both late bound and early bound regions. Use this for functions,
- /// which frequently have late bound regions.
- Bound,
+ /// Only permit parameter regions. This should be used
+ /// for everything apart from functions, which may use
+ /// `ReBound` to represent late-bound regions.
+ OnlyParam,
+ /// Check region parameters from a function definition.
+ /// Allows `ReEarlyParam` and `ReBound` to handle early
+ /// and late-bound region parameters.
+ FromFunction,
}
#[derive(Copy, Clone, Debug)]
@@ -359,7 +361,7 @@ impl<'tcx> TyCtxt<'tcx> {
let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
self.sess
- .delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
+ .span_delayed_bug(self.def_span(impl_did), "Drop impl without drop function");
return;
};
@@ -419,19 +421,16 @@ impl<'tcx> TyCtxt<'tcx> {
let impl_args = match *self.type_of(impl_def_id).instantiate_identity().kind() {
ty::Adt(def_, args) if def_ == def => args,
- _ => bug!(),
+ _ => span_bug!(self.def_span(impl_def_id), "expected ADT for self type of `Drop` impl"),
};
- let item_args = match *self.type_of(def.did()).instantiate_identity().kind() {
- ty::Adt(def_, args) if def_ == def => args,
- _ => bug!(),
- };
+ let item_args = ty::GenericArgs::identity_for_item(self, def.did());
let result = iter::zip(item_args, impl_args)
.filter(|&(_, k)| {
match k.unpack() {
GenericArgKind::Lifetime(region) => match region.kind() {
- ty::ReEarlyBound(ref ebr) => {
+ ty::ReEarlyParam(ref ebr) => {
!impl_generics.region_param(ebr, self).pure_wrt_drop
}
// Error: not a region param
@@ -468,17 +467,17 @@ impl<'tcx> TyCtxt<'tcx> {
for arg in args {
match arg.unpack() {
GenericArgKind::Lifetime(lt) => match (ignore_regions, lt.kind()) {
- (CheckRegions::Bound, ty::ReLateBound(di, reg)) => {
+ (CheckRegions::FromFunction, ty::ReBound(di, reg)) => {
if !seen_late.insert((di, reg)) {
return Err(NotUniqueParam::DuplicateParam(lt.into()));
}
}
- (CheckRegions::OnlyEarlyBound | CheckRegions::Bound, ty::ReEarlyBound(p)) => {
+ (CheckRegions::OnlyParam | CheckRegions::FromFunction, ty::ReEarlyParam(p)) => {
if !seen.insert(p.index) {
return Err(NotUniqueParam::DuplicateParam(lt.into()));
}
}
- (CheckRegions::OnlyEarlyBound | CheckRegions::Bound, _) => {
+ (CheckRegions::OnlyParam | CheckRegions::FromFunction, _) => {
return Err(NotUniqueParam::NotParam(lt.into()));
}
(CheckRegions::No, _) => {}
@@ -548,16 +547,13 @@ impl<'tcx> TyCtxt<'tcx> {
/// those are not yet phased out). The parent of the closure's
/// `DefId` will also be the context where it appears.
pub fn is_closure(self, def_id: DefId) -> bool {
- matches!(self.def_kind(def_id), DefKind::Closure | DefKind::Coroutine)
+ matches!(self.def_kind(def_id), DefKind::Closure)
}
/// Returns `true` if `def_id` refers to a definition that does not have its own
/// type-checking context, i.e. closure, coroutine or inline const.
pub fn is_typeck_child(self, def_id: DefId) -> bool {
- matches!(
- self.def_kind(def_id),
- DefKind::Closure | DefKind::Coroutine | DefKind::InlineConst
- )
+ matches!(self.def_kind(def_id), DefKind::Closure | DefKind::InlineConst)
}
/// Returns `true` if `def_id` refers to a trait (i.e., `trait Foo { ... }`).
@@ -699,22 +695,6 @@ impl<'tcx> TyCtxt<'tcx> {
.map(|decl| ty::EarlyBinder::bind(decl.ty))
}
- /// Normalizes all opaque types in the given value, replacing them
- /// with their underlying types.
- pub fn expand_opaque_types(self, val: Ty<'tcx>) -> Ty<'tcx> {
- let mut visitor = OpaqueTypeExpander {
- seen_opaque_tys: FxHashSet::default(),
- expanded_cache: FxHashMap::default(),
- primary_def_id: None,
- found_recursion: false,
- found_any_recursion: false,
- check_recursion: false,
- expand_coroutines: false,
- tcx: self,
- };
- val.fold_with(&mut visitor)
- }
-
/// Expands the given impl trait type, stopping if the type is recursive.
#[instrument(skip(self), level = "debug", ret)]
pub fn try_expand_impl_trait_type(
@@ -746,11 +726,14 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn def_kind_descr(self, def_kind: DefKind, def_id: DefId) -> &'static str {
match def_kind {
DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "method",
- DefKind::Coroutine => match self.coroutine_kind(def_id).unwrap() {
- rustc_hir::CoroutineKind::Async(..) => "async closure",
- rustc_hir::CoroutineKind::Coroutine => "coroutine",
- rustc_hir::CoroutineKind::Gen(..) => "gen closure",
- },
+ DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => {
+ match coroutine_kind {
+ rustc_hir::CoroutineKind::Async(..) => "async closure",
+ rustc_hir::CoroutineKind::AsyncGen(..) => "async gen closure",
+ rustc_hir::CoroutineKind::Coroutine => "coroutine",
+ rustc_hir::CoroutineKind::Gen(..) => "gen closure",
+ }
+ }
_ => def_kind.descr(def_id),
}
}
@@ -764,11 +747,14 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn def_kind_descr_article(self, def_kind: DefKind, def_id: DefId) -> &'static str {
match def_kind {
DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "a",
- DefKind::Coroutine => match self.coroutine_kind(def_id).unwrap() {
- rustc_hir::CoroutineKind::Async(..) => "an",
- rustc_hir::CoroutineKind::Coroutine => "a",
- rustc_hir::CoroutineKind::Gen(..) => "a",
- },
+ DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => {
+ match coroutine_kind {
+ rustc_hir::CoroutineKind::Async(..) => "an",
+ rustc_hir::CoroutineKind::AsyncGen(..) => "an",
+ rustc_hir::CoroutineKind::Coroutine => "a",
+ rustc_hir::CoroutineKind::Gen(..) => "a",
+ }
+ }
_ => def_kind.article(),
}
}
@@ -790,7 +776,60 @@ impl<'tcx> TyCtxt<'tcx> {
// If `extern_crate` is `None`, then the crate was injected (e.g., by the allocator).
// Treat that kind of crate as "indirect", since it's an implementation detail of
// the language.
- || self.extern_crate(key.as_def_id()).map_or(false, |e| e.is_direct())
+ || self.extern_crate(key.as_def_id()).is_some_and(|e| e.is_direct())
+ }
+
+ pub fn expected_host_effect_param_for_body(self, def_id: impl Into<DefId>) -> ty::Const<'tcx> {
+ let def_id = def_id.into();
+ // FIXME(effects): This is suspicious and should probably not be done,
+ // especially now that we enforce host effects and then properly handle
+ // effect vars during fallback.
+ let mut host_always_on =
+ !self.features().effects || self.sess.opts.unstable_opts.unleash_the_miri_inside_of_you;
+
+ // Compute the constness required by the context.
+ let const_context = self.hir().body_const_context(def_id);
+
+ let kind = self.def_kind(def_id);
+ debug_assert_ne!(kind, DefKind::ConstParam);
+
+ if self.has_attr(def_id, sym::rustc_do_not_const_check) {
+ trace!("do not const check this context");
+ host_always_on = true;
+ }
+
+ match const_context {
+ _ if host_always_on => self.consts.true_,
+ Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => {
+ self.consts.false_
+ }
+ Some(hir::ConstContext::ConstFn) => {
+ let host_idx = self
+ .generics_of(def_id)
+ .host_effect_index
+ .expect("ConstContext::Maybe must have host effect param");
+ ty::GenericArgs::identity_for_item(self, def_id).const_at(host_idx)
+ }
+ None => self.consts.true_,
+ }
+ }
+
+ /// Constructs generic args for an item, optionally appending a const effect param type
+ pub fn with_opt_host_effect_param(
+ self,
+ caller_def_id: LocalDefId,
+ callee_def_id: DefId,
+ args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
+ ) -> ty::GenericArgsRef<'tcx> {
+ let generics = self.generics_of(callee_def_id);
+ assert_eq!(generics.parent, None);
+
+ let opt_const_param = generics
+ .host_effect_index
+ .is_some()
+ .then(|| ty::GenericArg::from(self.expected_host_effect_param_for_body(caller_def_id)));
+
+ self.mk_args_from_iter(args.into_iter().map(|arg| arg.into()).chain(opt_const_param))
}
}
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 8fc5c0302..e1ce94125 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -1,4 +1,4 @@
-use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
+use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
use rustc_errors::ErrorGuaranteed;
use rustc_data_structures::fx::FxHashSet;
@@ -111,16 +111,16 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
}
/// True if there are any late-bound regions
- fn has_late_bound_regions(&self) -> bool {
- self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
+ fn has_bound_regions(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_RE_BOUND)
}
/// True if there are any late-bound non-region variables
- fn has_non_region_late_bound(&self) -> bool {
- self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND)
+ fn has_non_region_bound_vars(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_BOUND_VARS - TypeFlags::HAS_RE_BOUND)
}
- /// True if there are any late-bound variables
- fn has_late_bound_vars(&self) -> bool {
- self.has_type_flags(TypeFlags::HAS_LATE_BOUND)
+ /// True if there are any bound variables
+ fn has_bound_vars(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_BOUND_VARS)
}
/// Indicates whether this value still has parameters/placeholders/inference variables
@@ -204,7 +204,7 @@ impl<'tcx> TyCtxt<'tcx> {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
match *r {
- ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => {
+ ty::ReBound(debruijn, _) if debruijn < self.outer_index => {
ControlFlow::Continue(())
}
_ => {
@@ -337,7 +337,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
match *r {
- ty::ReLateBound(index, br) if index == self.binder_index => {
+ ty::ReBound(index, br) if index == self.binder_index => {
if self.bound_vars.len() <= br.var.as_usize() {
bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars);
}
@@ -440,16 +440,15 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasEscapingVarsVisitor {
}
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- // we don't have a `visit_infer_const` callback, so we have to
- // hook in here to catch this case (annoying...), but
- // otherwise we do want to remember to visit the rest of the
- // const, as it has types/regions embedded in a lot of other
- // places.
- match ct.kind() {
- ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => {
- ControlFlow::Break(FoundEscapingVars)
- }
- _ => ct.super_visit_with(self),
+ // If the outer-exclusive-binder is *strictly greater* than
+ // `outer_index`, that means that `ct` contains some content
+ // bound at `outer_index` or above (because
+ // `outer_exclusive_binder` is always 1 higher than the
+ // content in `t`). Therefore, `t` has some escaping vars.
+ if ct.outer_exclusive_binder() > self.outer_index {
+ ControlFlow::Break(FoundEscapingVars)
+ } else {
+ ControlFlow::Continue(())
}
}
@@ -529,9 +528,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
#[inline]
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
// Note: no `super_visit_with` call.
- let flags = FlagComputation::for_const(c);
- trace!(r.flags=?flags);
- if flags.intersects(self.flags) {
+ if c.flags().intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::Continue(())
@@ -613,7 +610,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
- if let ty::ReLateBound(debruijn, br) = *r {
+ if let ty::ReBound(debruijn, br) = *r {
if debruijn == self.current_index {
self.regions.insert(br.kind);
}
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index 634ed5ec5..5c9dd18ae 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -31,23 +31,23 @@ fn opt_span_bug_fmt<S: Into<MultiSpan>>(
tls::with_opt(move |tcx| {
let msg = format!("{location}: {args}");
match (tcx, span) {
- (Some(tcx), Some(span)) => tcx.sess.diagnostic().span_bug(span, msg),
- (Some(tcx), None) => tcx.sess.diagnostic().bug(msg),
+ (Some(tcx), Some(span)) => tcx.sess.dcx().span_bug(span, msg),
+ (Some(tcx), None) => tcx.sess.dcx().bug(msg),
(None, _) => panic_any(msg),
}
})
}
-/// A query to trigger a `delay_span_bug`. Clearly, if one has a `tcx` one can already trigger a
-/// `delay_span_bug`, so what is the point of this? It exists to help us test `delay_span_bug`'s
+/// A query to trigger a `span_delayed_bug`. Clearly, if one has a `tcx` one can already trigger a
+/// `span_delayed_bug`, so what is the point of this? It exists to help us test `span_delayed_bug`'s
/// interactions with the query system and incremental.
-pub fn trigger_delay_span_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) {
- tcx.sess.delay_span_bug(
+pub fn trigger_span_delayed_bug(tcx: TyCtxt<'_>, key: rustc_hir::def_id::DefId) {
+ tcx.sess.span_delayed_bug(
tcx.def_span(key),
- "delayed span bug triggered by #[rustc_error(delay_span_bug_from_inside_query)]",
+ "delayed span bug triggered by #[rustc_error(span_delayed_bug_from_inside_query)]",
);
}
pub fn provide(providers: &mut crate::query::Providers) {
- *providers = crate::query::Providers { trigger_delay_span_bug, ..*providers };
+ *providers = crate::query::Providers { trigger_span_delayed_bug, ..*providers };
}
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index f30993c9a..3224f2f26 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -114,12 +114,11 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>
}
impl<'tcx, T> Value<TyCtxt<'tcx>> for Result<T, &'_ ty::layout::LayoutError<'_>> {
- fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> Self {
+ fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self {
// tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under
// min_specialization. Since this is an error path anyways, leaking doesn't matter (and really,
// tcx.arena.alloc is pretty much equal to leaking).
- // FIXME: `Cycle` should carry the ErrorGuaranteed
- Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle)))
+ Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle(guar))))
}
}
@@ -155,8 +154,9 @@ pub fn recursive_type_error(
let (_, field_id) = item_and_field_ids[i];
let (next_item_id, _) = item_and_field_ids[(i + 1) % cycle_len];
// Find the span(s) that contain the next item in the cycle
- let hir_id = tcx.hir().local_def_id_to_hir_id(field_id);
- let hir::Node::Field(field) = tcx.hir().get(hir_id) else { bug!("expected field") };
+ let hir::Node::Field(field) = tcx.hir_node_by_def_id(field_id) else {
+ bug!("expected field")
+ };
let mut found = Vec::new();
find_item_ty_spans(tcx, field.ty, next_item_id, &mut found, representable_ids);