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.rs9
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs78
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs11
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs36
-rw-r--r--compiler/rustc_middle/src/lint.rs13
-rw-r--r--compiler/rustc_middle/src/macros.rs26
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs7
-rw-r--r--compiler/rustc_middle/src/middle/region.rs5
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs4
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs43
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs7
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs1
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs50
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs9
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs12
-rw-r--r--compiler/rustc_middle/src/mir/query.rs7
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs19
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs37
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs9
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs47
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs2
-rw-r--r--compiler/rustc_middle/src/mir/type_visitable.rs2
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs10
-rw-r--r--compiler/rustc_middle/src/query/keys.rs106
-rw-r--r--compiler/rustc_middle/src/query/mod.rs24
-rw-r--r--compiler/rustc_middle/src/thir.rs12
-rw-r--r--compiler/rustc_middle/src/traits/chalk.rs89
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs2
-rw-r--r--compiler/rustc_middle/src/traits/query.rs23
-rw-r--r--compiler/rustc_middle/src/traits/select.rs4
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs9
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs4
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs2
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs7
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs5
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs12
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs3
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs924
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs30
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs2
-rw-r--r--compiler/rustc_middle/src/ty/error.rs108
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs68
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs28
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs32
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs31
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs59
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs76
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs135
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs47
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs11
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs192
-rw-r--r--compiler/rustc_middle/src/ty/query.rs4
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs49
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs36
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs253
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs63
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs707
-rw-r--r--compiler/rustc_middle/src/ty/util.rs137
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs60
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs5
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs5
-rw-r--r--compiler/rustc_middle/src/util/bug.rs3
-rw-r--r--compiler/rustc_middle/src/values.rs35
68 files changed, 2203 insertions, 1652 deletions
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 6de68841f..f816d6145 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -30,7 +30,12 @@ macro_rules! arena_types {
[decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>,
[decode] borrowck_result:
rustc_middle::mir::BorrowCheckResult<'tcx>,
- [] resolver: rustc_data_structures::steal::Steal<rustc_middle::ty::ResolverAstLowering>,
+ [] 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>,
+ [] resolutions: rustc_middle::ty::ResolverGlobalCtxt,
[decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
[decode] code_region: rustc_middle::mir::coverage::CodeRegion,
[] const_allocs: rustc_middle::mir::interpret::Allocation,
@@ -93,7 +98,7 @@ macro_rules! arena_types {
// 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::ConstS<'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
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 6b5568269..865bb70af 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -175,7 +175,7 @@ impl DepNodeExt for DepNode {
/// DepNode. Condition (2) might not be fulfilled if a DepNode
/// refers to something from the previous compilation session that
/// has been removed.
- fn extract_def_id<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
+ fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash {
Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()), &mut || {
panic!("Failed to extract DefId: {:?} {}", self.kind, self.hash)
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 1bd8f9535..9e63c2bd2 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -14,11 +14,11 @@ use rustc_index::vec::Idx;
use rustc_middle::hir::nested_filter;
use rustc_span::def_id::StableCrateId;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
use rustc_target::spec::abi::Abi;
#[inline]
-pub fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
+pub fn associated_body(node: Node<'_>) -> Option<BodyId> {
match node {
Node::Item(Item {
kind: ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body),
@@ -41,7 +41,7 @@ pub fn associated_body<'hir>(node: Node<'hir>) -> Option<BodyId> {
}
}
-fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool {
+fn is_body_owner(node: Node<'_>, hir_id: HirId) -> bool {
match associated_body(node) {
Some(b) => b.hir_id == hir_id,
None => false,
@@ -69,7 +69,7 @@ impl<'hir> Iterator for ParentHirIterator<'hir> {
}
loop {
// There are nodes that do not have entries, so we need to skip them.
- let parent_id = self.map.get_parent_node(self.current_id);
+ let parent_id = self.map.parent_id(self.current_id);
if parent_id == self.current_id {
self.current_id = CRATE_HIR_ID;
@@ -170,6 +170,7 @@ impl<'hir> Map<'hir> {
}
#[inline]
+ #[track_caller]
pub fn local_def_id(self, hir_id: HirId) -> LocalDefId {
self.opt_local_def_id(hir_id).unwrap_or_else(|| {
bug!(
@@ -245,7 +246,7 @@ impl<'hir> Map<'hir> {
},
Node::Variant(_) => DefKind::Variant,
Node::Ctor(variant_data) => {
- let ctor_of = match self.find(self.get_parent_node(hir_id)) {
+ let ctor_of = match self.find_parent(hir_id) {
Some(Node::Item(..)) => def::CtorOf::Struct,
Some(Node::Variant(..)) => def::CtorOf::Variant,
_ => unreachable!(),
@@ -256,7 +257,7 @@ impl<'hir> Map<'hir> {
}
}
Node::AnonConst(_) => {
- let inline = match self.find(self.get_parent_node(hir_id)) {
+ let inline = match self.find_parent(hir_id) {
Some(Node::Expr(&Expr {
kind: ExprKind::ConstBlock(ref anon_const), ..
})) if anon_const.hir_id == hir_id => true,
@@ -297,7 +298,7 @@ impl<'hir> Map<'hir> {
/// Finds the id of the parent node to this one.
///
/// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`].
- pub fn find_parent_node(self, id: HirId) -> Option<HirId> {
+ pub fn opt_parent_id(self, id: HirId) -> Option<HirId> {
if id.local_id == ItemLocalId::from_u32(0) {
Some(self.tcx.hir_owner_parent(id.owner))
} else {
@@ -310,11 +311,20 @@ impl<'hir> Map<'hir> {
}
}
- pub fn get_parent_node(self, hir_id: HirId) -> HirId {
- self.find_parent_node(hir_id)
+ #[track_caller]
+ pub fn parent_id(self, hir_id: HirId) -> HirId {
+ self.opt_parent_id(hir_id)
.unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id)))
}
+ pub fn get_parent(self, hir_id: HirId) -> Node<'hir> {
+ self.get(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) {
@@ -334,12 +344,14 @@ impl<'hir> Map<'hir> {
}
/// 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))
}
@@ -377,6 +389,7 @@ impl<'hir> Map<'hir> {
self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[&id.hir_id.local_id]
}
+ #[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) {
node.fn_decl()
@@ -385,6 +398,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) {
node.fn_sig()
@@ -393,6 +407,7 @@ impl<'hir> Map<'hir> {
}
}
+ #[track_caller]
pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId {
for (_, node) in self.parent_iter(hir_id) {
if let Some(body) = associated_body(node) {
@@ -407,8 +422,8 @@ impl<'hir> Map<'hir> {
/// which this is the body of, i.e., a `fn`, `const` or `static`
/// item (possibly associated), a closure, or a `hir::AnonConst`.
pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId {
- let parent = self.get_parent_node(hir_id);
- assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)));
+ let parent = self.parent_id(hir_id);
+ assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)), "{hir_id:?}");
parent
}
@@ -419,10 +434,11 @@ impl<'hir> Map<'hir> {
/// 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> {
- self.get_if_local(id.to_def_id()).map(associated_body).flatten()
+ self.find_by_def_id(id).and_then(associated_body)
}
/// Given a body owner's id, returns the `BodyId` associated with it.
+ #[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);
@@ -469,7 +485,9 @@ impl<'hir> Map<'hir> {
BodyOwnerKind::Static(mt) => ConstContext::Static(mt),
BodyOwnerKind::Fn if self.tcx.is_constructor(def_id.to_def_id()) => return None,
- BodyOwnerKind::Fn if self.tcx.is_const_fn_raw(def_id.to_def_id()) => {
+ 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()) => {
@@ -564,10 +582,10 @@ impl<'hir> Map<'hir> {
/// Visits all item-likes in the crate in some deterministic (but unspecified) order. If you
/// need to process every item-like, and don't care about visiting nested items in a particular
- /// order then this method is the best choice. If you do care about this nesting, you should
+ /// order then this method is the best choice. If you do care about this nesting, you should
/// use the `tcx.hir().walk_toplevel_module`.
///
- /// Note that this function will access HIR for all the item-likes in the crate. If you only
+ /// Note that this function will access HIR for all the item-likes in the crate. If you only
/// need to access some of them, it is usually better to manually loop on the iterators
/// provided by `tcx.hir_crate_items(())`.
///
@@ -634,21 +652,21 @@ impl<'hir> Map<'hir> {
}
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
- /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+ /// until the crate root is reached. Prefer this over your own loop using `parent_id`.
#[inline]
pub fn parent_id_iter(self, current_id: HirId) -> impl Iterator<Item = HirId> + 'hir {
ParentHirIterator { current_id, map: self }
}
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
- /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+ /// 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)?)))
}
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
- /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+ /// until the crate root is reached. Prefer this over your own loop using `parent_id`.
#[inline]
pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
ParentOwnerIterator { current_id, map: self }
@@ -656,7 +674,7 @@ impl<'hir> Map<'hir> {
/// Checks if the node is left-hand side of an assignment.
pub fn is_lhs(self, id: HirId) -> bool {
- match self.find(self.get_parent_node(id)) {
+ match self.find_parent(id) {
Some(Node::Expr(expr)) => match expr.kind {
ExprKind::Assign(lhs, _rhs, _span) => lhs.hir_id == id,
_ => false,
@@ -696,12 +714,10 @@ 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) = self.find(id) {
- if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = node {
- // When dealing with `return` statements, we don't care about climbing only tail
- // expressions.
- ignore_tail = true;
- }
+ if let Some(Node::Expr(Expr { kind: ExprKind::Ret(_), .. })) = self.find(id) {
+ // When dealing with `return` statements, we don't care about climbing only tail
+ // expressions.
+ ignore_tail = true;
}
while let Some((hir_id, node)) = iter.next() {
if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) {
@@ -886,7 +902,7 @@ impl<'hir> Map<'hir> {
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`.
- Node::Ctor(..) => match self.find(self.get_parent_node(id))? {
+ Node::Ctor(..) => match self.find_parent(id)? {
Node::Item(item) => Some(item.ident),
Node::Variant(variant) => Some(variant.ident),
_ => unreachable!(),
@@ -1015,7 +1031,7 @@ impl<'hir> Map<'hir> {
ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()),
_ => named_span(item.span, item.ident, None),
},
- Node::Ctor(_) => return self.opt_span(self.get_parent_node(hir_id)),
+ Node::Ctor(_) => return self.opt_span(self.parent_id(hir_id)),
Node::Expr(Expr {
kind: ExprKind::Closure(Closure { fn_decl_span, .. }),
span,
@@ -1057,7 +1073,7 @@ impl<'hir> Map<'hir> {
Node::PatField(field) => field.span,
Node::Arm(arm) => arm.span,
Node::Block(block) => block.span,
- Node::Ctor(..) => self.span_with_body(self.get_parent_node(hir_id)),
+ Node::Ctor(..) => self.span_with_body(self.parent_id(hir_id)),
Node::Lifetime(lifetime) => lifetime.ident.span,
Node::GenericParam(param) => param.span,
Node::Infer(i) => i.span,
@@ -1087,7 +1103,7 @@ impl<'hir> Map<'hir> {
/// Returns the HirId of `N` in `struct Foo<const N: usize = { ... }>` when
/// called with the HirId for the `{ ... }` anon const
pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option<LocalDefId> {
- match self.get(self.get_parent_node(anon_const)) {
+ match self.get_parent(anon_const) {
Node::GenericParam(GenericParam {
def_id: param_id,
kind: GenericParamKind::Const { .. },
@@ -1154,7 +1170,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher);
upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
- if tcx.sess.opts.unstable_opts.incremental_relative_spans {
+ if tcx.sess.opts.incremental_relative_spans() {
let definitions = tcx.definitions_untracked();
let mut owner_spans: Vec<_> = krate
.owners
@@ -1162,7 +1178,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
.filter_map(|(def_id, info)| {
let _ = info.as_owner()?;
let def_path_hash = definitions.def_path_hash(def_id);
- let span = resolutions.source_span.get(def_id).unwrap_or(&DUMMY_SP);
+ let span = tcx.source_span(def_id);
debug_assert_eq!(span.parent(), None);
Some((def_path_hash, span))
})
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 02fd03c02..dedc65f4c 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -36,7 +36,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Owner<'tcx> {
}
/// Gather the LocalDefId for each item-like within a module, including items contained within
-/// bodies. The Ids are in visitor order. This is used to partition a pass between modules.
+/// bodies. The Ids are in visitor order. This is used to partition a pass between modules.
#[derive(Debug, HashStable, Encodable, Decodable)]
pub struct ModuleItems {
submodules: Box<[OwnerId]>,
@@ -102,6 +102,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn impl_subject(self, def_id: DefId) -> ImplSubject<'tcx> {
self.impl_trait_ref(def_id)
+ .map(|t| t.subst_identity())
.map(ImplSubject::Trait)
.unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id)))
}
@@ -141,8 +142,6 @@ pub fn provide(providers: &mut Providers) {
providers.hir_attrs = |tcx, id| {
tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
};
- providers.source_span =
- |tcx, def_id| tcx.resolutions(()).source_span.get(def_id).copied().unwrap_or(DUMMY_SP);
providers.def_span = |tcx, def_id| {
let def_id = def_id.expect_local();
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
@@ -162,9 +161,13 @@ pub fn provide(providers: &mut Providers) {
} else if let Node::TraitItem(&TraitItem {
kind: TraitItemKind::Fn(_, TraitFn::Required(idents)),
..
+ })
+ | Node::ForeignItem(&ForeignItem {
+ kind: ForeignItemKind::Fn(_, idents, _),
+ ..
}) = hir.get(hir_id)
{
- tcx.arena.alloc_slice(idents)
+ idents
} else {
span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
}
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 0331d764b..43583b572 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -68,6 +68,22 @@ pub struct CanonicalVarValues<'tcx> {
pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
}
+impl CanonicalVarValues<'_> {
+ pub fn is_identity(&self) -> bool {
+ self.var_values.iter_enumerated().all(|(bv, arg)| match arg.unpack() {
+ ty::GenericArgKind::Lifetime(r) => {
+ matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var == bv)
+ }
+ ty::GenericArgKind::Type(ty) => {
+ matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var == bv)
+ }
+ ty::GenericArgKind::Const(ct) => {
+ matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc == bv)
+ }
+ })
+ }
+}
+
/// When we canonicalize a value to form a query, we wind up replacing
/// various parts of it with canonical variables. This struct stores
/// those replaced bits to remember for when we process the query
@@ -213,9 +229,7 @@ impl QueryRegionConstraints<'_> {
}
}
-pub type Canonicalized<'tcx, V> = Canonical<'tcx, V>;
-
-pub type CanonicalizedQueryResponse<'tcx, T> = &'tcx Canonical<'tcx, QueryResponse<'tcx, T>>;
+pub type CanonicalQueryResponse<'tcx, T> = &'tcx Canonical<'tcx, QueryResponse<'tcx, T>>;
/// Indicates whether or not we were able to prove the query to be
/// true.
@@ -300,6 +314,16 @@ impl<'tcx, V> Canonical<'tcx, V> {
let Canonical { max_universe, variables, value } = self;
Canonical { max_universe, variables, value: map_op(value) }
}
+
+ /// Allows you to map the `value` of a canonical while keeping the same set of
+ /// bound variables.
+ ///
+ /// **WARNING:** This function is very easy to mis-use, hence the name! See
+ /// the comment of [Canonical::unchecked_map] for more details.
+ pub fn unchecked_rebind<W>(self, value: W) -> Canonical<'tcx, W> {
+ let Canonical { max_universe, variables, value: _ } = self;
+ Canonical { max_universe, variables, value }
+ }
}
pub type QueryOutlivesConstraint<'tcx> = (
@@ -315,6 +339,12 @@ TrivialTypeTraversalAndLiftImpls! {
}
impl<'tcx> CanonicalVarValues<'tcx> {
+ /// Creates dummy var values which should not be used in a
+ /// canonical response.
+ pub fn dummy() -> CanonicalVarValues<'tcx> {
+ CanonicalVarValues { var_values: Default::default() }
+ }
+
#[inline]
pub fn len(&self) -> usize {
self.var_values.len()
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 51df42f6d..c61de97d5 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -182,7 +182,7 @@ impl TyCtxt<'_> {
if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
return id;
}
- let next = hir.get_parent_node(id);
+ let next = hir.parent_id(id);
if next == id {
bug!("lint traversal reached the root of the crate");
}
@@ -234,16 +234,7 @@ pub fn explain_lint_level_source(
err.note_once(&format!("`#[{}({})]` on by default", level.as_str(), name));
}
LintLevelSource::CommandLine(lint_flag_val, orig_level) => {
- let flag = match orig_level {
- Level::Warn => "-W",
- Level::Deny => "-D",
- Level::Forbid => "-F",
- Level::Allow => "-A",
- Level::ForceWarn(_) => "--force-warn",
- Level::Expect(_) => {
- unreachable!("the expect level does not have a commandline flag")
- }
- };
+ let flag = orig_level.to_cmd_flag();
let hyphen_case_lint_name = name.replace('_', "-");
if lint_flag_val.as_str() == name {
err.note_once(&format!(
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 01fe72de6..250f3d079 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -1,3 +1,13 @@
+/// A macro for triggering an ICE.
+/// Calling `bug` instead of panicking will result in a nicer error message and should
+/// therefore be prefered over `panic`/`unreachable` or others.
+///
+/// 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.
+///
+/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
+/// [`span_bug`]: crate::span_bug
#[macro_export]
macro_rules! bug {
() => ( $crate::bug!("impossible case reached") );
@@ -8,6 +18,14 @@ macro_rules! bug {
});
}
+/// A macro for triggering an ICE with a span.
+/// Calling `span_bug!` instead of panicking will result in a nicer error message and point
+/// 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.
+///
+/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug
#[macro_export]
macro_rules! span_bug {
($span:expr, $msg:expr) => ({ $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg)) });
@@ -75,7 +93,7 @@ macro_rules! TrivialTypeTraversalImpls {
_: &mut F)
-> ::std::ops::ControlFlow<F::BreakTy>
{
- ::std::ops::ControlFlow::CONTINUE
+ ::std::ops::ControlFlow::Continue(())
}
}
)+
@@ -201,7 +219,7 @@ macro_rules! EnumTypeTraversalImpl {
$($crate::ty::visit::TypeVisitable::visit_with(
$variant_arg, $visitor
)?;)*
- ::std::ops::ControlFlow::CONTINUE
+ ::std::ops::ControlFlow::Continue(())
}
$($output)*
)
@@ -219,7 +237,7 @@ macro_rules! EnumTypeTraversalImpl {
$($crate::ty::visit::TypeVisitable::visit_with(
$variant_arg, $visitor
)?;)*
- ::std::ops::ControlFlow::CONTINUE
+ ::std::ops::ControlFlow::Continue(())
}
$($output)*
)
@@ -233,7 +251,7 @@ macro_rules! EnumTypeTraversalImpl {
@VisitVariants($this, $visitor)
input($($input)*)
output(
- $variant => { ::std::ops::ControlFlow::CONTINUE }
+ $variant => { ::std::ops::ControlFlow::Continue(()) }
$($output)*
)
)
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index fc08d58cc..0e18ba73d 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -103,12 +103,7 @@ impl EffectiveVisibilities {
pub fn public_at_level(&self, id: LocalDefId) -> Option<Level> {
self.effective_vis(id).and_then(|effective_vis| {
- for level in Level::all_levels() {
- if effective_vis.is_public_at_level(level) {
- return Some(level);
- }
- }
- None
+ Level::all_levels().into_iter().find(|&level| effective_vis.is_public_at_level(level))
})
}
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index c886175c6..94ca38c0e 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -147,9 +147,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 `...`.
- pub struct FirstStatementIndex {
- derive [HashStable]
- }
+ #[derive(HashStable)]
+ pub struct FirstStatementIndex {}
}
// compilation error if size of `ScopeData` is not the same as a `u32`
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 61bc089e4..0836f236e 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -223,8 +223,8 @@ pub fn deprecation_message_and_lint(
)
}
-pub fn early_report_deprecation<'a>(
- lint_buffer: &'a mut LintBuffer,
+pub fn early_report_deprecation(
+ lint_buffer: &mut LintBuffer,
message: &str,
suggestion: Option<Symbol>,
lint: &'static Lint,
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index efa946452..e7bb3ab0b 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -3,7 +3,6 @@
use rustc_macros::HashStable;
use rustc_span::Symbol;
-use std::cmp::Ord;
use std::fmt::{self, Debug, Formatter};
rustc_index::newtype_index! {
@@ -11,10 +10,10 @@ rustc_index::newtype_index! {
/// CounterValueReference.as_u32() (which ascend from 1) or an ExpressionOperandId.as_u32()
/// (which _*descend*_ from u32::MAX). Id value `0` (zero) represents a virtual counter with a
/// constant value of `0`.
+ #[derive(HashStable)]
+ #[max = 0xFFFF_FFFF]
+ #[debug_format = "ExpressionOperandId({})"]
pub struct ExpressionOperandId {
- derive [HashStable]
- DEBUG_FORMAT = "ExpressionOperandId({})",
- MAX = 0xFFFF_FFFF,
}
}
@@ -33,11 +32,10 @@ impl ExpressionOperandId {
}
rustc_index::newtype_index! {
- pub struct CounterValueReference {
- derive [HashStable]
- DEBUG_FORMAT = "CounterValueReference({})",
- MAX = 0xFFFF_FFFF,
- }
+ #[derive(HashStable)]
+ #[max = 0xFFFF_FFFF]
+ #[debug_format = "CounterValueReference({})"]
+ pub struct CounterValueReference {}
}
impl CounterValueReference {
@@ -57,33 +55,30 @@ rustc_index::newtype_index! {
/// InjectedExpressionId.as_u32() converts to ExpressionOperandId.as_u32()
///
/// Values descend from u32::MAX.
- pub struct InjectedExpressionId {
- derive [HashStable]
- DEBUG_FORMAT = "InjectedExpressionId({})",
- MAX = 0xFFFF_FFFF,
- }
+ #[derive(HashStable)]
+ #[max = 0xFFFF_FFFF]
+ #[debug_format = "InjectedExpressionId({})"]
+ pub struct InjectedExpressionId {}
}
rustc_index::newtype_index! {
/// InjectedExpressionIndex.as_u32() translates to u32::MAX - ExpressionOperandId.as_u32()
///
/// Values ascend from 0.
- pub struct InjectedExpressionIndex {
- derive [HashStable]
- DEBUG_FORMAT = "InjectedExpressionIndex({})",
- MAX = 0xFFFF_FFFF,
- }
+ #[derive(HashStable)]
+ #[max = 0xFFFF_FFFF]
+ #[debug_format = "InjectedExpressionIndex({})"]
+ pub struct InjectedExpressionIndex {}
}
rustc_index::newtype_index! {
/// MappedExpressionIndex values ascend from zero, and are recalculated indexes based on their
/// array position in the LLVM coverage map "Expressions" array, which is assembled during the
/// "mapgen" process. They cannot be computed algorithmically, from the other `newtype_index`s.
- pub struct MappedExpressionIndex {
- derive [HashStable]
- DEBUG_FORMAT = "MappedExpressionIndex({})",
- MAX = 0xFFFF_FFFF,
- }
+ #[derive(HashStable)]
+ #[max = 0xFFFF_FFFF]
+ #[debug_format = "MappedExpressionIndex({})"]
+ pub struct MappedExpressionIndex {}
}
impl From<CounterValueReference> for ExpressionOperandId {
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index d79cd8b7a..5f425a287 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -95,7 +95,6 @@ mod pointer;
mod queries;
mod value;
-use std::convert::TryFrom;
use std::fmt;
use std::io;
use std::io::{Read, Write};
@@ -510,7 +509,7 @@ impl<'tcx> TyCtxt<'tcx> {
self.reserve_and_set_dedup(GlobalAlloc::Static(static_id))
}
- /// Generates an `AllocId` for a function. Depending on the function type,
+ /// Generates an `AllocId` for a function. Depending on the function type,
/// this might get deduplicated or assigned a new ID each time.
pub fn create_fn_alloc(self, instance: Instance<'tcx>) -> AllocId {
// Functions cannot be identified by pointers, as asm-equal functions can get deduplicated
@@ -519,7 +518,7 @@ impl<'tcx> TyCtxt<'tcx> {
// We thus generate a new `AllocId` for every mention of a function. This means that
// `main as fn() == main as fn()` is false, while `let x = main as fn(); x == x` is true.
// However, formatting code relies on function identity (see #58320), so we only do
- // this for generic functions. Lifetime parameters are ignored.
+ // this for generic functions. Lifetime parameters are ignored.
let is_generic = instance
.substs
.into_iter()
@@ -536,7 +535,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- /// Generates an `AllocId` for a (symbolic, not-reified) vtable. Will get deduplicated.
+ /// Generates an `AllocId` for a (symbolic, not-reified) vtable. Will get deduplicated.
pub fn create_vtable_alloc(
self,
ty: Ty<'tcx>,
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index 9c270ba1e..b08309910 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -3,7 +3,6 @@ use super::{AllocId, InterpResult};
use rustc_macros::HashStable;
use rustc_target::abi::{HasDataLayout, Size};
-use std::convert::{TryFrom, TryInto};
use std::fmt;
////////////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index e6636e50e..88fb14eb3 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -1,4 +1,3 @@
-use std::convert::{TryFrom, TryInto};
use std::fmt;
use either::{Either, Left, Right};
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index a513444e1..e52b243ec 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -36,7 +36,6 @@ use rustc_span::{Span, DUMMY_SP};
use either::Either;
use std::borrow::Cow;
-use std::convert::TryInto;
use std::fmt::{self, Debug, Display, Formatter, Write};
use std::ops::{ControlFlow, Index, IndexMut};
use std::{iter, mem};
@@ -534,6 +533,11 @@ impl<'tcx> Body<'tcx> {
};
injection_phase > self.phase
}
+
+ #[inline]
+ pub fn is_custom_mir(&self) -> bool {
+ self.injection_phase.is_some()
+ }
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
@@ -650,10 +654,10 @@ impl SourceInfo {
// Variables and temps
rustc_index::newtype_index! {
+ #[derive(HashStable)]
+ #[debug_format = "_{}"]
pub struct Local {
- derive [HashStable]
- DEBUG_FORMAT = "_{}",
- const RETURN_PLACE = 0,
+ const RETURN_PLACE = 0;
}
}
@@ -1142,10 +1146,10 @@ rustc_index::newtype_index! {
/// https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis
/// [`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)]
+ #[debug_format = "bb{}"]
pub struct BasicBlock {
- derive [HashStable]
- DEBUG_FORMAT = "bb{}",
- const START_BLOCK = 0,
+ const START_BLOCK = 0;
}
}
@@ -1526,10 +1530,9 @@ rustc_index::newtype_index! {
/// [wrapper]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html#newtype
/// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg
/// [mir-datatypes]: https://rustc-dev-guide.rust-lang.org/mir/index.html#mir-data-types
- pub struct Field {
- derive [HashStable]
- DEBUG_FORMAT = "field[{}]"
- }
+ #[derive(HashStable)]
+ #[debug_format = "field[{}]"]
+ pub struct Field {}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -1753,10 +1756,10 @@ impl Debug for Place<'_> {
// Scopes
rustc_index::newtype_index! {
+ #[derive(HashStable)]
+ #[debug_format = "scope[{}]"]
pub struct SourceScope {
- derive [HashStable]
- DEBUG_FORMAT = "scope[{}]",
- const OUTERMOST_SOURCE_SCOPE = 0,
+ const OUTERMOST_SOURCE_SCOPE = 0;
}
}
@@ -1764,9 +1767,9 @@ impl SourceScope {
/// Finds the original HirId this MIR item came from.
/// This is necessary after MIR optimizations, as otherwise we get a HirId
/// from the function that was inlined instead of the function call site.
- pub fn lint_root<'tcx>(
+ pub fn lint_root(
self,
- source_scopes: &IndexVec<SourceScope, SourceScopeData<'tcx>>,
+ source_scopes: &IndexVec<SourceScope, SourceScopeData<'_>>,
) -> Option<HirId> {
let mut data = &source_scopes[self];
// FIXME(oli-obk): we should be able to just walk the `inlined_parent_scope`, but it
@@ -1848,7 +1851,7 @@ impl<'tcx> Operand<'tcx> {
pub fn function_handle(
tcx: TyCtxt<'tcx>,
def_id: DefId,
- substs: SubstsRef<'tcx>,
+ substs: impl IntoIterator<Item = GenericArg<'tcx>>,
span: Span,
) -> Self {
let ty = tcx.mk_fn_def(def_id, substs);
@@ -2480,7 +2483,7 @@ impl<'tcx> ConstantKind<'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
+ // 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
@@ -2503,7 +2506,7 @@ impl<'tcx> ConstantKind<'tcx> {
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
- let parent_substs = if let Some(parent_hir_id) = tcx.hir().find_parent_node(hir_id) {
+ let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) {
if let Some(parent_did) = tcx.hir().opt_local_def_id(parent_hir_id) {
InternalSubsts::identity_for_item(tcx, parent_did.to_def_id())
} else {
@@ -2751,10 +2754,9 @@ impl<'tcx> TypeVisitable<'tcx> for UserTypeProjection {
}
rustc_index::newtype_index! {
- pub struct Promoted {
- derive [HashStable]
- DEBUG_FORMAT = "promoted[{}]"
- }
+ #[derive(HashStable)]
+ #[debug_format = "promoted[{}]"]
+ pub struct Promoted {}
}
impl<'tcx> Debug for Constant<'tcx> {
@@ -2892,7 +2894,7 @@ fn pretty_print_const_value<'tcx>(
if let Some(contents) = tcx.try_destructure_mir_constant(
ty::ParamEnv::reveal_all().and(ConstantKind::Val(ct, ty)),
) {
- let fields = contents.fields.iter().copied().collect::<Vec<_>>();
+ let fields = contents.fields.to_vec();
match *ty.kind() {
ty::Array(..) => {
fmt.write_str("[")?;
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 15a24aa4a..1e8d5f7ea 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -200,6 +200,15 @@ impl<'tcx> MonoItem<'tcx> {
MonoItem::GlobalAsm(..) => LOCAL_CRATE,
}
}
+
+ /// Returns the item's `DefId`
+ pub fn def_id(&self) -> DefId {
+ match *self {
+ MonoItem::Fn(Instance { def, .. }) => def.def_id(),
+ MonoItem::Static(def_id) => def_id,
+ MonoItem::GlobalAsm(item_id) => item_id.owner_id.to_def_id(),
+ }
+ }
}
impl<'tcx> fmt::Display for MonoItem<'tcx> {
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 2a4ff4b88..40289af25 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -88,7 +88,7 @@ pub fn dump_mir<'tcx, F>(
dump_matched_mir_node(tcx, pass_num, pass_name, disambiguator, body, extra_data);
}
-pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) -> bool {
+pub fn dump_enabled(tcx: TyCtxt<'_>, pass_name: &str, def_id: DefId) -> bool {
let Some(ref filters) = tcx.sess.opts.unstable_opts.dump_mir else {
return false;
};
@@ -421,7 +421,7 @@ impl<'tcx> ExtraComments<'tcx> {
}
}
-fn use_verbose<'tcx>(ty: Ty<'tcx>, fn_def: bool) -> bool {
+fn use_verbose(ty: Ty<'_>, fn_def: bool) -> bool {
match *ty.kind() {
ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false,
// Unit type
@@ -448,15 +448,15 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
// FIXME: this is a poor version of `pretty_print_const_value`.
let fmt_val = |val: &ConstValue<'tcx>| match val {
- ConstValue::ZeroSized => format!("<ZST>"),
+ ConstValue::ZeroSized => "<ZST>".to_string(),
ConstValue::Scalar(s) => format!("Scalar({:?})", s),
- ConstValue::Slice { .. } => format!("Slice(..)"),
- ConstValue::ByRef { .. } => format!("ByRef(..)"),
+ ConstValue::Slice { .. } => "Slice(..)".to_string(),
+ ConstValue::ByRef { .. } => "ByRef(..)".to_string(),
};
let fmt_valtree = |valtree: &ty::ValTree<'tcx>| match valtree {
ty::ValTree::Leaf(leaf) => format!("ValTree::Leaf({:?})", leaf),
- ty::ValTree::Branch(_) => format!("ValTree::Branch(..)"),
+ ty::ValTree::Branch(_) => "ValTree::Branch(..)".to_string(),
};
let val = match literal {
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index efd7357af..a8a453222 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -130,10 +130,9 @@ pub struct UnsafetyCheckResult {
}
rustc_index::newtype_index! {
- pub struct GeneratorSavedLocal {
- derive [HashStable]
- DEBUG_FORMAT = "_{}",
- }
+ #[derive(HashStable)]
+ #[debug_format = "_{}"]
+ pub struct GeneratorSavedLocal {}
}
/// The layout of generator state.
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 4e06d9101..887ee5715 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -230,7 +230,7 @@ where
}
/// Format a string showing the start line and column, and end line and column within a file.
-pub fn source_range_no_file<'tcx>(tcx: TyCtxt<'tcx>, span: Span) -> String {
+pub fn source_range_no_file(tcx: TyCtxt<'_>, span: Span) -> String {
let source_map = tcx.sess.source_map();
let start = source_map.lookup_char_pos(span.lo());
let end = source_map.lookup_char_pos(span.hi());
@@ -322,7 +322,7 @@ fn block_span_viewable<'tcx>(
Some(SpanViewable { bb, span, id, tooltip })
}
-fn compute_block_span<'tcx>(data: &BasicBlockData<'tcx>, body_span: Span) -> Span {
+fn compute_block_span(data: &BasicBlockData<'_>, body_span: Span) -> Span {
let mut span = data.terminator().source_info.span;
for statement_span in data.statements.iter().map(|statement| statement.source_info.span) {
// Only combine Spans from the root context, and within the function's body_span.
@@ -522,12 +522,7 @@ where
}
#[inline(always)]
-fn write_coverage_gap<'tcx, W>(
- tcx: TyCtxt<'tcx>,
- lo: BytePos,
- hi: BytePos,
- w: &mut W,
-) -> io::Result<()>
+fn write_coverage_gap<W>(tcx: TyCtxt<'_>, lo: BytePos, hi: BytePos, w: &mut W) -> io::Result<()>
where
W: Write,
{
@@ -582,8 +577,8 @@ where
Ok(())
}
-fn make_html_snippet<'tcx>(
- tcx: TyCtxt<'tcx>,
+fn make_html_snippet(
+ tcx: TyCtxt<'_>,
span: Span,
some_viewable: Option<&SpanViewable>,
) -> Option<String> {
@@ -664,7 +659,7 @@ fn trim_span_hi(span: Span, to_pos: BytePos) -> Span {
if to_pos >= span.hi() { span } else { span.with_hi(cmp::max(span.lo(), to_pos)) }
}
-fn fn_span<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Span {
+fn fn_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
let fn_decl_span = tcx.def_span(def_id);
if let Some(body_span) = hir_body(tcx, def_id).map(|hir_body| hir_body.value.span) {
if fn_decl_span.eq_ctxt(body_span) { fn_decl_span.to(body_span) } else { body_span }
@@ -673,7 +668,7 @@ fn fn_span<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Span {
}
}
-fn hir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<&'tcx rustc_hir::Body<'tcx>> {
+fn hir_body(tcx: TyCtxt<'_>, def_id: DefId) -> Option<&rustc_hir::Body<'_>> {
let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
hir::map::associated_body(hir_node).map(|fn_body_id| tcx.hir().body(fn_body_id))
}
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 5ba053820..52c2b10cb 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -320,8 +320,10 @@ pub enum StatementKind<'tcx> {
/// <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/> for
/// more details.
///
- /// For code that is not specific to stacked borrows, you should consider retags to read
- /// and modify the place in an opaque way.
+ /// For code that is not specific to stacked borrows, you should consider retags to read and
+ /// modify the place in an opaque way.
+ ///
+ /// Only `RetagKind::Default` and `RetagKind::FnEntry` are permitted.
Retag(RetagKind, Box<Place<'tcx>>),
/// Encodes a user's type ascription. These need to be preserved
@@ -510,6 +512,16 @@ pub struct CopyNonOverlapping<'tcx> {
/// must also be `cleanup`. This is a part of the type system and checked statically, so it is
/// still an error to have such an edge in the CFG even if it's known that it won't be taken at
/// runtime.
+/// 4. The control flow between cleanup blocks must look like an upside down tree. Roughly
+/// speaking, this means that control flow that looks like a V is allowed, while control flow
+/// that looks like a W is not. This is necessary to ensure that landing pad information can be
+/// correctly codegened on MSVC. More precisely:
+///
+/// Begin with the standard control flow graph `G`. Modify `G` as follows: for any two cleanup
+/// vertices `u` and `v` such that `u` dominates `v`, contract `u` and `v` into a single vertex,
+/// deleting self edges and duplicate edges in the process. Now remove all vertices from `G`
+/// that are not cleanup vertices or are not reachable. The resulting graph must be an inverted
+/// tree, that is each vertex may have at most one successor and there may be no cycles.
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
pub enum TerminatorKind<'tcx> {
/// Block has one successor; we continue execution there.
@@ -526,12 +538,6 @@ pub enum TerminatorKind<'tcx> {
SwitchInt {
/// The discriminant value being tested.
discr: Operand<'tcx>,
-
- /// The type of value being tested.
- /// This is always the same as the type of `discr`.
- /// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing.
- switch_ty: Ty<'tcx>,
-
targets: SwitchTargets,
},
@@ -568,14 +574,13 @@ pub enum TerminatorKind<'tcx> {
Unreachable,
/// The behavior of this statement differs significantly before and after drop elaboration.
- /// After drop elaboration, `Drop` executes the drop glue for the specified place, after which
- /// it continues execution/unwinds at the given basic blocks. It is possible that executing drop
- /// glue is special - this would be part of Rust's memory model. (**FIXME**: due we have an
- /// issue tracking if drop glue has any interesting semantics in addition to those of a function
- /// call?)
- ///
- /// `Drop` before drop elaboration is a *conditional* execution of the drop glue. Specifically, the
- /// `Drop` will be executed if...
+ ///
+ /// After drop elaboration: `Drop` terminators are a complete nop for types that have no drop
+ /// glue. For other types, `Drop` terminators behave exactly like a call to
+ /// `core::mem::drop_in_place` with a pointer to the given place.
+ ///
+ /// `Drop` before drop elaboration is a *conditional* execution of the drop glue. Specifically,
+ /// the `Drop` will be executed if...
///
/// **Needs clarification**: End of that sentence. This in effect should document the exact
/// behavior of drop elaboration. The following sounds vaguely right, but I'm not quite sure:
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index fa3adafd4..599f0b9d3 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -32,8 +32,9 @@ impl<'tcx> PlaceTy<'tcx> {
/// not carry a `Ty` for `T`.)
///
/// Note that the resulting type has not been normalized.
+ #[instrument(level = "debug", skip(tcx), ret)]
pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> {
- let answer = match self.ty.kind() {
+ match self.ty.kind() {
ty::Adt(adt_def, substs) => {
let variant_def = match self.variant_index {
None => adt_def.non_enum_variant(),
@@ -47,9 +48,7 @@ impl<'tcx> PlaceTy<'tcx> {
}
ty::Tuple(tys) => tys[f.index()],
_ => bug!("extracting field of non-tuple non-adt: {:?}", self),
- };
- debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer);
- answer
+ }
}
/// Convenience wrapper around `projection_ty_core` for
@@ -234,7 +233,7 @@ impl<'tcx> Operand<'tcx> {
{
match self {
&Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
- &Operand::Constant(ref c) => c.literal.ty(),
+ Operand::Constant(c) => c.literal.ty(),
}
}
}
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 4ea333cff..6e905224c 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -1,7 +1,4 @@
-use crate::mir;
-use crate::mir::interpret::Scalar;
-use crate::ty::{self, Ty, TyCtxt};
-use smallvec::{smallvec, SmallVec};
+use smallvec::SmallVec;
use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind};
use rustc_ast::InlineAsmTemplatePiece;
@@ -77,7 +74,7 @@ impl SwitchTargets {
}
/// Finds the `BasicBlock` to which this `SwitchInt` will branch given the
- /// specific value. This cannot fail, as it'll return the `otherwise`
+ /// specific value. This cannot fail, as it'll return the `otherwise`
/// branch if there's not a specific match for the value.
pub fn target_for_value(&self, value: u128) -> BasicBlock {
self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise())
@@ -131,17 +128,8 @@ impl<'tcx> Terminator<'tcx> {
}
impl<'tcx> TerminatorKind<'tcx> {
- pub fn if_(
- tcx: TyCtxt<'tcx>,
- cond: Operand<'tcx>,
- t: BasicBlock,
- f: BasicBlock,
- ) -> TerminatorKind<'tcx> {
- TerminatorKind::SwitchInt {
- discr: cond,
- switch_ty: tcx.types.bool,
- targets: SwitchTargets::static_if(0, f, t),
- }
+ pub fn if_(cond: Operand<'tcx>, t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
+ TerminatorKind::SwitchInt { discr: cond, targets: SwitchTargets::static_if(0, f, t) }
}
pub fn successors(&self) -> Successors<'_> {
@@ -264,11 +252,9 @@ impl<'tcx> TerminatorKind<'tcx> {
}
}
- pub fn as_switch(&self) -> Option<(&Operand<'tcx>, Ty<'tcx>, &SwitchTargets)> {
+ pub fn as_switch(&self) -> Option<(&Operand<'tcx>, &SwitchTargets)> {
match self {
- TerminatorKind::SwitchInt { discr, switch_ty, targets } => {
- Some((discr, *switch_ty, targets))
- }
+ TerminatorKind::SwitchInt { discr, targets } => Some((discr, targets)),
_ => None,
}
}
@@ -403,21 +389,12 @@ impl<'tcx> TerminatorKind<'tcx> {
match *self {
Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
Goto { .. } => vec!["".into()],
- SwitchInt { ref targets, switch_ty, .. } => ty::tls::with(|tcx| {
- let param_env = ty::ParamEnv::empty();
- let switch_ty = tcx.lift(switch_ty).unwrap();
- let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
- targets
- .values
- .iter()
- .map(|&u| {
- mir::ConstantKind::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
- .to_string()
- .into()
- })
- .chain(iter::once("otherwise".into()))
- .collect()
- }),
+ SwitchInt { ref targets, .. } => targets
+ .values
+ .iter()
+ .map(|&u| Cow::Owned(u.to_string()))
+ .chain(iter::once("otherwise".into()))
+ .collect(),
Call { target: Some(_), cleanup: Some(_), .. } => {
vec!["return".into(), "unwind".into()]
}
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index 55b2c5927..0b461d1ce 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -302,7 +302,7 @@ pub fn reachable<'a, 'tcx>(
}
/// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`.
-pub fn reachable_as_bitset<'tcx>(body: &Body<'tcx>) -> BitSet<BasicBlock> {
+pub fn reachable_as_bitset(body: &Body<'_>) -> BitSet<BasicBlock> {
let mut iter = preorder(body);
(&mut iter).for_each(drop);
iter.visited
diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs
index e7cd497b2..d44c6809b 100644
--- a/compiler/rustc_middle/src/mir/type_visitable.rs
+++ b/compiler/rustc_middle/src/mir/type_visitable.rs
@@ -4,6 +4,6 @@ use super::*;
impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index b21f50ae5..1a264d2d5 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -3,15 +3,15 @@
//! ## Overview
//!
//! There are two visitors, one for immutable and one for mutable references,
-//! but both are generated by the following macro. The code is written according
-//! to the following conventions:
+//! but both are generated by the `make_mir_visitor` macro.
+//! The code is written according to the following conventions:
//!
//! - introduce a `visit_foo` and a `super_foo` method for every MIR type
//! - `visit_foo`, by default, calls `super_foo`
//! - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
//!
-//! This allows you as a user to override `visit_foo` for types are
-//! interested in, and invoke (within that method) call
+//! This allows you to override `visit_foo` for types you are
+//! interested in, and invoke (within that method call)
//! `self.super_foo` to get the default behavior. Just as in an OO
//! language, you should never call `super` methods ordinarily except
//! in that circumstance.
@@ -477,11 +477,9 @@ macro_rules! make_mir_visitor {
TerminatorKind::SwitchInt {
discr,
- switch_ty,
targets: _
} => {
self.visit_operand(discr, location);
- self.visit_ty($(& $mutability)? *switch_ty, TyContext::Location(location));
}
TerminatorKind::Drop {
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 880632561..e4bb3ce3d 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -15,7 +15,15 @@ use rustc_span::{Span, DUMMY_SP};
/// The `Key` trait controls what types can legally be used as the key
/// for a query.
pub trait Key: Sized {
- type CacheSelector = DefaultCacheSelector<Self>;
+ // N.B. Most of the keys down below have `type CacheSelector = DefaultCacheSelector<Self>;`,
+ // it would be reasonable to use associated type defaults, to remove the duplication...
+ //
+ // ...But r-a doesn't support them yet and using a default here causes r-a to not infer
+ // return types of queries which is very annoying. Thus, until r-a support associated
+ // type defaults, plese restrain from using them here <3
+ //
+ // r-a issue: <https://github.com/rust-lang/rust-analyzer/issues/13693>
+ type CacheSelector;
/// Given an instance of this key, what crate is it referring to?
/// This is used to find the provider.
@@ -37,6 +45,8 @@ pub trait Key: Sized {
}
impl Key for () {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -48,6 +58,8 @@ impl Key for () {
}
impl<'tcx> Key for ty::InstanceDef<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -59,6 +71,8 @@ impl<'tcx> Key for ty::InstanceDef<'tcx> {
}
impl<'tcx> Key for ty::Instance<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -70,6 +84,8 @@ impl<'tcx> Key for ty::Instance<'tcx> {
}
impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -81,6 +97,8 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
}
impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -92,6 +110,8 @@ impl<'tcx> Key for (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
}
impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -145,6 +165,8 @@ impl Key for LocalDefId {
}
impl Key for DefId {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.krate == LOCAL_CRATE
@@ -159,6 +181,8 @@ impl Key for DefId {
}
impl Key for ty::WithOptConstParam<LocalDefId> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -169,6 +193,8 @@ impl Key for ty::WithOptConstParam<LocalDefId> {
}
impl Key for SimplifiedType {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -179,6 +205,8 @@ impl Key for SimplifiedType {
}
impl Key for (DefId, DefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -189,6 +217,8 @@ impl Key for (DefId, DefId) {
}
impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -199,6 +229,8 @@ impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) {
}
impl Key for (DefId, LocalDefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -209,6 +241,8 @@ impl Key for (DefId, LocalDefId) {
}
impl Key for (LocalDefId, DefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -219,6 +253,8 @@ impl Key for (LocalDefId, DefId) {
}
impl Key for (LocalDefId, LocalDefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -229,6 +265,8 @@ impl Key for (LocalDefId, LocalDefId) {
}
impl Key for (DefId, Option<Ident>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -243,6 +281,8 @@ impl Key for (DefId, Option<Ident>) {
}
impl Key for (DefId, LocalDefId, Ident) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -253,6 +293,8 @@ impl Key for (DefId, LocalDefId, Ident) {
}
impl Key for (CrateNum, DefId) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0 == LOCAL_CRATE
@@ -263,6 +305,8 @@ impl Key for (CrateNum, DefId) {
}
impl Key for (CrateNum, SimplifiedType) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0 == LOCAL_CRATE
@@ -273,6 +317,8 @@ impl Key for (CrateNum, SimplifiedType) {
}
impl Key for (DefId, SimplifiedType) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -283,6 +329,8 @@ impl Key for (DefId, SimplifiedType) {
}
impl<'tcx> Key for SubstsRef<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -293,6 +341,8 @@ impl<'tcx> Key for SubstsRef<'tcx> {
}
impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.krate == LOCAL_CRATE
@@ -303,6 +353,8 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
}
impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
(self.0).def.did.krate == LOCAL_CRATE
@@ -313,6 +365,8 @@ impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
}
impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -323,6 +377,8 @@ impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
}
impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.1.def_id().krate == LOCAL_CRATE
@@ -333,6 +389,8 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
}
impl<'tcx> Key for (ty::Const<'tcx>, mir::Field) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -343,6 +401,8 @@ impl<'tcx> Key for (ty::Const<'tcx>, mir::Field) {
}
impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -353,6 +413,8 @@ impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
}
impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.def_id().krate == LOCAL_CRATE
@@ -363,6 +425,8 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
}
impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.def_id().krate == LOCAL_CRATE
@@ -373,6 +437,8 @@ impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
}
impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.0.def_id().krate == LOCAL_CRATE
@@ -383,6 +449,8 @@ impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
}
impl<'tcx> Key for GenericArg<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -393,6 +461,8 @@ impl<'tcx> Key for GenericArg<'tcx> {
}
impl<'tcx> Key for mir::ConstantKind<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -403,6 +473,8 @@ impl<'tcx> Key for mir::ConstantKind<'tcx> {
}
impl<'tcx> Key for ty::Const<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -413,6 +485,8 @@ impl<'tcx> Key for ty::Const<'tcx> {
}
impl<'tcx> Key for Ty<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -429,6 +503,8 @@ impl<'tcx> Key for Ty<'tcx> {
}
impl<'tcx> Key for TyAndLayout<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -439,6 +515,8 @@ impl<'tcx> Key for TyAndLayout<'tcx> {
}
impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -449,6 +527,8 @@ impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
}
impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -459,6 +539,8 @@ impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
}
impl<'tcx> Key for ty::ParamEnv<'tcx> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -469,6 +551,8 @@ impl<'tcx> Key for ty::ParamEnv<'tcx> {
}
impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
self.value.query_crate_is_local()
@@ -479,6 +563,8 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
}
impl Key for Symbol {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -489,6 +575,8 @@ impl Key for Symbol {
}
impl Key for Option<Symbol> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -501,6 +589,8 @@ impl Key for Option<Symbol> {
/// Canonical query goals correspond to abstract trait operations that
/// are not tied to any crate in particular.
impl<'tcx, T> Key for Canonical<'tcx, T> {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -512,6 +602,8 @@ impl<'tcx, T> Key for Canonical<'tcx, T> {
}
impl Key for (Symbol, u32, u32) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -523,6 +615,8 @@ impl Key for (Symbol, u32, u32) {
}
impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -534,6 +628,8 @@ impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) {
}
impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -545,6 +641,8 @@ impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
}
impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -556,6 +654,8 @@ impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
}
impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -567,6 +667,8 @@ impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
}
impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
@@ -578,6 +680,8 @@ impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
}
impl Key for HirId {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
true
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 34415e2a1..6bbf7fa39 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -27,12 +27,12 @@ rustc_queries! {
}
query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt {
- eval_always
+ feedable
no_hash
desc { "getting the resolver outputs" }
}
- query resolver_for_lowering(_: ()) -> &'tcx Steal<ty::ResolverAstLowering> {
+ query resolver_for_lowering(_: ()) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
feedable
no_hash
desc { "getting the resolver for lowering" }
@@ -43,6 +43,8 @@ rustc_queries! {
/// This span is meant for dep-tracking rather than diagnostics. It should not be used outside
/// of rustc_middle::hir::source_map.
query source_span(key: LocalDefId) -> Span {
+ // Accesses untracked data
+ eval_always
desc { "getting the source span" }
}
@@ -140,7 +142,7 @@ rustc_queries! {
/// Given the def_id of a const-generic parameter, computes the associated default const
/// parameter. e.g. `fn example<const N: usize=3>` called on `N` would return `3`.
- query const_param_default(param: DefId) -> ty::Const<'tcx> {
+ query const_param_default(param: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> {
desc { |tcx| "computing const default for a given parameter `{}`", tcx.def_path_str(param) }
cache_on_disk_if { param.is_local() }
separate_provide_extern
@@ -167,7 +169,7 @@ rustc_queries! {
separate_provide_extern
}
- query collect_trait_impl_trait_tys(key: DefId)
+ query collect_return_position_impl_trait_in_trait_tys(key: DefId)
-> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>
{
desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" }
@@ -276,7 +278,7 @@ rustc_queries! {
/// ```
///
/// Bounds from the parent (e.g. with nested impl trait) are not included.
- query item_bounds(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
+ query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
}
@@ -741,7 +743,7 @@ rustc_queries! {
/// Given an `impl_id`, return the trait it implements.
/// Return `None` if this is an inherent impl.
- query impl_trait_ref(impl_id: DefId) -> Option<ty::TraitRef<'tcx>> {
+ query impl_trait_ref(impl_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) }
cache_on_disk_if { impl_id.is_local() }
separate_provide_extern
@@ -1677,7 +1679,7 @@ rustc_queries! {
/// Gets the name of the crate.
query crate_name(_: CrateNum) -> Symbol {
- eval_always
+ feedable
desc { "fetching what a crate is named" }
separate_provide_extern
}
@@ -1843,7 +1845,7 @@ rustc_queries! {
desc { "getting codegen unit `{sym}`" }
}
- query unused_generic_params(key: ty::InstanceDef<'tcx>) -> FiniteBitSet<u32> {
+ query unused_generic_params(key: ty::InstanceDef<'tcx>) -> UnusedGenericParams {
cache_on_disk_if { key.def_id().is_local() }
desc {
|tcx| "determining which generic parameters are unused by `{}`",
@@ -1861,7 +1863,7 @@ rustc_queries! {
/// This query returns an `&Arc` because codegen backends need the value even after the `TyCtxt`
/// has been destroyed.
query output_filenames(_: ()) -> &'tcx Arc<OutputFilenames> {
- eval_always
+ feedable
desc { "getting output filenames" }
}
@@ -2045,7 +2047,7 @@ rustc_queries! {
}
query features_query(_: ()) -> &'tcx rustc_feature::Features {
- eval_always
+ feedable
desc { "looking up enabled feature gates" }
}
@@ -2121,7 +2123,7 @@ rustc_queries! {
desc { "checking to see if `{}` permits being left zeroed", key.ty }
}
- query compare_assoc_const_impl_item_with_trait_item(
+ query compare_impl_const(
key: (LocalDefId, DefId)
) -> Result<(), ErrorGuaranteed> {
desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) }
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 8bef9dfe0..5f320708c 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -9,6 +9,7 @@
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::RangeEnd;
@@ -35,9 +36,8 @@ macro_rules! thir_with_elements {
$(
newtype_index! {
#[derive(HashStable)]
- pub struct $id {
- DEBUG_FORMAT = $format
- }
+ #[debug_format = $format]
+ pub struct $id {}
}
)*
@@ -576,6 +576,12 @@ impl<'tcx> Pat<'tcx> {
}
}
+impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ format!("{}", self).into_diagnostic_arg()
+ }
+}
+
#[derive(Clone, Debug, HashStable)]
pub struct Ascription<'tcx> {
pub annotation: CanonicalUserTypeAnnotation<'tcx>,
diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs
index 6d4af8bea..fcc8f457a 100644
--- a/compiler/rustc_middle/src/traits/chalk.rs
+++ b/compiler/rustc_middle/src/traits/chalk.rs
@@ -159,18 +159,20 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
}
chalk_ir::TyKind::Array(ty, len) => Some(write!(fmt, "[{:?}; {:?}]", ty, len)),
chalk_ir::TyKind::Slice(ty) => Some(write!(fmt, "[{:?}]", ty)),
- chalk_ir::TyKind::Tuple(len, substs) => Some((|| {
- write!(fmt, "(")?;
- for (idx, substitution) in substs.interned().iter().enumerate() {
- if idx == *len && *len != 1 {
- // Don't add a trailing comma if the tuple has more than one element
- write!(fmt, "{:?}", substitution)?;
- } else {
- write!(fmt, "{:?},", substitution)?;
+ chalk_ir::TyKind::Tuple(len, substs) => Some(
+ try {
+ write!(fmt, "(")?;
+ for (idx, substitution) in substs.interned().iter().enumerate() {
+ if idx == *len && *len != 1 {
+ // Don't add a trailing comma if the tuple has more than one element
+ write!(fmt, "{:?}", substitution)?;
+ } else {
+ write!(fmt, "{:?},", substitution)?;
+ }
}
- }
- write!(fmt, ")")
- })()),
+ write!(fmt, ")")?;
+ },
+ ),
_ => None,
}
}
@@ -210,7 +212,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
Box::new(chalk_ir::TyData { kind: ty, flags: flags })
}
- fn ty_data<'a>(self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> {
+ fn ty_data(self, ty: &Self::InternedType) -> &chalk_ir::TyData<Self> {
ty
}
@@ -218,10 +220,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
Box::new(lifetime)
}
- fn lifetime_data<'a>(
- self,
- lifetime: &'a Self::InternedLifetime,
- ) -> &'a chalk_ir::LifetimeData<Self> {
+ fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &chalk_ir::LifetimeData<Self> {
&lifetime
}
@@ -229,7 +228,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
Box::new(constant)
}
- fn const_data<'a>(self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> {
+ fn const_data(self, constant: &Self::InternedConst) -> &chalk_ir::ConstData<Self> {
&constant
}
@@ -246,10 +245,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
Box::new(data)
}
- fn generic_arg_data<'a>(
- self,
- data: &'a Self::InternedGenericArg,
- ) -> &'a chalk_ir::GenericArgData<Self> {
+ fn generic_arg_data(self, data: &Self::InternedGenericArg) -> &chalk_ir::GenericArgData<Self> {
&data
}
@@ -257,7 +253,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
Box::new(goal)
}
- fn goal_data<'a>(self, goal: &'a Self::InternedGoal) -> &'a chalk_ir::GoalData<Self> {
+ fn goal_data(self, goal: &Self::InternedGoal) -> &chalk_ir::GoalData<Self> {
&goal
}
@@ -268,7 +264,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
data.into_iter().collect::<Result<Vec<_>, _>>()
}
- fn goals_data<'a>(self, goals: &'a Self::InternedGoals) -> &'a [chalk_ir::Goal<Self>] {
+ fn goals_data(self, goals: &Self::InternedGoals) -> &[chalk_ir::Goal<Self>] {
goals
}
@@ -279,10 +275,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
data.into_iter().collect::<Result<Vec<_>, _>>()
}
- fn substitution_data<'a>(
+ fn substitution_data(
self,
- substitution: &'a Self::InternedSubstitution,
- ) -> &'a [chalk_ir::GenericArg<Self>] {
+ substitution: &Self::InternedSubstitution,
+ ) -> &[chalk_ir::GenericArg<Self>] {
substitution
}
@@ -293,10 +289,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
Box::new(data)
}
- fn program_clause_data<'a>(
+ fn program_clause_data(
self,
- clause: &'a Self::InternedProgramClause,
- ) -> &'a chalk_ir::ProgramClauseData<Self> {
+ clause: &Self::InternedProgramClause,
+ ) -> &chalk_ir::ProgramClauseData<Self> {
&clause
}
@@ -307,10 +303,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
data.into_iter().collect::<Result<Vec<_>, _>>()
}
- fn program_clauses_data<'a>(
+ fn program_clauses_data(
self,
- clauses: &'a Self::InternedProgramClauses,
- ) -> &'a [chalk_ir::ProgramClause<Self>] {
+ clauses: &Self::InternedProgramClauses,
+ ) -> &[chalk_ir::ProgramClause<Self>] {
clauses
}
@@ -321,10 +317,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
data.into_iter().collect::<Result<Vec<_>, _>>()
}
- fn quantified_where_clauses_data<'a>(
+ fn quantified_where_clauses_data(
self,
- clauses: &'a Self::InternedQuantifiedWhereClauses,
- ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] {
+ clauses: &Self::InternedQuantifiedWhereClauses,
+ ) -> &[chalk_ir::QuantifiedWhereClause<Self>] {
clauses
}
@@ -335,10 +331,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
data.into_iter().collect::<Result<Vec<_>, _>>()
}
- fn variable_kinds_data<'a>(
+ fn variable_kinds_data(
self,
- parameter_kinds: &'a Self::InternedVariableKinds,
- ) -> &'a [chalk_ir::VariableKind<Self>] {
+ parameter_kinds: &Self::InternedVariableKinds,
+ ) -> &[chalk_ir::VariableKind<Self>] {
parameter_kinds
}
@@ -349,10 +345,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
data.into_iter().collect::<Result<Vec<_>, _>>()
}
- fn canonical_var_kinds_data<'a>(
+ fn canonical_var_kinds_data(
self,
- canonical_var_kinds: &'a Self::InternedCanonicalVarKinds,
- ) -> &'a [chalk_ir::CanonicalVarKind<Self>] {
+ canonical_var_kinds: &Self::InternedCanonicalVarKinds,
+ ) -> &[chalk_ir::CanonicalVarKind<Self>] {
canonical_var_kinds
}
@@ -363,10 +359,10 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
data.into_iter().collect::<Result<Vec<_>, _>>()
}
- fn constraints_data<'a>(
+ fn constraints_data(
self,
- constraints: &'a Self::InternedConstraints,
- ) -> &'a [chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] {
+ constraints: &Self::InternedConstraints,
+ ) -> &[chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] {
constraints
}
@@ -377,10 +373,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
data.into_iter().collect::<Result<Vec<_>, _>>()
}
- fn variances_data<'a>(
- self,
- variances: &'a Self::InternedVariances,
- ) -> &'a [chalk_ir::Variance] {
+ fn variances_data(self, variances: &Self::InternedVariances) -> &[chalk_ir::Variance] {
variances
}
}
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 143435cb2..d00b26a5a 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -250,7 +250,7 @@ pub enum ObligationCauseCode<'tcx> {
TupleElem,
/// This is the trait reference from the given projection.
- ProjectionWf(ty::ProjectionTy<'tcx>),
+ ProjectionWf(ty::AliasTy<'tcx>),
/// Must satisfy all of the where-clause predicates of the
/// given item.
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index fb152b63f..615154a55 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -8,30 +8,25 @@
use crate::error::DropCheckOverflow;
use crate::infer::canonical::{Canonical, QueryResponse};
use crate::ty::error::TypeError;
-use crate::ty::subst::{GenericArg, SubstsRef};
+use crate::ty::subst::GenericArg;
use crate::ty::{self, Ty, TyCtxt};
-use rustc_hir::def_id::DefId;
use rustc_span::source_map::Span;
-use std::iter::FromIterator;
pub mod type_op {
use crate::ty::fold::TypeFoldable;
- use crate::ty::subst::UserSubsts;
- use crate::ty::{Predicate, Ty};
- use rustc_hir::def_id::DefId;
+ use crate::ty::{Predicate, Ty, UserType};
use std::fmt;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct AscribeUserType<'tcx> {
pub mir_ty: Ty<'tcx>,
- pub def_id: DefId,
- pub user_substs: UserSubsts<'tcx>,
+ pub user_ty: UserType<'tcx>,
}
impl<'tcx> AscribeUserType<'tcx> {
- pub fn new(mir_ty: Ty<'tcx>, def_id: DefId, user_substs: UserSubsts<'tcx>) -> Self {
- Self { mir_ty, def_id, user_substs }
+ pub fn new(mir_ty: Ty<'tcx>, user_ty: UserType<'tcx>) -> Self {
+ Self { mir_ty, user_ty }
}
}
@@ -77,8 +72,7 @@ pub mod type_op {
}
}
-pub type CanonicalProjectionGoal<'tcx> =
- Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
+pub type CanonicalProjectionGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
@@ -98,7 +92,7 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
-#[derive(Copy, Clone, Debug, HashStable)]
+#[derive(Copy, Clone, Debug, HashStable, PartialEq, Eq)]
pub struct NoSolution;
pub type Fallible<T> = Result<T, NoSolution>;
@@ -219,6 +213,5 @@ pub struct NormalizationResult<'tcx> {
pub enum OutlivesBound<'tcx> {
RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
- RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
- RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>),
+ RegionSubAlias(ty::Region<'tcx>, ty::AliasTy<'tcx>),
}
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index ec69864c9..1cc9fd526 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -131,7 +131,9 @@ pub enum SelectionCandidate<'tcx> {
/// Implementation of a `Fn`-family trait by one of the anonymous types
/// generated for an `||` expression.
- ClosureCandidate,
+ ClosureCandidate {
+ is_const: bool,
+ },
/// Implementation of a `Generator` trait by one of the anonymous types
/// generated for a generator.
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index cccedc9ec..aad5b2fbe 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -60,7 +60,7 @@ pub enum OverlapMode {
}
impl OverlapMode {
- pub fn get<'tcx>(tcx: TyCtxt<'tcx>, trait_id: DefId) -> OverlapMode {
+ pub fn get(tcx: TyCtxt<'_>, trait_id: DefId) -> OverlapMode {
let with_negative_coherence = tcx.features().with_negative_coherence;
let strict_coherence = tcx.has_attr(trait_id, sym::rustc_strict_coherence);
@@ -180,6 +180,7 @@ impl Iterator for Ancestors<'_> {
}
/// Information about the most specialized definition of an associated item.
+#[derive(Debug)]
pub struct LeafDef {
/// The associated item described by this `LeafDef`.
pub item: ty::AssocItem,
@@ -253,11 +254,11 @@ impl<'tcx> Ancestors<'tcx> {
///
/// Returns `Err` if an error was reported while building the specialization
/// graph.
-pub fn ancestors<'tcx>(
- tcx: TyCtxt<'tcx>,
+pub fn ancestors(
+ tcx: TyCtxt<'_>,
trait_def_id: DefId,
start_from_impl: DefId,
-) -> Result<Ancestors<'tcx>, ErrorGuaranteed> {
+) -> Result<Ancestors<'_>, ErrorGuaranteed> {
let specialization_graph = tcx.specialization_graph_of(trait_def_id);
if let Some(reported) = specialization_graph.has_errored {
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index cd147d7e5..b9c5a4e0d 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -89,7 +89,9 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
Err(TypeError::Sorts(relate::expected_found(self, a, b)))
}
- (&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(self.tcx().ty_error()),
+ (&ty::Error(guar), _) | (_, &ty::Error(guar)) => {
+ Ok(self.tcx().ty_error_with_guaranteed(guar))
+ }
_ => relate::super_relate_tys(self, a, b),
}
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index 7036c4a7b..8ce06404d 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -131,7 +131,7 @@ impl<'tcx> OverloadedDeref<'tcx> {
.find(|m| m.kind == ty::AssocKind::Fn)
.unwrap()
.def_id;
- tcx.mk_fn_def(method_def_id, tcx.mk_substs_trait(source, []))
+ tcx.mk_fn_def(method_def_id, [source])
}
}
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index 55ee5bd2f..bb7fba3ee 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -37,6 +37,11 @@ impl AssocItem {
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
}
+ /// Gets the defaultness of the associated item.
+ /// To get the default associated type, use the [`type_of`] query on the
+ /// [`DefId`] of the type.
+ ///
+ /// [`type_of`]: crate::ty::TyCtxt::type_of
pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness {
tcx.impl_defaultness(self.def_id)
}
@@ -72,7 +77,7 @@ impl AssocItem {
ty::AssocKind::Fn => {
// We skip the binder here because the binder would deanonymize all
// late-bound regions, and we don't want method signatures to show up
- // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
+ // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
// regions just fine, showing `fn(&MyType)`.
tcx.fn_sig(self.def_id).skip_binder().to_string()
}
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index d00553cba..6ade8935f 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -238,10 +238,7 @@ impl<'tcx> CapturedPlace<'tcx> {
}
}
-fn symbols_for_closure_captures<'tcx>(
- tcx: TyCtxt<'tcx>,
- def_id: (LocalDefId, LocalDefId),
-) -> Vec<Symbol> {
+fn symbols_for_closure_captures(tcx: TyCtxt<'_>, def_id: (LocalDefId, LocalDefId)) -> Vec<Symbol> {
let typeck_results = tcx.typeck(def_id.0);
let captures = typeck_results.closure_min_captures_flattened(def_id.1);
captures.into_iter().map(|captured_place| captured_place.to_symbol(tcx)).collect()
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 75f2d45ea..8cc8286c1 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -310,7 +310,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> {
fn decode(decoder: &mut D) -> Self {
- let consts: ty::ConstS<'tcx> = Decodable::decode(decoder);
+ let consts: ty::ConstData<'tcx> = Decodable::decode(decoder);
decoder.interner().mk_const(consts.kind, consts.ty)
}
}
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index c2be08e49..65cbac3e8 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -14,10 +14,10 @@ pub use int::*;
pub use kind::*;
pub use valtree::*;
-/// Use this rather than `ConstS`, whenever possible.
+/// 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 Interned<'tcx, ConstS<'tcx>>);
+pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
impl<'tcx> fmt::Debug for Const<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -30,13 +30,13 @@ impl<'tcx> fmt::Debug for Const<'tcx> {
/// Typed constant value.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
-pub struct ConstS<'tcx> {
+pub struct ConstData<'tcx> {
pub ty: Ty<'tcx>,
pub kind: ConstKind<'tcx>,
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(ConstS<'_>, 40);
+static_assert_size!(ConstData<'_>, 40);
impl<'tcx> Const<'tcx> {
#[inline]
@@ -239,7 +239,7 @@ impl<'tcx> Const<'tcx> {
}
}
-pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> {
+pub fn const_param_default(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Const<'_>> {
let default_def_id = match tcx.hir().get_by_def_id(def_id.expect_local()) {
hir::Node::GenericParam(hir::GenericParam {
kind: hir::GenericParamKind::Const { default: Some(ac), .. },
@@ -250,5 +250,5 @@ pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx
"`const_param_default` expected a generic parameter with a constant"
),
};
- Const::from_anon_const(tcx, default_def_id)
+ ty::EarlyBinder(Const::from_anon_const(tcx, default_def_id))
}
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index f3186e1c3..48958e0d9 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -2,7 +2,6 @@ use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::Float;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_target::abi::Size;
-use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::num::NonZeroU8;
@@ -233,7 +232,7 @@ impl ScalarInt {
}
#[inline]
- pub fn try_to_machine_usize<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Result<u64, Size> {
+ pub fn try_to_machine_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64)
}
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index becc2b805..d9721863a 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,5 +1,3 @@
-use std::convert::TryInto;
-
use super::Const;
use crate::mir;
use crate::mir::interpret::{AllocId, ConstValue, Scalar};
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index b44bc14ec..ce04d8d21 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -4,8 +4,7 @@
use crate::arena::Arena;
use crate::dep_graph::{DepGraph, DepKindStruct};
-use crate::hir::place::Place as HirPlace;
-use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
+use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
use crate::lint::struct_lint_level;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::resolve_lifetime;
@@ -18,14 +17,13 @@ use crate::thir::Thir;
use crate::traits;
use crate::ty::query::{self, TyCtxtAt};
use crate::ty::{
- self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
- ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid,
- GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
- PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region,
- RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy,
+ self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar,
+ FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
+ ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind,
+ ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy,
Visibility,
};
-use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
+use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
use rustc_ast as ast;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -35,31 +33,26 @@ 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, Lock, Lrc, ReadGuard, RwLock, WorkerLocal};
-use rustc_data_structures::unord::UnordSet;
-use rustc_data_structures::vec_map::VecMap;
+use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, WorkerLocal};
use rustc_errors::{
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
};
use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LOCAL_CRATE};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::Definitions;
-use rustc_hir::hir_id::OwnerId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{
- Constness, ExprKind, HirId, ImplItemKind, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet,
- Node, TraitCandidate, TraitItemKind,
+ Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
};
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
-use rustc_middle::mir::FakeReadCause;
use rustc_query_system::dep_graph::DepNodeIndex;
use rustc_query_system::ich::StableHashingContext;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
-use rustc_session::config::{CrateType, OutputFilenames};
-use rustc_session::cstore::CrateStoreDyn;
+use rustc_session::config::CrateType;
+use rustc_session::cstore::{CrateStoreDyn, Untracked};
use rustc_session::lint::Lint;
use rustc_session::Limit;
use rustc_session::Session;
@@ -76,15 +69,11 @@ use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlag
use std::any::Any;
use std::borrow::Borrow;
use std::cmp::Ordering;
-use std::collections::hash_map::{self, Entry};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter;
use std::mem;
use std::ops::{Bound, Deref};
-use std::sync::Arc;
-
-use super::{ImplPolarity, RvalueScopes};
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
@@ -116,7 +105,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type ListBinderExistentialPredicate = &'tcx List<PolyExistentialPredicate<'tcx>>;
type BinderListTy = Binder<'tcx, &'tcx List<Ty<'tcx>>>;
type ListTy = &'tcx List<Ty<'tcx>>;
- type ProjectionTy = ty::ProjectionTy<'tcx>;
+ type AliasTy = ty::AliasTy<'tcx>;
type ParamTy = ParamTy;
type BoundTy = ty::BoundTy;
type PlaceholderType = ty::PlaceholderType;
@@ -150,7 +139,7 @@ pub struct CtxtInterners<'tcx> {
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
- const_: InternedSet<'tcx, ConstS<'tcx>>,
+ const_: InternedSet<'tcx, ConstData<'tcx>>,
const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
layout: InternedSet<'tcx, LayoutS<VariantIdx>>,
@@ -182,20 +171,12 @@ impl<'tcx> CtxtInterners<'tcx> {
/// Interns a type.
#[allow(rustc::usage_of_ty_tykind)]
#[inline(never)]
- fn intern_ty(
- &self,
- kind: TyKind<'tcx>,
- sess: &Session,
- definitions: &rustc_hir::definitions::Definitions,
- cstore: &CrateStoreDyn,
- source_span: &IndexVec<LocalDefId, Span>,
- ) -> Ty<'tcx> {
+ fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> {
Ty(Interned::new_unchecked(
self.type_
.intern(kind, |kind| {
let flags = super::flags::FlagComputation::for_kind(&kind);
- let stable_hash =
- self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
+ let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
internee: kind,
@@ -212,9 +193,7 @@ impl<'tcx> CtxtInterners<'tcx> {
&self,
flags: &ty::flags::FlagComputation,
sess: &'a Session,
- definitions: &'a rustc_hir::definitions::Definitions,
- cstore: &'a CrateStoreDyn,
- source_span: &'a IndexVec<LocalDefId, Span>,
+ untracked: &'a Untracked,
val: &T,
) -> Fingerprint {
// It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
@@ -223,7 +202,7 @@ impl<'tcx> CtxtInterners<'tcx> {
Fingerprint::ZERO
} else {
let mut hasher = StableHasher::new();
- let mut hcx = StableHashingContext::new(sess, definitions, cstore, source_span);
+ let mut hcx = StableHashingContext::new(sess, untracked);
val.hash_stable(&mut hcx, &mut hasher);
hasher.finish()
}
@@ -234,17 +213,14 @@ impl<'tcx> CtxtInterners<'tcx> {
&self,
kind: Binder<'tcx, PredicateKind<'tcx>>,
sess: &Session,
- definitions: &rustc_hir::definitions::Definitions,
- cstore: &CrateStoreDyn,
- source_span: &IndexVec<LocalDefId, Span>,
+ untracked: &Untracked,
) -> Predicate<'tcx> {
Predicate(Interned::new_unchecked(
self.predicate
.intern(kind, |kind| {
let flags = super::flags::FlagComputation::for_predicate(kind);
- let stable_hash =
- self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
+ let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
internee: kind,
@@ -298,675 +274,13 @@ pub struct CommonConsts<'tcx> {
pub unit: Const<'tcx>,
}
-pub struct LocalTableInContext<'a, V> {
- hir_owner: OwnerId,
- data: &'a ItemLocalMap<V>,
-}
-
-/// Validate that the given HirId (respectively its `local_id` part) can be
-/// safely used as a key in the maps of a TypeckResults. For that to be
-/// the case, the HirId must have the same `owner` as all the other IDs in
-/// this table (signified by `hir_owner`). Otherwise the HirId
-/// would be in a different frame of reference and using its `local_id`
-/// would result in lookup errors, or worse, in silently wrong data being
-/// stored/returned.
-#[inline]
-fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
- if hir_id.owner != hir_owner {
- invalid_hir_id_for_typeck_results(hir_owner, hir_id);
- }
-}
-
-#[cold]
-#[inline(never)]
-fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
- ty::tls::with(|tcx| {
- bug!(
- "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
- tcx.hir().node_to_string(hir_id),
- hir_id.owner,
- hir_owner
- )
- });
-}
-
-impl<'a, V> LocalTableInContext<'a, V> {
- pub fn contains_key(&self, id: hir::HirId) -> bool {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.contains_key(&id.local_id)
- }
-
- pub fn get(&self, id: hir::HirId) -> Option<&V> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.get(&id.local_id)
- }
-
- pub fn iter(&self) -> hash_map::Iter<'_, hir::ItemLocalId, V> {
- self.data.iter()
- }
-}
-
-impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
- type Output = V;
-
- fn index(&self, key: hir::HirId) -> &V {
- self.get(key).expect("LocalTableInContext: key not found")
- }
-}
-
-pub struct LocalTableInContextMut<'a, V> {
- hir_owner: OwnerId,
- data: &'a mut ItemLocalMap<V>,
-}
-
-impl<'a, V> LocalTableInContextMut<'a, V> {
- pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.get_mut(&id.local_id)
- }
-
- pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.entry(id.local_id)
- }
-
- pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.insert(id.local_id, val)
- }
-
- pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.data.remove(&id.local_id)
- }
-}
-
-/// Whenever a value may be live across a generator yield, the type of that value winds up in the
-/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
-/// captured types that can be useful for diagnostics. In particular, it stores the span that
-/// caused a given type to be recorded, along with the scope that enclosed the value (which can
-/// be used to find the await that the value is live across).
-///
-/// For example:
-///
-/// ```ignore (pseudo-Rust)
-/// async move {
-/// let x: T = expr;
-/// foo.await
-/// ...
-/// }
-/// ```
-///
-/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
-/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
-#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct GeneratorInteriorTypeCause<'tcx> {
- /// Type of the captured binding.
- pub ty: Ty<'tcx>,
- /// Span of the binding that was captured.
- pub span: Span,
- /// Span of the scope of the captured binding.
- pub scope_span: Option<Span>,
- /// Span of `.await` or `yield` expression.
- pub yield_span: Span,
- /// Expr which the type evaluated from.
- pub expr: Option<hir::HirId>,
-}
-
-// This type holds diagnostic information on generators and async functions across crate boundaries
-// and is used to provide better error messages
-#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
-pub struct GeneratorDiagnosticData<'tcx> {
- pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
- pub hir_owner: DefId,
- pub nodes_types: ItemLocalMap<Ty<'tcx>>,
- pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
-}
-
-#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
-pub struct TypeckResults<'tcx> {
- /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
- pub hir_owner: OwnerId,
-
- /// Resolved definitions for `<T>::X` associated paths and
- /// method calls, including those of overloaded operators.
- type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
-
- /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
- /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
- /// about the field you also need definition of the variant to which the field
- /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
- field_indices: ItemLocalMap<usize>,
-
- /// Stores the types for various nodes in the AST. Note that this table
- /// is not guaranteed to be populated outside inference. See
- /// typeck::check::fn_ctxt for details.
- node_types: ItemLocalMap<Ty<'tcx>>,
-
- /// Stores the type parameters which were substituted to obtain the type
- /// of this node. This only applies to nodes that refer to entities
- /// parameterized by type parameters, such as generic fns, types, or
- /// other items.
- node_substs: ItemLocalMap<SubstsRef<'tcx>>,
-
- /// This will either store the canonicalized types provided by the user
- /// or the substitutions that the user explicitly gave (if any) attached
- /// to `id`. These will not include any inferred values. The canonical form
- /// is used to capture things like `_` or other unspecified values.
- ///
- /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
- /// canonical substitutions would include only `for<X> { Vec<X> }`.
- ///
- /// See also `AscribeUserType` statement in MIR.
- user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
-
- /// Stores the canonicalized types provided by the user. See also
- /// `AscribeUserType` statement in MIR.
- pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
-
- adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
-
- /// Stores the actual binding mode for all instances of hir::BindingAnnotation.
- pat_binding_modes: ItemLocalMap<BindingMode>,
-
- /// Stores the types which were implicitly dereferenced in pattern binding modes
- /// for later usage in THIR lowering. For example,
- ///
- /// ```
- /// match &&Some(5i32) {
- /// Some(n) => {},
- /// _ => {},
- /// }
- /// ```
- /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
- ///
- /// See:
- /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
- pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
-
- /// Records the reasons that we picked the kind of each closure;
- /// not all closures are present in the map.
- closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
-
- /// For each fn, records the "liberated" types of its arguments
- /// and return type. Liberated means that all bound regions
- /// (including late-bound regions) are replaced with free
- /// equivalents. This table is not used in codegen (since regions
- /// are erased there) and hence is not serialized to metadata.
- ///
- /// This table also contains the "revealed" values for any `impl Trait`
- /// that appear in the signature and whose values are being inferred
- /// by this function.
- ///
- /// # Example
- ///
- /// ```rust
- /// # use std::fmt::Debug;
- /// fn foo(x: &u32) -> impl Debug { *x }
- /// ```
- ///
- /// The function signature here would be:
- ///
- /// ```ignore (illustrative)
- /// for<'a> fn(&'a u32) -> Foo
- /// ```
- ///
- /// where `Foo` is an opaque type created for this function.
- ///
- ///
- /// The *liberated* form of this would be
- ///
- /// ```ignore (illustrative)
- /// fn(&'a u32) -> u32
- /// ```
- ///
- /// Note that `'a` is not bound (it would be an `ReFree`) and
- /// that the `Foo` opaque type is replaced by its hidden type.
- liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
-
- /// For each FRU expression, record the normalized types of the fields
- /// of the struct - this is needed because it is non-trivial to
- /// normalize while preserving regions. This table is used only in
- /// MIR construction and hence is not serialized to metadata.
- fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
-
- /// For every coercion cast we add the HIR node ID of the cast
- /// expression to this set.
- coercion_casts: ItemLocalSet,
-
- /// Set of trait imports actually used in the method resolution.
- /// This is used for warning unused imports. During type
- /// checking, this `Lrc` should not be cloned: it must have a ref-count
- /// of 1 so that we can insert things into the set mutably.
- pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
-
- /// If any errors occurred while type-checking this body,
- /// this field will be set to `Some(ErrorGuaranteed)`.
- pub tainted_by_errors: Option<ErrorGuaranteed>,
-
- /// All the opaque types that have hidden types set
- /// by this function. We also store the
- /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
- /// even if they are only set in dead code (which doesn't show up in MIR).
- pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
-
- /// Tracks the minimum captures required for a closure;
- /// see `MinCaptureInformationMap` for more details.
- pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
-
- /// Tracks the fake reads required for a closure and the reason for the fake read.
- /// When performing pattern matching for closures, there are times we don't end up
- /// reading places that are mentioned in a closure (because of _ patterns). However,
- /// to ensure the places are initialized, we introduce fake reads.
- /// Consider these two examples:
- /// ``` (discriminant matching with only wildcard arm)
- /// let x: u8;
- /// let c = || match x { _ => () };
- /// ```
- /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
- /// want to capture it. However, we do still want an error here, because `x` should have
- /// to be initialized at the point where c is created. Therefore, we add a "fake read"
- /// instead.
- /// ``` (destructured assignments)
- /// let c = || {
- /// let (t1, t2) = t;
- /// }
- /// ```
- /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
- /// we never capture `t`. This becomes an issue when we build MIR as we require
- /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
- /// issue by fake reading `t`.
- pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
-
- /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
- /// by applying extended parameter rules.
- /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
- pub rvalue_scopes: RvalueScopes,
-
- /// Stores the type, expression, span and optional scope span of all types
- /// that are live across the yield of this generator (if a generator).
- pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
-
- /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
- /// as `&[u8]`, depending on the pattern in which they are used.
- /// This hashset records all instances where we behave
- /// like this to allow `const_to_pat` to reliably handle this situation.
- pub treat_byte_string_as_slice: ItemLocalSet,
-
- /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
- /// on closure size.
- pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
-}
-
-impl<'tcx> TypeckResults<'tcx> {
- pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
- TypeckResults {
- hir_owner,
- type_dependent_defs: Default::default(),
- field_indices: Default::default(),
- user_provided_types: Default::default(),
- user_provided_sigs: Default::default(),
- node_types: Default::default(),
- node_substs: Default::default(),
- adjustments: Default::default(),
- pat_binding_modes: Default::default(),
- pat_adjustments: Default::default(),
- closure_kind_origins: Default::default(),
- liberated_fn_sigs: Default::default(),
- fru_field_types: Default::default(),
- coercion_casts: Default::default(),
- used_trait_imports: Lrc::new(Default::default()),
- tainted_by_errors: None,
- concrete_opaque_types: Default::default(),
- closure_min_captures: Default::default(),
- closure_fake_reads: Default::default(),
- rvalue_scopes: Default::default(),
- generator_interior_types: ty::Binder::dummy(Default::default()),
- treat_byte_string_as_slice: Default::default(),
- closure_size_eval: Default::default(),
- }
- }
-
- /// 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::TypeRelative(..) | hir::QPath::LangItem(..) => self
- .type_dependent_def(id)
- .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
- }
- }
-
- pub fn type_dependent_defs(
- &self,
- ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
- }
-
- pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
- }
-
- pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
- self.type_dependent_def(id).map(|(_, def_id)| def_id)
- }
-
- pub fn type_dependent_defs_mut(
- &mut self,
- ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
- }
-
- pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
- }
-
- pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
- }
-
- pub fn field_index(&self, id: hir::HirId) -> usize {
- self.field_indices().get(id).cloned().expect("no index for a field")
- }
-
- pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
- self.field_indices().get(id).cloned()
- }
-
- pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
- }
-
- pub fn user_provided_types_mut(
- &mut self,
- ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
- }
-
- pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
- }
-
- pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
- }
-
- pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
- let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
- vec.iter()
- .map(|item| {
- GeneratorInteriorTypeCause {
- ty: item.ty,
- span: item.span,
- scope_span: item.scope_span,
- yield_span: item.yield_span,
- expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
- }
- })
- .collect::<Vec<_>>()
- });
- GeneratorDiagnosticData {
- generator_interior_types: generator_interior_type,
- hir_owner: self.hir_owner.to_def_id(),
- nodes_types: self.node_types.clone(),
- adjustments: self.adjustments.clone(),
- }
- }
-
- pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
- self.node_type_opt(id).unwrap_or_else(|| {
- bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
- })
- }
-
- pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.node_types.get(&id.local_id).cloned()
- }
-
- pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
- }
-
- pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
- }
-
- pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
- validate_hir_id_for_typeck_results(self.hir_owner, id);
- self.node_substs.get(&id.local_id).cloned()
- }
-
- /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
- /// doesn't provide type parameter substitutions.
- ///
- /// [`expr_ty`]: TypeckResults::expr_ty
- pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
- self.node_type(pat.hir_id)
- }
-
- /// Returns the type of an expression as a monotype.
- ///
- /// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
- /// some cases, we insert `Adjustment` annotations such as auto-deref or
- /// auto-ref. The type returned by this function does not consider such
- /// adjustments. See `expr_ty_adjusted()` instead.
- ///
- /// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
- /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
- /// instead of `fn(ty) -> T with T = isize`.
- pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
- self.node_type(expr.hir_id)
- }
-
- pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
- self.node_type_opt(expr.hir_id)
- }
-
- pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
- }
-
- pub fn adjustments_mut(
- &mut self,
- ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
- }
-
- pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
- validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
- self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
- }
-
- /// Returns the type of `expr`, considering any `Adjustment`
- /// entry recorded for that expression.
- pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
- self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
- }
-
- pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
- self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
- }
-
- pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
- // Only paths and method calls/overloaded operators have
- // entries in type_dependent_defs, ignore the former here.
- if let hir::ExprKind::Path(_) = expr.kind {
- return false;
- }
-
- matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
- }
-
- 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");
- None
- })
- }
-
- pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
- }
-
- pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
- }
-
- pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
- }
-
- pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
- }
-
- /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
- /// by the closure.
- pub fn closure_min_captures_flattened(
- &self,
- closure_def_id: LocalDefId,
- ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
- self.closure_min_captures
- .get(&closure_def_id)
- .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
- .into_iter()
- .flatten()
- }
-
- pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
- }
-
- pub fn closure_kind_origins_mut(
- &mut self,
- ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
- }
-
- pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
- }
-
- pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
- }
-
- pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
- LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
- }
-
- pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
- LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
- }
-
- pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
- validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
- self.coercion_casts.contains(&hir_id.local_id)
- }
-
- pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
- self.coercion_casts.insert(id);
- }
-
- pub fn coercion_casts(&self) -> &ItemLocalSet {
- &self.coercion_casts
- }
-}
-
-rustc_index::newtype_index! {
- pub struct UserTypeAnnotationIndex {
- derive [HashStable]
- DEBUG_FORMAT = "UserType({})",
- const START_INDEX = 0,
- }
-}
-
-/// Mapping of type annotation indices to canonical user type annotations.
-pub type CanonicalUserTypeAnnotations<'tcx> =
- IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
-
-#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct CanonicalUserTypeAnnotation<'tcx> {
- pub user_ty: Box<CanonicalUserType<'tcx>>,
- pub span: Span,
- pub inferred_ty: Ty<'tcx>,
-}
-
-/// Canonicalized user type annotation.
-pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
-
-impl<'tcx> CanonicalUserType<'tcx> {
- /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
- /// i.e., each thing is mapped to a canonical variable with the same index.
- pub fn is_identity(&self) -> bool {
- match self.value {
- UserType::Ty(_) => false,
- UserType::TypeOf(_, user_substs) => {
- if user_substs.user_self_ty.is_some() {
- return false;
- }
-
- iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
- match kind.unpack() {
- GenericArgKind::Type(ty) => match ty.kind() {
- ty::Bound(debruijn, b) => {
- // We only allow a `ty::INNERMOST` index in substitutions.
- assert_eq!(*debruijn, ty::INNERMOST);
- cvar == b.var
- }
- _ => false,
- },
-
- GenericArgKind::Lifetime(r) => match *r {
- ty::ReLateBound(debruijn, br) => {
- // We only allow a `ty::INNERMOST` index in substitutions.
- assert_eq!(debruijn, ty::INNERMOST);
- cvar == br.var
- }
- _ => false,
- },
-
- GenericArgKind::Const(ct) => match ct.kind() {
- ty::ConstKind::Bound(debruijn, b) => {
- // We only allow a `ty::INNERMOST` index in substitutions.
- assert_eq!(debruijn, ty::INNERMOST);
- cvar == b
- }
- _ => false,
- },
- }
- })
- }
- }
- }
-}
-
-/// A user-given type annotation attached to a constant. These arise
-/// from constants that are named via paths, like `Foo::<A>::new` and
-/// so forth.
-#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub enum UserType<'tcx> {
- Ty(Ty<'tcx>),
-
- /// The canonical type is the result of `type_of(def_id)` with the
- /// given substitutions applied.
- TypeOf(DefId, UserSubsts<'tcx>),
-}
-
impl<'tcx> CommonTypes<'tcx> {
fn new(
interners: &CtxtInterners<'tcx>,
sess: &Session,
- definitions: &rustc_hir::definitions::Definitions,
- cstore: &CrateStoreDyn,
- source_span: &IndexVec<LocalDefId, Span>,
+ untracked: &Untracked,
) -> CommonTypes<'tcx> {
- let mk = |ty| interners.intern_ty(ty, sess, definitions, cstore, source_span);
+ let mk = |ty| interners.intern_ty(ty, sess, untracked);
CommonTypes {
unit: mk(Tuple(List::empty())),
@@ -1016,7 +330,7 @@ impl<'tcx> CommonConsts<'tcx> {
};
CommonConsts {
- unit: mk_const(ty::ConstS {
+ unit: mk_const(ty::ConstData {
kind: ty::ConstKind::Value(ty::ValTree::zst()),
ty: types.unit,
}),
@@ -1048,6 +362,9 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> {
TyCtxtFeed { tcx: self, key: () }
}
+ pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
+ TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
+ }
}
impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
@@ -1112,13 +429,7 @@ pub struct GlobalCtxt<'tcx> {
/// Common consts, pre-interned for your convenience.
pub consts: CommonConsts<'tcx>,
- definitions: RwLock<Definitions>,
-
- /// Output of the resolver.
- pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt,
- /// The entire crate as AST. This field serves as the input for the hir_crate query,
- /// which lowers it from AST to HIR. It must not be read or used by anything else.
- pub untracked_crate: Steal<Lrc<ast::Crate>>,
+ untracked: Untracked,
/// This provides access to the incremental compilation on-disk cache for query results.
/// Do not access this directly. It is only meant to be used by
@@ -1143,17 +454,11 @@ pub struct GlobalCtxt<'tcx> {
/// Merge this with `selection_cache`?
pub evaluation_cache: traits::EvaluationCache<'tcx>,
- /// The definite name of the current crate after taking into account
- /// attributes, commandline parameters, etc.
- crate_name: Symbol,
-
/// Data layout specification for the current target.
pub data_layout: TargetDataLayout,
/// Stores memory for globals (statics/consts).
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
-
- output_filenames: Arc<OutputFilenames>,
}
impl<'tcx> TyCtxt<'tcx> {
@@ -1278,28 +583,17 @@ impl<'tcx> TyCtxt<'tcx> {
lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
- definitions: Definitions,
- untracked_resolutions: ty::ResolverGlobalCtxt,
- krate: Lrc<ast::Crate>,
+ untracked: Untracked,
dep_graph: DepGraph,
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
queries: &'tcx dyn query::QueryEngine<'tcx>,
query_kinds: &'tcx [DepKindStruct<'tcx>],
- crate_name: Symbol,
- output_filenames: OutputFilenames,
) -> GlobalCtxt<'tcx> {
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
s.emit_fatal(err);
});
let interners = CtxtInterners::new(arena);
- let common_types = CommonTypes::new(
- &interners,
- s,
- &definitions,
- &*untracked_resolutions.cstore,
- // This is only used to create a stable hashing context.
- &untracked_resolutions.source_span,
- );
+ let common_types = CommonTypes::new(&interners, s, &untracked);
let common_lifetimes = CommonLifetimes::new(&interners);
let common_consts = CommonConsts::new(&interners, &common_types);
@@ -1310,13 +604,11 @@ impl<'tcx> TyCtxt<'tcx> {
hir_arena,
interners,
dep_graph,
- definitions: RwLock::new(definitions),
prof: s.prof.clone(),
types: common_types,
lifetimes: common_lifetimes,
consts: common_consts,
- untracked_resolutions,
- untracked_crate: Steal::new(krate),
+ untracked,
on_disk_cache,
queries,
query_caches: query::QueryCaches::default(),
@@ -1325,10 +617,8 @@ impl<'tcx> TyCtxt<'tcx> {
pred_rcache: Default::default(),
selection_cache: Default::default(),
evaluation_cache: Default::default(),
- crate_name,
data_layout,
alloc_map: Lock::new(interpret::AllocMap::new()),
- output_filenames: Arc::new(output_filenames),
}
}
@@ -1428,7 +718,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(id) = id.as_local() {
self.definitions_untracked().def_key(id)
} else {
- self.untracked_resolutions.cstore.def_key(id)
+ self.untracked.cstore.def_key(id)
}
}
@@ -1442,7 +732,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(id) = id.as_local() {
self.definitions_untracked().def_path(id)
} else {
- self.untracked_resolutions.cstore.def_path(id)
+ self.untracked.cstore.def_path(id)
}
}
@@ -1452,7 +742,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(def_id) = def_id.as_local() {
self.definitions_untracked().def_path_hash(def_id)
} else {
- self.untracked_resolutions.cstore.def_path_hash(def_id)
+ self.untracked.cstore.def_path_hash(def_id)
}
}
@@ -1461,7 +751,7 @@ impl<'tcx> TyCtxt<'tcx> {
if crate_num == LOCAL_CRATE {
self.sess.local_stable_crate_id()
} else {
- self.untracked_resolutions.cstore.stable_crate_id(crate_num)
+ self.untracked.cstore.stable_crate_id(crate_num)
}
}
@@ -1472,7 +762,7 @@ impl<'tcx> TyCtxt<'tcx> {
if stable_crate_id == self.sess.local_stable_crate_id() {
LOCAL_CRATE
} else {
- self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id)
+ self.untracked.cstore.stable_crate_id_to_crate_num(stable_crate_id)
}
}
@@ -1487,11 +777,11 @@ impl<'tcx> TyCtxt<'tcx> {
// If this is a DefPathHash from the local crate, we can look up the
// DefId in the tcx's `Definitions`.
if stable_crate_id == self.sess.local_stable_crate_id() {
- self.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
+ self.untracked.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
} else {
// If this is a DefPathHash from an upstream crate, let the CrateStore map
// it to a DefId.
- let cstore = &*self.untracked_resolutions.cstore;
+ let cstore = &*self.untracked.cstore;
let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
cstore.def_path_hash_to_def_id(cnum, hash)
}
@@ -1503,9 +793,9 @@ impl<'tcx> TyCtxt<'tcx> {
// statements within the query system and we'd run into endless
// recursion otherwise.
let (crate_name, stable_crate_id) = if def_id.is_local() {
- (self.crate_name, self.sess.local_stable_crate_id())
+ (self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id())
} else {
- let cstore = &*self.untracked_resolutions.cstore;
+ let cstore = &*self.untracked.cstore;
(cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
};
@@ -1547,7 +837,7 @@ 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.definitions.write().create_def(parent, data);
+ let key = self.untracked.definitions.write().create_def(parent, data);
let feed = TyCtxtFeed { tcx: self.tcx, key };
feed.def_span(self.span);
@@ -1561,7 +851,7 @@ impl<'tcx> TyCtxt<'tcx> {
// definitions change.
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
- let definitions = &self.definitions;
+ let definitions = &self.untracked.definitions;
std::iter::from_generator(|| {
let mut i = 0;
@@ -1584,8 +874,8 @@ impl<'tcx> TyCtxt<'tcx> {
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
// Leak a read lock once we start iterating on definitions, to prevent adding new ones
- // while iterating. If some query needs to add definitions, it should be `ensure`d above.
- let definitions = self.definitions.leak();
+ // while iterating. If some query needs to add definitions, it should be `ensure`d above.
+ let definitions = self.untracked.definitions.leak();
definitions.def_path_table()
}
@@ -1596,29 +886,29 @@ impl<'tcx> TyCtxt<'tcx> {
// definitions change.
self.ensure().hir_crate(());
// Leak a read lock once we start iterating on definitions, to prevent adding new ones
- // while iterating. If some query needs to add definitions, it should be `ensure`d above.
- let definitions = self.definitions.leak();
+ // while iterating. If some query needs to add definitions, it should be `ensure`d above.
+ let definitions = self.untracked.definitions.leak();
definitions.def_path_hash_to_def_index_map()
}
/// Note that this is *untracked* and should only be used within the query
/// system if the result is otherwise tracked through queries
pub fn cstore_untracked(self) -> &'tcx CrateStoreDyn {
- &*self.untracked_resolutions.cstore
+ &*self.untracked.cstore
}
/// Note that this is *untracked* and should only be used within the query
/// system if the result is otherwise tracked through queries
#[inline]
pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> {
- self.definitions.read()
+ self.untracked.definitions.read()
}
/// Note that this is *untracked* and should only be used within the query
/// system if the result is otherwise tracked through queries
#[inline]
pub fn source_span_untracked(self, def_id: LocalDefId) -> Span {
- self.untracked_resolutions.source_span.get(def_id).copied().unwrap_or(DUMMY_SP)
+ self.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP)
}
#[inline(always)]
@@ -1626,14 +916,7 @@ impl<'tcx> TyCtxt<'tcx> {
self,
f: impl FnOnce(StableHashingContext<'_>) -> R,
) -> R {
- let definitions = self.definitions_untracked();
- let hcx = StableHashingContext::new(
- self.sess,
- &*definitions,
- &*self.untracked_resolutions.cstore,
- &self.untracked_resolutions.source_span,
- );
- f(hcx)
+ f(StableHashingContext::new(self.sess, &self.untracked))
}
pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult {
@@ -2175,8 +1458,7 @@ impl<'tcx> TyCtxt<'tcx> {
Bound,
Param,
Infer,
- Projection,
- Opaque,
+ Alias,
Foreign
)?;
@@ -2219,7 +1501,7 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
#[allow(rustc::usage_of_ty_tykind)]
impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
- fn borrow<'a>(&'a self) -> &'a T {
+ fn borrow(&self) -> &T {
&self.0.internee
}
}
@@ -2242,7 +1524,7 @@ impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
}
impl<'tcx, T> Borrow<[T]> for InternedInSet<'tcx, List<T>> {
- fn borrow<'a>(&'a self) -> &'a [T] {
+ fn borrow(&self) -> &[T] {
&self.0[..]
}
}
@@ -2302,7 +1584,7 @@ macro_rules! direct_interners {
direct_interners! {
region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
- const_: mk_const_internal(ConstS<'tcx>): Const -> Const<'tcx>,
+ const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>,
const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>,
adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
@@ -2353,7 +1635,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Given a `ty`, return whether it's an `impl Future<...>`.
pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool {
- let ty::Opaque(def_id, _) = ty.kind() else { return false };
+ let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
let future_trait = self.require_lang_item(LangItem::Future, None);
self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
@@ -2427,10 +1709,8 @@ impl<'tcx> TyCtxt<'tcx> {
self.interners.intern_ty(
st,
self.sess,
- &self.definitions.read(),
- &*self.untracked_resolutions.cstore,
// This is only used to create a stable hashing context.
- &self.untracked_resolutions.source_span,
+ &self.untracked,
)
}
@@ -2439,10 +1719,8 @@ impl<'tcx> TyCtxt<'tcx> {
self.interners.intern_predicate(
binder,
self.sess,
- &self.definitions.read(),
- &*self.untracked_resolutions.cstore,
// This is only used to create a stable hashing context.
- &self.untracked_resolutions.source_span,
+ &self.untracked,
)
}
@@ -2601,15 +1879,35 @@ impl<'tcx> TyCtxt<'tcx> {
}
#[inline]
- pub fn mk_fn_def(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- debug_assert_eq!(
- self.generics_of(def_id).count(),
- substs.len(),
- "wrong number of generic parameters for {def_id:?}: {substs:?}",
- );
+ pub fn mk_fn_def(
+ self,
+ def_id: DefId,
+ substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ ) -> Ty<'tcx> {
+ let substs = self.check_substs(def_id, substs);
self.mk_ty(FnDef(def_id, substs))
}
+ #[inline(always)]
+ fn check_substs(
+ self,
+ _def_id: DefId,
+ substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ ) -> SubstsRef<'tcx> {
+ let substs = substs.into_iter().map(Into::into);
+ #[cfg(debug_assertions)]
+ {
+ let n = self.generics_of(_def_id).count();
+ assert_eq!(
+ (n, Some(n)),
+ substs.size_hint(),
+ "wrong number of generic parameters for {_def_id:?}: {:?}",
+ substs.collect::<Vec<_>>(),
+ );
+ }
+ self.mk_substs(substs)
+ }
+
#[inline]
pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
self.mk_ty(FnPtr(fty))
@@ -2626,13 +1924,12 @@ impl<'tcx> TyCtxt<'tcx> {
}
#[inline]
- pub fn mk_projection(self, item_def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- debug_assert_eq!(
- self.generics_of(item_def_id).count(),
- substs.len(),
- "wrong number of generic parameters for {item_def_id:?}: {substs:?}",
- );
- self.mk_ty(Projection(ProjectionTy { item_def_id, substs }))
+ pub fn mk_projection(
+ self,
+ item_def_id: DefId,
+ substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ ) -> Ty<'tcx> {
+ self.mk_ty(Alias(ty::Projection, self.mk_alias_ty(item_def_id, substs)))
}
#[inline]
@@ -2655,6 +1952,15 @@ impl<'tcx> TyCtxt<'tcx> {
self.mk_ty(GeneratorWitness(types))
}
+ /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes.
+ pub fn mk_task_context(self) -> Ty<'tcx> {
+ let context_did = self.require_lang_item(LangItem::Context, None);
+ let context_adt_ref = self.adt_def(context_did);
+ let context_substs = self.intern_substs(&[self.lifetimes.re_erased.into()]);
+ let context_ty = self.mk_adt(context_adt_ref, context_substs);
+ self.mk_mut_ref(self.lifetimes.re_erased, context_ty)
+ }
+
#[inline]
pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
self.mk_ty_infer(TyVar(v))
@@ -2662,7 +1968,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> {
- self.mk_const_internal(ty::ConstS { kind: kind.into(), ty })
+ self.mk_const_internal(ty::ConstData { kind: kind.into(), ty })
}
#[inline]
@@ -2702,7 +2008,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- self.mk_ty(Opaque(def_id, substs))
+ self.mk_ty(Alias(ty::Opaque, self.mk_alias_ty(def_id, substs)))
}
pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
@@ -2891,16 +2197,17 @@ impl<'tcx> TyCtxt<'tcx> {
trait_def_id: DefId,
substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
) -> ty::TraitRef<'tcx> {
- let substs = substs.into_iter().map(Into::into);
- let n = self.generics_of(trait_def_id).count();
- debug_assert_eq!(
- (n, Some(n)),
- substs.size_hint(),
- "wrong number of generic parameters for {trait_def_id:?}: {:?} \nDid you accidentally include the self-type in the params list?",
- substs.collect::<Vec<_>>(),
- );
- let substs = self.mk_substs(substs);
- ty::TraitRef::new(trait_def_id, substs)
+ let substs = self.check_substs(trait_def_id, substs);
+ ty::TraitRef { def_id: trait_def_id, substs, _use_mk_trait_ref_instead: () }
+ }
+
+ pub fn mk_alias_ty(
+ self,
+ def_id: DefId,
+ substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ ) -> ty::AliasTy<'tcx> {
+ let substs = self.check_substs(def_id, substs);
+ ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
}
pub fn mk_bound_variable_kinds<
@@ -3092,13 +2399,8 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
}
pub fn provide(providers: &mut ty::query::Providers) {
- providers.resolutions = |tcx, ()| &tcx.untracked_resolutions;
providers.module_reexports =
|tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]);
- providers.crate_name = |tcx, id| {
- assert_eq!(id, LOCAL_CRATE);
- tcx.crate_name
- };
providers.maybe_unused_trait_imports =
|tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
providers.maybe_unused_extern_crates =
@@ -3109,8 +2411,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
providers.extern_mod_stmt_cnum =
|tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
- providers.output_filenames = |tcx, ()| &tcx.output_filenames;
- providers.features_query = |tcx, ()| tcx.sess.features_untracked();
providers.is_panic_runtime = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
tcx.sess.contains_name(tcx.hir().krate_attrs(), sym::panic_runtime)
@@ -3124,4 +2424,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
// We want to check if the panic handler was defined in this crate
tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
};
+ providers.source_span =
+ |tcx, def_id| tcx.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP);
}
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 511d51cd6..4b4518f61 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -3,13 +3,14 @@
use std::ops::ControlFlow;
use crate::ty::{
- visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferConst, InferTy,
- PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
+ visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque,
+ PolyTraitPredicate, Projection, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::WherePredicate;
use rustc_span::Span;
@@ -17,7 +18,7 @@ use rustc_type_ir::sty::TyKind::*;
impl<'tcx> IntoDiagnosticArg for Ty<'tcx> {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- format!("{}", self).into_diagnostic_arg()
+ self.to_string().into_diagnostic_arg()
}
}
@@ -443,7 +444,7 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- match t.kind() {
+ match *t.kind() {
Infer(InferTy::TyVar(_)) if self.infer_suggestable => {}
FnDef(..)
@@ -457,11 +458,11 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
return ControlFlow::Break(());
}
- Opaque(did, _) => {
- let parent = self.tcx.parent(*did);
- if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
- && let Opaque(parent_did, _) = self.tcx.type_of(parent).kind()
- && parent_did == did
+ Alias(Opaque, AliasTy { def_id, .. }) => {
+ let parent = self.tcx.parent(def_id);
+ if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent)
+ && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *self.tcx.type_of(parent).kind()
+ && parent_opaque_def_id == def_id
{
// Okay
} else {
@@ -469,14 +470,9 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
}
}
- Dynamic(dty, _, _) => {
- for pred in *dty {
- match pred.skip_binder() {
- ExistentialPredicate::Trait(_) | ExistentialPredicate::Projection(_) => {
- // Okay
- }
- _ => return ControlFlow::Break(()),
- }
+ Alias(Projection, AliasTy { def_id, .. }) => {
+ if self.tcx.def_kind(def_id) != DefKind::AssocTy {
+ return ControlFlow::Break(());
}
}
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index ffdac93bc..9e4f90caa 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -21,7 +21,7 @@ impl<'tcx> TyCtxt<'tcx> {
T: TypeFoldable<'tcx>,
{
// If there's nothing to erase avoid performing the query at all
- if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
+ if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
return value;
}
debug!("erase_regions({:?})", value);
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index aa61c39b8..5d394f71f 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -1,11 +1,11 @@
use crate::traits::{ObligationCause, ObligationCauseCode};
use crate::ty::diagnostics::suggest_constraining_type_param;
-use crate::ty::print::{FmtPrinter, Printer};
+use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer};
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
-use hir::def::DefKind;
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
use rustc_hir as hir;
+use rustc_hir::def::{CtorOf, DefKind};
use rustc_hir::def_id::DefId;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, Span};
@@ -162,17 +162,29 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
),
RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| {
- report_maybe_different(
- f,
- &values.expected.sort_string(tcx),
- &values.found.sort_string(tcx),
- )
+ let (mut expected, mut found) = with_forced_trimmed_paths!((
+ values.expected.sort_string(tcx),
+ values.found.sort_string(tcx),
+ ));
+ if expected == found {
+ expected = values.expected.sort_string(tcx);
+ found = values.found.sort_string(tcx);
+ }
+ report_maybe_different(f, &expected, &found)
}),
Traits(values) => ty::tls::with(|tcx| {
+ let (mut expected, mut found) = with_forced_trimmed_paths!((
+ tcx.def_path_str(values.expected),
+ tcx.def_path_str(values.found),
+ ));
+ if expected == found {
+ expected = tcx.def_path_str(values.expected);
+ found = tcx.def_path_str(values.found);
+ }
report_maybe_different(
f,
- &format!("trait `{}`", tcx.def_path_str(values.expected)),
- &format!("trait `{}`", tcx.def_path_str(values.found)),
+ &format!("trait `{expected}`"),
+ &format!("trait `{found}`"),
)
}),
IntMismatch(ref values) => {
@@ -307,7 +319,11 @@ impl<'tcx> Ty<'tcx> {
.into()
}
}
- ty::FnDef(..) => "fn item".into(),
+ ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
+ DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
+ DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
+ _ => "fn item".into(),
+ },
ty::FnPtr(_) => "fn pointer".into(),
ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
@@ -325,9 +341,9 @@ impl<'tcx> Ty<'tcx> {
ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
- ty::Projection(_) => "associated type".into(),
+ ty::Alias(ty::Projection, _) => "associated type".into(),
ty::Param(p) => format!("type parameter `{}`", p).into(),
- ty::Opaque(..) => "opaque type".into(),
+ ty::Alias(ty::Opaque, ..) => "opaque type".into(),
ty::Error(_) => "type error".into(),
}
}
@@ -354,7 +370,11 @@ impl<'tcx> Ty<'tcx> {
_ => "reference",
}
.into(),
- ty::FnDef(..) => "fn item".into(),
+ ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
+ DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
+ DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
+ _ => "fn item".into(),
+ },
ty::FnPtr(_) => "fn pointer".into(),
ty::Dynamic(..) => "trait object".into(),
ty::Closure(..) => "closure".into(),
@@ -363,9 +383,9 @@ impl<'tcx> Ty<'tcx> {
ty::Tuple(..) => "tuple".into(),
ty::Placeholder(..) => "higher-ranked type".into(),
ty::Bound(..) => "bound type variable".into(),
- ty::Projection(_) => "associated type".into(),
+ ty::Alias(ty::Projection, _) => "associated type".into(),
ty::Param(_) => "type parameter".into(),
- ty::Opaque(..) => "opaque type".into(),
+ ty::Alias(ty::Opaque, ..) => "opaque type".into(),
}
}
}
@@ -388,7 +408,7 @@ impl<'tcx> TyCtxt<'tcx> {
diag.note("no two closures, even if identical, have the same type");
diag.help("consider boxing your closure and/or using it as a trait object");
}
- (ty::Opaque(..), ty::Opaque(..)) => {
+ (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => {
// Issue #63167
diag.note("distinct uses of `impl Trait` result in different opaque types");
}
@@ -427,11 +447,11 @@ impl<'tcx> TyCtxt<'tcx> {
#traits-as-parameters",
);
}
- (ty::Projection(_), ty::Projection(_)) => {
+ (ty::Alias(ty::Projection, _), ty::Alias(ty::Projection, _)) => {
diag.note("an associated type was expected, but a different one was found");
}
- (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p))
- if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder =>
+ (ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
+ if self.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
{
let generics = self.generics_of(body_owner_def_id);
let p_span = self.def_span(generics.type_param(p, self).def_id);
@@ -445,7 +465,7 @@ impl<'tcx> TyCtxt<'tcx> {
.def_id
.as_local()
.map(|id| hir.local_def_id_to_hir_id(id))
- .and_then(|id| self.hir().find(self.hir().get_parent_node(id)))
+ .and_then(|id| self.hir().find_parent(id))
.as_ref()
.and_then(|node| node.generics())
{
@@ -454,7 +474,7 @@ impl<'tcx> TyCtxt<'tcx> {
let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(self);
let path =
self.def_path_str_with_substs(trait_ref.def_id, trait_ref.substs);
- let item_name = self.item_name(proj.item_def_id);
+ let item_name = self.item_name(proj.def_id);
let item_args = self.format_generic_args(assoc_substs);
let path = if path.ends_with('>') {
@@ -481,8 +501,8 @@ impl<'tcx> TyCtxt<'tcx> {
diag.note("you might be missing a type parameter or trait bound");
}
}
- (ty::Param(p), ty::Dynamic(..) | ty::Opaque(..))
- | (ty::Dynamic(..) | ty::Opaque(..), ty::Param(p)) => {
+ (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
+ | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
let generics = self.generics_of(body_owner_def_id);
let p_span = self.def_span(generics.type_param(p, self).def_id);
if !sp.contains(p_span) {
@@ -541,7 +561,7 @@ impl<T> Trait<T> for X {
diag.span_label(p_span, "this type parameter");
}
}
- (ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
+ (ty::Alias(ty::Projection, proj_ty), _) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
self.expected_projection(
diag,
proj_ty,
@@ -550,7 +570,7 @@ impl<T> Trait<T> for X {
cause.code(),
);
}
- (_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
+ (_, ty::Alias(ty::Projection, proj_ty)) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
let msg = format!(
"consider constraining the associated type `{}` to `{}`",
values.found, values.expected,
@@ -612,10 +632,10 @@ impl<T> Trait<T> for X {
diag: &mut Diagnostic,
msg: &str,
body_owner_def_id: DefId,
- proj_ty: &ty::ProjectionTy<'tcx>,
+ proj_ty: &ty::AliasTy<'tcx>,
ty: Ty<'tcx>,
) -> bool {
- let assoc = self.associated_item(proj_ty.item_def_id);
+ let assoc = self.associated_item(proj_ty.def_id);
let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
if let Some(item) = self.hir().get_if_local(body_owner_def_id) {
if let Some(hir_generics) = item.generics() {
@@ -668,7 +688,7 @@ impl<T> Trait<T> for X {
fn expected_projection(
self,
diag: &mut Diagnostic,
- proj_ty: &ty::ProjectionTy<'tcx>,
+ proj_ty: &ty::AliasTy<'tcx>,
values: ExpectedFound<Ty<'tcx>>,
body_owner_def_id: DefId,
cause_code: &ObligationCauseCode<'_>,
@@ -691,7 +711,7 @@ impl<T> Trait<T> for X {
);
let impl_comparison =
matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
- let assoc = self.associated_item(proj_ty.item_def_id);
+ let assoc = self.associated_item(proj_ty.def_id);
if !callable_scope || impl_comparison {
// We do not want to suggest calling functions when the reason of the
// type error is a comparison of an `impl` with its `trait` or when the
@@ -704,7 +724,7 @@ impl<T> Trait<T> for X {
diag,
assoc.container_id(self),
current_method_ident,
- proj_ty.item_def_id,
+ proj_ty.def_id,
values.expected,
);
// Possibly suggest constraining the associated type to conform to the
@@ -763,11 +783,11 @@ fn foo(&self) -> Self::T { String::new() }
self,
diag: &mut Diagnostic,
msg: &str,
- proj_ty: &ty::ProjectionTy<'tcx>,
+ proj_ty: &ty::AliasTy<'tcx>,
ty: Ty<'tcx>,
) -> bool {
- let assoc = self.associated_item(proj_ty.item_def_id);
- if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
+ let assoc = self.associated_item(proj_ty.def_id);
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
let opaque_local_def_id = def_id.as_local();
let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
match &self.hir().expect_item(opaque_local_def_id).kind {
@@ -816,7 +836,7 @@ fn foo(&self) -> Self::T { String::new() }
.filter_map(|(_, item)| {
let method = self.fn_sig(item.def_id);
match *method.output().skip_binder().kind() {
- ty::Projection(ty::ProjectionTy { item_def_id, .. })
+ ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. })
if item_def_id == proj_ty_item_def_id =>
{
Some((
@@ -998,15 +1018,17 @@ fn foo(&self) -> Self::T { String::new() }
}
let mut short;
loop {
- // Look for the longest properly trimmed path that still fits in lenght_limit.
- short = FmtPrinter::new_with_limit(
- self,
- hir::def::Namespace::TypeNS,
- rustc_session::Limit(type_limit),
- )
- .pretty_print_type(ty)
- .expect("could not write to `String`")
- .into_buffer();
+ // Look for the longest properly trimmed path that still fits in length_limit.
+ short = with_forced_trimmed_paths!(
+ FmtPrinter::new_with_limit(
+ self,
+ hir::def::Namespace::TypeNS,
+ rustc_session::Limit(type_limit),
+ )
+ .pretty_print_type(ty)
+ .expect("could not write to `String`")
+ .into_buffer()
+ );
if short.len() <= length_limit || type_limit == 0 {
break;
}
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index c9c09c93a..f785fb5c4 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -6,28 +6,18 @@ use std::fmt::Debug;
use std::hash::Hash;
use std::iter;
-use self::SimplifiedTypeGen::*;
+use self::SimplifiedType::*;
-pub type SimplifiedType = SimplifiedTypeGen<DefId>;
-
-/// See `simplify_type`
-///
-/// Note that we keep this type generic over the type of identifier it uses
-/// because we sometimes need to use SimplifiedTypeGen values as stable sorting
-/// keys (in which case we use a DefPathHash as id-type) but in the general case
-/// the non-stable but fast to construct DefId-version is the better choice.
+/// See `simplify_type`.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
-pub enum SimplifiedTypeGen<D>
-where
- D: Copy + Debug + Eq,
-{
+pub enum SimplifiedType {
BoolSimplifiedType,
CharSimplifiedType,
IntSimplifiedType(ty::IntTy),
UintSimplifiedType(ty::UintTy),
FloatSimplifiedType(ty::FloatTy),
- AdtSimplifiedType(D),
- ForeignSimplifiedType(D),
+ AdtSimplifiedType(DefId),
+ ForeignSimplifiedType(DefId),
StrSimplifiedType,
ArraySimplifiedType,
SliceSimplifiedType,
@@ -38,9 +28,9 @@ where
/// A trait object, all of whose components are markers
/// (e.g., `dyn Send + Sync`).
MarkerTraitObjectSimplifiedType,
- TraitSimplifiedType(D),
- ClosureSimplifiedType(D),
- GeneratorSimplifiedType(D),
+ TraitSimplifiedType(DefId),
+ ClosureSimplifiedType(DefId),
+ GeneratorSimplifiedType(DefId),
GeneratorWitnessSimplifiedType(usize),
FunctionSimplifiedType(usize),
PlaceholderSimplifiedType,
@@ -126,7 +116,7 @@ pub fn simplify_type<'tcx>(
TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType),
TreatParams::AsInfer => None,
},
- ty::Opaque(..) | ty::Projection(_) => match treat_params {
+ ty::Alias(..) => match treat_params {
// When treating `ty::Param` as a placeholder, projections also
// don't unify with anything else as long as they are fully normalized.
//
@@ -142,8 +132,8 @@ pub fn simplify_type<'tcx>(
}
}
-impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
- pub fn def(self) -> Option<D> {
+impl SimplifiedType {
+ pub fn def(self) -> Option<DefId> {
match self {
AdtSimplifiedType(d)
| ForeignSimplifiedType(d)
@@ -153,36 +143,6 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
_ => None,
}
}
-
- pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U>
- where
- F: Fn(D) -> U,
- U: Copy + Debug + Eq,
- {
- match self {
- BoolSimplifiedType => BoolSimplifiedType,
- CharSimplifiedType => CharSimplifiedType,
- IntSimplifiedType(t) => IntSimplifiedType(t),
- UintSimplifiedType(t) => UintSimplifiedType(t),
- FloatSimplifiedType(t) => FloatSimplifiedType(t),
- AdtSimplifiedType(d) => AdtSimplifiedType(map(d)),
- ForeignSimplifiedType(d) => ForeignSimplifiedType(map(d)),
- StrSimplifiedType => StrSimplifiedType,
- ArraySimplifiedType => ArraySimplifiedType,
- SliceSimplifiedType => SliceSimplifiedType,
- RefSimplifiedType(m) => RefSimplifiedType(m),
- PtrSimplifiedType(m) => PtrSimplifiedType(m),
- NeverSimplifiedType => NeverSimplifiedType,
- MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
- TupleSimplifiedType(n) => TupleSimplifiedType(n),
- TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
- ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
- GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
- GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
- FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
- PlaceholderSimplifiedType => PlaceholderSimplifiedType,
- }
- }
}
/// Given generic arguments from an obligation and an impl,
@@ -225,7 +185,7 @@ impl DeepRejectCtxt {
match impl_ty.kind() {
// Start by checking whether the type in the impl may unify with
// pretty much everything. Just return `true` in that case.
- ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true,
+ ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true,
// These types only unify with inference variables or their own
// variant.
ty::Bool
@@ -323,8 +283,6 @@ impl DeepRejectCtxt {
_ => false,
},
- ty::Opaque(..) => true,
-
// Impls cannot contain these types as these cannot be named directly.
ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
@@ -344,7 +302,7 @@ impl DeepRejectCtxt {
// projections can unify with other stuff.
//
// Looking forward to lazy normalization this is the safer strategy anyways.
- ty::Projection(_) => true,
+ ty::Alias(..) => true,
ty::Error(_) => true,
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 046a2660a..b7eafc4b4 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -22,7 +22,7 @@ impl FlagComputation {
result
}
- pub fn for_predicate<'tcx>(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation {
+ pub fn for_predicate(binder: ty::Binder<'_, ty::PredicateKind<'_>>) -> FlagComputation {
let mut result = FlagComputation::new();
result.add_predicate(binder);
result
@@ -59,8 +59,18 @@ impl FlagComputation {
{
let mut computation = FlagComputation::new();
- if !value.bound_vars().is_empty() {
- computation.flags = computation.flags | TypeFlags::HAS_RE_LATE_BOUND;
+ for bv in value.bound_vars() {
+ match bv {
+ ty::BoundVariableKind::Ty(_) => {
+ computation.flags |= TypeFlags::HAS_TY_LATE_BOUND;
+ }
+ ty::BoundVariableKind::Region(_) => {
+ computation.flags |= TypeFlags::HAS_RE_LATE_BOUND;
+ }
+ ty::BoundVariableKind::Const => {
+ computation.flags |= TypeFlags::HAS_CT_LATE_BOUND;
+ }
+ }
}
f(&mut computation, value.skip_binder());
@@ -95,7 +105,7 @@ impl FlagComputation {
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
}
- &ty::Generator(_, ref substs, _) => {
+ ty::Generator(_, substs, _) => {
let substs = substs.as_generator();
let should_remove_further_specializable =
!self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
@@ -131,6 +141,7 @@ impl FlagComputation {
&ty::Bound(debruijn, _) => {
self.add_bound_var(debruijn);
+ self.add_flags(TypeFlags::HAS_TY_LATE_BOUND);
}
&ty::Placeholder(..) => {
@@ -155,12 +166,12 @@ impl FlagComputation {
self.add_substs(substs);
}
- &ty::Projection(data) => {
+ &ty::Alias(ty::Projection, data) => {
self.add_flags(TypeFlags::HAS_TY_PROJECTION);
self.add_projection_ty(data);
}
- &ty::Opaque(_, substs) => {
+ &ty::Alias(ty::Opaque, ty::AliasTy { substs, .. }) => {
self.add_flags(TypeFlags::HAS_TY_OPAQUE);
self.add_substs(substs);
}
@@ -186,7 +197,7 @@ impl FlagComputation {
&ty::Slice(tt) => self.add_ty(tt),
- &ty::RawPtr(ref m) => {
+ ty::RawPtr(m) => {
self.add_ty(m.ty);
}
@@ -303,6 +314,7 @@ impl FlagComputation {
}
ty::ConstKind::Bound(debruijn, _) => {
self.add_bound_var(debruijn);
+ self.add_flags(TypeFlags::HAS_CT_LATE_BOUND);
}
ty::ConstKind::Param(_) => {
self.add_flags(TypeFlags::HAS_CT_PARAM);
@@ -345,7 +357,7 @@ impl FlagComputation {
}
}
- fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) {
+ fn add_projection_ty(&mut self, projection_ty: ty::AliasTy<'_>) {
self.add_substs(projection_ty.substs);
}
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index d431d008d..6b9a37d84 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -290,7 +290,7 @@ pub struct RegionFolder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
/// Stores the index of a binder *just outside* the stuff we have
- /// visited. So this begins as INNERMOST; when we pass through a
+ /// visited. So this begins as INNERMOST; when we pass through a
/// binder, it is incremented (via `shift_in`).
current_index: ty::DebruijnIndex,
@@ -583,36 +583,6 @@ impl<'tcx> TyCtxt<'tcx> {
self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
}
- /// Rewrite any late-bound regions so that they are anonymous. Region numbers are
- /// assigned starting at 0 and increasing monotonically in the order traversed
- /// by the fold operation.
- ///
- /// The chief purpose of this function is to canonicalize regions so that two
- /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
- /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and
- /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization.
- pub fn anonymize_late_bound_regions<T>(self, sig: Binder<'tcx, T>) -> Binder<'tcx, T>
- where
- T: TypeFoldable<'tcx>,
- {
- let mut counter = 0;
- let inner = self
- .replace_late_bound_regions(sig, |_| {
- let br = ty::BoundRegion {
- var: ty::BoundVar::from_u32(counter),
- kind: ty::BrAnon(counter, None),
- };
- let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
- counter += 1;
- r
- })
- .0;
- let bound_vars = self.mk_bound_variable_kinds(
- (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
- );
- Binder::bind_with_vars(inner, bound_vars)
- }
-
/// Anonymize all bound variables in `value`, this is mostly used to improve caching.
pub fn anonymize_bound_vars<T>(self, value: Binder<'tcx, T>) -> Binder<'tcx, T>
where
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 48329da3e..801ca6004 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -70,14 +70,6 @@ impl GenericParamDef {
}
}
- pub fn has_default(&self) -> bool {
- match self.kind {
- GenericParamDefKind::Type { has_default, .. }
- | GenericParamDefKind::Const { has_default } => has_default,
- GenericParamDefKind::Lifetime => false,
- }
- }
-
pub fn is_anonymous_lifetime(&self) -> bool {
match self.kind {
GenericParamDefKind::Lifetime => {
@@ -96,7 +88,7 @@ impl GenericParamDef {
Some(tcx.bound_type_of(self.def_id).map_bound(|t| t.into()))
}
GenericParamDefKind::Const { has_default } if has_default => {
- Some(tcx.bound_const_param_default(self.def_id).map_bound(|c| c.into()))
+ Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into()))
}
_ => None,
}
@@ -234,6 +226,15 @@ impl<'tcx> Generics {
}
}
+ pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] {
+ if let Some(index) = param_index.checked_sub(self.parent_count) {
+ &self.params[..index]
+ } else {
+ tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
+ .params_to(param_index, tcx)
+ }
+ }
+
/// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`.
pub fn region_param(
&'tcx self,
@@ -340,15 +341,9 @@ impl<'tcx> GenericPredicates<'tcx> {
&self,
tcx: TyCtxt<'tcx>,
substs: SubstsRef<'tcx>,
- ) -> InstantiatedPredicates<'tcx> {
- InstantiatedPredicates {
- predicates: self
- .predicates
- .iter()
- .map(|(p, _)| EarlyBinder(*p).subst(tcx, substs))
- .collect(),
- spans: self.predicates.iter().map(|(_, sp)| *sp).collect(),
- }
+ ) -> impl Iterator<Item = (Predicate<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
+ {
+ EarlyBinder(self.predicates).subst_iter_copied(tcx, substs)
}
#[instrument(level = "debug", skip(self, tcx))]
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index ace81bc4f..5d5089cec 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -112,7 +112,7 @@ impl<'tcx> Ty<'tcx> {
InhabitedPredicate::True
}
Never => InhabitedPredicate::False,
- Param(_) | Projection(_) => InhabitedPredicate::GenericType(self),
+ Param(_) | Alias(ty::Projection, _) => InhabitedPredicate::GenericType(self),
Tuple(tys) if tys.is_empty() => InhabitedPredicate::True,
// use a query for more complex cases
Adt(..) | Array(..) | Tuple(_) => tcx.inhabited_predicate_type(self),
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 586460986..6ac00d16c 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -6,6 +6,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::lang_items::LangItem;
+use rustc_index::bit_set::FiniteBitSet;
use rustc_macros::HashStable;
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
use rustc_span::Symbol;
@@ -385,6 +386,21 @@ impl<'tcx> Instance<'tcx> {
)
}
+ pub fn expect_resolve(
+ tcx: TyCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ def_id: DefId,
+ substs: SubstsRef<'tcx>,
+ ) -> Instance<'tcx> {
+ match ty::Instance::resolve(tcx, param_env, def_id, substs) {
+ Ok(Some(instance)) => instance,
+ _ => bug!(
+ "failed to resolve instance for {}",
+ tcx.def_path_str_with_substs(def_id, substs)
+ ),
+ }
+ }
+
// This should be kept up to date with `resolve`.
pub fn resolve_opt_const_arg(
tcx: TyCtxt<'tcx>,
@@ -525,7 +541,7 @@ impl<'tcx> Instance<'tcx> {
pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
let def_id = tcx.require_lang_item(LangItem::DropInPlace, None);
let substs = tcx.intern_substs(&[ty.into()]);
- Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap()
+ Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
}
#[instrument(level = "debug", skip(tcx), ret)]
@@ -696,7 +712,7 @@ fn polymorphize<'tcx>(
}
InternalSubsts::for_item(tcx, def_id, |param, _| {
- let is_unused = unused.contains(param.index).unwrap_or(false);
+ let is_unused = unused.is_unused(param.index);
debug!("polymorphize: param={:?} is_unused={:?}", param, is_unused);
match param.kind {
// Upvar case: If parameter is a type parameter..
@@ -718,7 +734,7 @@ fn polymorphize<'tcx>(
// Simple case: If parameter is a const or type parameter..
ty::GenericParamDefKind::Const { .. } | ty::GenericParamDefKind::Type { .. } if
// ..and is within range and unused..
- unused.contains(param.index).unwrap_or(false) =>
+ unused.is_unused(param.index) =>
// ..then use the identity for this parameter.
tcx.mk_param_from_def(param),
@@ -740,14 +756,14 @@ fn needs_fn_once_adapter_shim(
Ok(false)
}
(ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
- // The closure fn `llfn` is a `fn(&self, ...)`. We want a
+ // The closure fn `llfn` is a `fn(&self, ...)`. We want a
// `fn(&mut self, ...)`. In fact, at codegen time, these are
// basically the same thing, so we can just return llfn.
Ok(false)
}
(ty::ClosureKind::Fn | ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
// The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
- // self, ...)`. We want a `fn(self, ...)`. We can produce
+ // self, ...)`. We want a `fn(self, ...)`. We can produce
// this by doing something like:
//
// fn call_once(self, ...) { call_mut(&self, ...) }
@@ -759,3 +775,36 @@ fn needs_fn_once_adapter_shim(
(ty::ClosureKind::FnMut | ty::ClosureKind::FnOnce, _) => Err(()),
}
}
+
+// Set bits represent unused generic parameters.
+// An empty set indicates that all parameters are used.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Decodable, Encodable, HashStable)]
+pub struct UnusedGenericParams(FiniteBitSet<u32>);
+
+impl UnusedGenericParams {
+ pub fn new_all_unused(amount: u32) -> Self {
+ let mut bitset = FiniteBitSet::new_empty();
+ bitset.set_range(0..amount);
+ Self(bitset)
+ }
+
+ pub fn new_all_used() -> Self {
+ Self(FiniteBitSet::new_empty())
+ }
+
+ pub fn mark_used(&mut self, idx: u32) {
+ self.0.clear(idx);
+ }
+
+ pub fn is_unused(&self, idx: u32) -> bool {
+ self.0.contains(idx).unwrap_or(false)
+ }
+
+ pub fn is_used(&self, idx: u32) -> bool {
+ !self.is_unused(idx)
+ }
+
+ pub fn all_used(&self) -> bool {
+ self.0.is_empty()
+ }
+}
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 488fd5678..dfd016569 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -271,7 +271,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
let non_zero = !ty.is_unsafe_ptr();
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
match tail.kind() {
- ty::Param(_) | ty::Projection(_) => {
+ ty::Param(_) | ty::Alias(ty::Projection, _) => {
debug_assert!(tail.has_non_region_param());
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
}
@@ -349,7 +349,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
}
}
- ty::Projection(_) | ty::Opaque(..) => {
+ ty::Alias(..) => {
let normalized = tcx.normalize_erasing_regions(param_env, ty);
if ty == normalized {
Err(err)
@@ -670,29 +670,50 @@ where
});
}
- match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
- ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize),
- ty::Dynamic(_, _, ty::Dyn) => {
- TyMaybeWithLayout::Ty(tcx.mk_imm_ref(
- tcx.lifetimes.re_static,
- tcx.mk_array(tcx.types.usize, 3),
- ))
- /* FIXME: use actual fn pointers
- Warning: naively computing the number of entries in the
- vtable by counting the methods on the trait + methods on
- all parent traits does not work, because some methods can
- be not object safe and thus excluded from the vtable.
- Increase this counter if you tried to implement this but
- failed to do it without duplicating a lot of code from
- other places in the compiler: 2
- tcx.mk_tup(&[
- tcx.mk_array(tcx.types.usize, 3),
- tcx.mk_array(Option<fn()>),
- ])
- */
+ let mk_dyn_vtable = || {
+ tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3))
+ /* FIXME: use actual fn pointers
+ Warning: naively computing the number of entries in the
+ vtable by counting the methods on the trait + methods on
+ all parent traits does not work, because some methods can
+ be not object safe and thus excluded from the vtable.
+ Increase this counter if you tried to implement this but
+ failed to do it without duplicating a lot of code from
+ other places in the compiler: 2
+ tcx.mk_tup(&[
+ tcx.mk_array(tcx.types.usize, 3),
+ tcx.mk_array(Option<fn()>),
+ ])
+ */
+ };
+
+ let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
+ let metadata = tcx.normalize_erasing_regions(
+ cx.param_env(),
+ tcx.mk_projection(metadata_def_id, [pointee]),
+ );
+
+ // Map `Metadata = DynMetadata<dyn Trait>` back to a vtable, since it
+ // offers better information than `std::ptr::metadata::VTable`,
+ // and we rely on this layout information to trigger a panic in
+ // `std::mem::uninitialized::<&dyn Trait>()`, for example.
+ if let ty::Adt(def, substs) = metadata.kind()
+ && Some(def.did()) == tcx.lang_items().dyn_metadata()
+ && substs.type_at(0).is_trait()
+ {
+ mk_dyn_vtable()
+ } else {
+ metadata
}
- _ => bug!("TyAndLayout::field({:?}): not applicable", this),
- }
+ } else {
+ match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
+ ty::Slice(_) | ty::Str => tcx.types.usize,
+ ty::Dynamic(_, _, ty::Dyn) => mk_dyn_vtable(),
+ _ => bug!("TyAndLayout::field({:?}): not applicable", this),
+ }
+ };
+
+ TyMaybeWithLayout::Ty(metadata)
}
// Arrays and slices.
@@ -757,10 +778,9 @@ where
}
}
- ty::Projection(_)
+ ty::Alias(..)
| ty::Bound(..)
| ty::Placeholder(..)
- | ty::Opaque(..)
| ty::Param(_)
| ty::Infer(_)
| ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty),
@@ -859,7 +879,7 @@ where
//
// If the niche is a pointer, it's either valid (according
// to its type), or null (which the niche field's scalar
- // validity range encodes). This allows using
+ // validity range encodes). This allows using
// `dereferenceable_or_null` for e.g., `Option<&T>`, and
// this will continue to work as long as we don't start
// using more niches than just null (e.g., the first page of
@@ -994,7 +1014,7 @@ where
/// might (from a foreign exception or similar).
#[inline]
#[tracing::instrument(level = "debug", skip(tcx))]
-pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
+pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
if let Some(did) = fn_def_id {
// Special attribute for functions which can't unwind.
if tcx.codegen_fn_attrs(did).flags.contains(CodegenFnAttrFlags::NEVER_UNWIND) {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 3f99efd25..7dfcd1bb5 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -38,14 +38,13 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
-use rustc_hir::definitions::Definitions;
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
use rustc_hir::Node;
use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
use rustc_serialize::{Decodable, Encodable};
-use rustc_session::cstore::CrateStoreDyn;
+use rustc_session::cstore::Untracked;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ExpnId, Span};
@@ -64,6 +63,7 @@ use std::ops::ControlFlow;
use std::{fmt, str};
pub use crate::ty::diagnostics::*;
+pub use rustc_type_ir::AliasKind::*;
pub use rustc_type_ir::DynKind::*;
pub use rustc_type_ir::InferTy::*;
pub use rustc_type_ir::RegionKind::*;
@@ -79,30 +79,32 @@ pub use self::closure::{
CAPTURE_STRUCT_LOCAL,
};
pub use self::consts::{
- Const, ConstInt, ConstKind, ConstS, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
+ Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
};
pub use self::context::{
- tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
- CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GeneratorDiagnosticData,
- GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TyCtxtFeed, TypeckResults,
- UserType, UserTypeAnnotationIndex,
+ tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt,
+ TyCtxtFeed,
};
-pub use self::instance::{Instance, InstanceDef, ShortInstance};
+pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
pub use self::list::List;
pub use self::parameterized::ParameterizedOverTcx;
pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::BoundRegionKind::*;
pub use self::sty::{
- Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
+ AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef,
- ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts,
- VarianceDiagInfo,
+ Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
};
pub use self::trait_def::TraitDef;
+pub use self::typeck_results::{
+ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
+ GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
+ UserTypeAnnotationIndex,
+};
pub mod _match;
pub mod abstract_const;
@@ -143,27 +145,25 @@ mod parameterized;
mod rvalue_scopes;
mod structural_impls;
mod sty;
+mod typeck_results;
// Data types
pub type RegisteredTools = FxHashSet<Ident>;
pub struct ResolverOutputs {
- pub definitions: Definitions,
pub global_ctxt: ResolverGlobalCtxt,
pub ast_lowering: ResolverAstLowering,
+ pub untracked: Untracked,
}
#[derive(Debug)]
pub struct ResolverGlobalCtxt {
- pub cstore: Box<CrateStoreDyn>,
pub visibilities: FxHashMap<LocalDefId, Visibility>,
/// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error.
pub has_pub_restricted: bool,
/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
- /// Reference span for definitions.
- pub source_span: IndexVec<LocalDefId, Span>,
pub effective_visibilities: EffectiveVisibilities,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
@@ -238,7 +238,7 @@ pub struct ImplHeader<'tcx> {
pub predicates: Vec<Predicate<'tcx>>,
}
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
pub enum ImplSubject<'tcx> {
Trait(TraitRef<'tcx>),
Inherent(Ty<'tcx>),
@@ -436,7 +436,7 @@ pub struct CrateVariancesMap<'tcx> {
/// For each item with generics, maps to a vector of the variance
/// of its generics. If an item has no generics, it will have no
/// entry.
- pub variances: FxHashMap<DefId, &'tcx [ty::Variance]>,
+ pub variances: DefIdMap<&'tcx [ty::Variance]>,
}
// Contains information needed to resolve types and (in the future) look up
@@ -534,6 +534,17 @@ impl<'tcx> Predicate<'tcx> {
self
}
+ #[instrument(level = "debug", skip(tcx), ret)]
+ pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool {
+ match self.kind().skip_binder() {
+ ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
+ tcx.trait_is_coinductive(data.def_id())
+ }
+ ty::PredicateKind::WellFormed(_) => true,
+ _ => false,
+ }
+ }
+
/// Whether this projection can be soundly normalized.
///
/// Wf predicates must not be normalized, as normalization
@@ -677,7 +688,7 @@ impl<'tcx> Predicate<'tcx> {
//
// In terms of why this is sound, the idea is that whenever there
// is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>`
- // holds. So if there is an impl of `T:Foo<'a>` that applies to
+ // holds. So if there is an impl of `T:Foo<'a>` that applies to
// all `'a`, then we must know that `T:Bar<'a,'a>` holds for all
// `'a`.
//
@@ -689,7 +700,7 @@ impl<'tcx> Predicate<'tcx> {
// Here, if we have `for<'x> T: Foo1<'x>`, then what do we know?
// The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The
// reason is similar to the previous example: any impl of
- // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So
+ // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So
// basically we would want to collapse the bound lifetimes from
// the input (`trait_ref`) and the supertraits.
//
@@ -784,8 +795,8 @@ impl<'tcx> TraitPredicate<'tcx> {
}
}
- pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
- Self { trait_ref: self.trait_ref.with_self_type(tcx, self_ty), ..self }
+ pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+ Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
}
pub fn def_id(self) -> DefId {
@@ -944,7 +955,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::ConstS<'tcx>),
+ &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
))),
_ => core::intrinsics::unreachable(),
}
@@ -990,7 +1001,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::ConstS<'tcx> as usize)
+ (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
}
};
@@ -1013,10 +1024,28 @@ impl<'tcx> TermKind<'tcx> {
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct ProjectionPredicate<'tcx> {
- pub projection_ty: ProjectionTy<'tcx>,
+ pub projection_ty: AliasTy<'tcx>,
pub term: Term<'tcx>,
}
+impl<'tcx> ProjectionPredicate<'tcx> {
+ pub fn self_ty(self) -> Ty<'tcx> {
+ self.projection_ty.self_ty()
+ }
+
+ pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> {
+ Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
+ }
+
+ pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
+ self.projection_ty.trait_def_id(tcx)
+ }
+
+ pub fn def_id(self) -> DefId {
+ self.projection_ty.def_id
+ }
+}
+
pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
impl<'tcx> PolyProjectionPredicate<'tcx> {
@@ -1049,7 +1078,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
/// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
pub fn projection_def_id(&self) -> DefId {
// Ok to skip binder since trait `DefId` does not care about regions.
- self.skip_binder().projection_ty.item_def_id
+ self.skip_binder().projection_ty.def_id
}
}
@@ -1222,6 +1251,35 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
pub fn is_empty(&self) -> bool {
self.predicates.is_empty()
}
+
+ pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
+ (&self).into_iter()
+ }
+}
+
+impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
+ type Item = (Predicate<'tcx>, Span);
+
+ type IntoIter = std::iter::Zip<std::vec::IntoIter<Predicate<'tcx>>, std::vec::IntoIter<Span>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ debug_assert_eq!(self.predicates.len(), self.spans.len());
+ std::iter::zip(self.predicates, self.spans)
+ }
+}
+
+impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> {
+ type Item = (Predicate<'tcx>, Span);
+
+ type IntoIter = std::iter::Zip<
+ std::iter::Copied<std::slice::Iter<'a, Predicate<'tcx>>>,
+ std::iter::Copied<std::slice::Iter<'a, Span>>,
+ >;
+
+ fn into_iter(self) -> Self::IntoIter {
+ debug_assert_eq!(self.predicates.len(), self.spans.len());
+ std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied())
+ }
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)]
@@ -1299,7 +1357,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
debug!(?id_substs);
// This zip may have several times the same lifetime in `substs` paired with a different
- // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour:
+ // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour:
// it will pick the last one, which is the one we introduced in the impl-trait desugaring.
let map = substs.iter().zip(id_substs).collect();
debug!("map = {:#?}", map);
@@ -2087,7 +2145,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Look up the name of a definition across crates. This does not look at HIR.
///
- /// This method will ICE if the corresponding item does not have a name. In these cases, use
+ /// This method will ICE if the corresponding item does not have a name. In these cases, use
/// [`opt_item_name`] instead.
///
/// [`opt_item_name`]: Self::opt_item_name
@@ -2133,8 +2191,10 @@ impl<'tcx> TyCtxt<'tcx> {
) -> Option<ImplOverlapKind> {
// If either trait impl references an error, they're allowed to overlap,
// as one of them essentially doesn't exist.
- if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.references_error())
- || self.impl_trait_ref(def_id2).map_or(false, |tr| tr.references_error())
+ if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.subst_identity().references_error())
+ || self
+ .impl_trait_ref(def_id2)
+ .map_or(false, |tr| tr.subst_identity().references_error())
{
return Some(ImplOverlapKind::Permitted { marker: false });
}
@@ -2164,7 +2224,7 @@ impl<'tcx> TyCtxt<'tcx> {
let is_marker_overlap = {
let is_marker_impl = |def_id: DefId| -> bool {
let trait_ref = self.impl_trait_ref(def_id);
- trait_ref.map_or(false, |tr| self.trait_def(tr.def_id).is_marker)
+ trait_ref.map_or(false, |tr| self.trait_def(tr.skip_binder().def_id).is_marker)
};
is_marker_impl(def_id1) && is_marker_impl(def_id2)
};
@@ -2297,6 +2357,11 @@ impl<'tcx> TyCtxt<'tcx> {
self.trait_def(trait_def_id).has_auto_impl
}
+ /// Returns `true` if this is a trait alias.
+ pub fn trait_is_alias(self, trait_def_id: DefId) -> bool {
+ self.def_kind(trait_def_id) == DefKind::TraitAlias
+ }
+
pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool {
self.trait_is_auto(trait_def_id) || self.lang_items().sized_trait() == Some(trait_def_id)
}
@@ -2310,7 +2375,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
/// If it implements no trait, returns `None`.
pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> {
- self.impl_trait_ref(def_id).map(|tr| tr.def_id)
+ self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id)
}
/// If the given `DefId` describes an item belonging to a trait,
@@ -2411,8 +2476,10 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn is_const_fn_raw(self, def_id: DefId) -> bool {
- matches!(self.def_kind(def_id), DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..))
- && self.constness(def_id) == hir::Constness::Const
+ matches!(
+ self.def_kind(def_id),
+ DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure
+ ) && self.constness(def_id) == hir::Constness::Const
}
#[inline]
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 9e69544d2..24f3d1acf 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -1,15 +1,10 @@
use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::{DefId, DefIndex};
+use rustc_hir::def_id::DefIndex;
use rustc_index::vec::{Idx, IndexVec};
-use crate::middle::exported_symbols::ExportedSymbol;
-use crate::mir::Body;
-use crate::ty::{
- self, Clause, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty,
-};
+use crate::ty;
pub trait ParameterizedOverTcx: 'static {
- #[allow(unused_lifetimes)]
type Value<'tcx>;
}
@@ -37,6 +32,10 @@ impl<T: ParameterizedOverTcx> ParameterizedOverTcx for ty::Binder<'static, T> {
type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>;
}
+impl<T: ParameterizedOverTcx> ParameterizedOverTcx for ty::EarlyBinder<T> {
+ type Value<'tcx> = ty::EarlyBinder<T::Value<'tcx>>;
+}
+
#[macro_export]
macro_rules! trivially_parameterized_over_tcx {
($($ty:ty),+ $(,)?) => {
@@ -66,9 +65,10 @@ trivially_parameterized_over_tcx! {
ty::ImplPolarity,
ty::ReprOptions,
ty::TraitDef,
+ ty::UnusedGenericParams,
ty::Visibility<DefIndex>,
ty::adjustment::CoerceUnsizedInfo,
- ty::fast_reject::SimplifiedTypeGen<DefId>,
+ ty::fast_reject::SimplifiedType,
rustc_ast::Attribute,
rustc_ast::DelimArgs,
rustc_attr::ConstStability,
@@ -101,29 +101,28 @@ trivially_parameterized_over_tcx! {
rustc_type_ir::Variance,
}
-// HACK(compiler-errors): This macro rule can only take an ident,
-// not a path, due to parsing ambiguity reasons. That means we gotta
-// import all of these types above.
+// HACK(compiler-errors): This macro rule can only take a fake path,
+// not a real, due to parsing ambiguity reasons.
#[macro_export]
macro_rules! parameterized_over_tcx {
- ($($ident:ident),+ $(,)?) => {
+ ($($($fake_path:ident)::+),+ $(,)?) => {
$(
- impl $crate::ty::ParameterizedOverTcx for $ident<'static> {
- type Value<'tcx> = $ident<'tcx>;
+ impl $crate::ty::ParameterizedOverTcx for $($fake_path)::+<'static> {
+ type Value<'tcx> = $($fake_path)::+<'tcx>;
}
)*
}
}
parameterized_over_tcx! {
- Ty,
- FnSig,
- GenericPredicates,
- TraitRef,
- Const,
- Predicate,
- Clause,
- GeneratorDiagnosticData,
- Body,
- ExportedSymbol,
+ crate::middle::exported_symbols::ExportedSymbol,
+ crate::mir::Body,
+ ty::Ty,
+ ty::FnSig,
+ ty::GenericPredicates,
+ ty::TraitRef,
+ ty::Const,
+ ty::Predicate,
+ ty::Clause,
+ ty::GeneratorDiagnosticData,
}
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 667298b9b..c302c4611 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -116,7 +116,7 @@ pub trait Printer<'tcx>: Sized {
DefPathData::Impl => {
let generics = self.tcx().generics_of(def_id);
let self_ty = self.tcx().bound_type_of(def_id);
- let impl_trait_ref = self.tcx().bound_impl_trait_ref(def_id);
+ let impl_trait_ref = self.tcx().impl_trait_ref(def_id);
let (self_ty, impl_trait_ref) = if substs.len() >= generics.count() {
(
self_ty.subst(self.tcx(), substs),
@@ -169,10 +169,8 @@ pub trait Printer<'tcx>: Sized {
self.path_append(
|cx: Self| {
if trait_qualify_parent {
- let trait_ref = ty::TraitRef::new(
- parent_def_id,
- cx.tcx().intern_substs(parent_substs),
- );
+ let trait_ref =
+ cx.tcx().mk_trait_ref(parent_def_id, parent_substs.iter().copied());
cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
} else {
cx.print_def_path(parent_def_id, parent_substs)
@@ -275,10 +273,9 @@ fn characteristic_def_id_of_type_cached<'a>(
| ty::Uint(_)
| ty::Str
| ty::FnPtr(_)
- | ty::Projection(_)
+ | ty::Alias(..)
| ty::Placeholder(..)
| ty::Param(_)
- | ty::Opaque(..)
| ty::Infer(_)
| ty::Bound(..)
| ty::Error(_)
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 5303341ba..ae7c20fff 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -10,12 +10,13 @@ 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, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData};
+use rustc_hir::definitions::{DefKey, DefPathData, DefPathDataName, DisambiguatedDefPathData};
use rustc_hir::LangItem;
use rustc_session::config::TrimmedDefPaths;
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
use rustc_session::Limit;
use rustc_span::symbol::{kw, Ident, Symbol};
+use rustc_span::FileNameDisplayPreference;
use rustc_target::abi::Size;
use rustc_target::spec::abi::Abi;
use smallvec::SmallVec;
@@ -23,7 +24,6 @@ use smallvec::SmallVec;
use std::cell::Cell;
use std::char;
use std::collections::BTreeMap;
-use std::convert::TryFrom;
use std::fmt::{self, Write as _};
use std::iter;
use std::ops::{ControlFlow, Deref, DerefMut};
@@ -63,6 +63,7 @@ thread_local! {
static FORCE_IMPL_FILENAME_LINE: Cell<bool> = const { Cell::new(false) };
static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
+ static FORCE_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
static NO_QUERIES: Cell<bool> = const { Cell::new(false) };
static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
}
@@ -116,6 +117,7 @@ define_helper!(
/// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`,
/// if no other `Vec` is found.
fn with_no_trimmed_paths(NoTrimmedGuard, NO_TRIMMED_PATH);
+ fn with_forced_trimmed_paths(ForceTrimmedGuard, FORCE_TRIMMED_PATH);
/// Prevent selection of visible paths. `Display` impl of DefId will prefer
/// visible (public) reexports of types as paths.
fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
@@ -281,6 +283,8 @@ pub trait PrettyPrinter<'tcx>:
/// This is typically the case for all non-`'_` regions.
fn should_print_region(&self, region: ty::Region<'tcx>) -> bool;
+ fn reset_type_limit(&mut self) {}
+
// Defaults (should not be overridden):
/// If possible, this returns a global path resolving to `def_id` that is visible
@@ -295,11 +299,89 @@ pub trait PrettyPrinter<'tcx>:
self.try_print_visible_def_path_recur(def_id, &mut callers)
}
+ // Given a `DefId`, produce a short name. For types and traits, it prints *only* its name,
+ // For associated items on traits it prints out the trait's name and the associated item's name.
+ // For enum variants, if they have an unique name, then we only print the name, otherwise we
+ // print the enum name and the variant name. Otherwise, we do not print anything and let the
+ // caller use the `print_def_path` fallback.
+ fn force_print_trimmed_def_path(
+ mut self,
+ def_id: DefId,
+ ) -> Result<(Self::Path, bool), Self::Error> {
+ let key = self.tcx().def_key(def_id);
+ let visible_parent_map = self.tcx().visible_parent_map(());
+ let kind = self.tcx().def_kind(def_id);
+
+ let get_local_name = |this: &Self, name, def_id, key: DefKey| {
+ if let Some(visible_parent) = visible_parent_map.get(&def_id)
+ && let actual_parent = this.tcx().opt_parent(def_id)
+ && let DefPathData::TypeNs(_) = key.disambiguated_data.data
+ && Some(*visible_parent) != actual_parent
+ {
+ this
+ .tcx()
+ .module_children(visible_parent)
+ .iter()
+ .filter(|child| child.res.opt_def_id() == Some(def_id))
+ .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore)
+ .map(|child| child.ident.name)
+ .unwrap_or(name)
+ } else {
+ name
+ }
+ };
+ if let DefKind::Variant = kind
+ && 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())?;
+ return Ok((self, true));
+ }
+ if let Some(symbol) = key.get_opt_name() {
+ if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = kind
+ && let Some(parent) = self.tcx().opt_parent(def_id)
+ && let parent_key = self.tcx().def_key(parent)
+ && 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("::")?;
+ } else if let DefKind::Variant = kind
+ && let Some(parent) = self.tcx().opt_parent(def_id)
+ && let parent_key = self.tcx().def_key(parent)
+ && let Some(symbol) = parent_key.get_opt_name()
+ {
+ // Enum
+
+ // 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("::")?;
+ } else if let DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Trait
+ | DefKind::TyAlias | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind
+ {
+ } else {
+ // If not covered above, like for example items out of `impl` blocks, fallback.
+ return Ok((self, false));
+ }
+ self.write_str(get_local_name(&self, symbol, def_id, key).as_str())?;
+ return Ok((self, true));
+ }
+ Ok((self, false))
+ }
+
/// 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<(Self::Path, bool), Self::Error> {
+ if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ let (s, trimmed) = self.force_print_trimmed_def_path(def_id)?;
+ if trimmed {
+ return Ok((s, true));
+ }
+ self = s;
+ }
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())
@@ -311,7 +393,7 @@ pub trait PrettyPrinter<'tcx>:
match self.tcx().trimmed_def_paths(()).get(&def_id) {
None => Ok((self, false)),
Some(symbol) => {
- self.write_str(symbol.as_str())?;
+ write!(self, "{}", Ident::with_dummy_span(*symbol))?;
Ok((self, true))
}
}
@@ -639,17 +721,17 @@ pub trait PrettyPrinter<'tcx>:
ty::Foreign(def_id) => {
p!(print_def_path(def_id, &[]));
}
- ty::Projection(ref data) => {
+ ty::Alias(ty::Projection, ref data) => {
if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
- && self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+ && self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
{
- return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs);
+ return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
} else {
p!(print(data))
}
}
ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
- ty::Opaque(def_id, substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
// FIXME(eddyb) print this with `print_def_path`.
// We use verbose printing in 'NO_QUERIES' mode, to
// avoid needing to call `predicates_of`. This should
@@ -664,7 +746,9 @@ pub trait PrettyPrinter<'tcx>:
let parent = self.tcx().parent(def_id);
match self.tcx().def_kind(parent) {
DefKind::TyAlias | DefKind::AssocTy => {
- if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() {
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
+ *self.tcx().type_of(parent).kind()
+ {
if d == def_id {
// If the type alias directly starts with the `impl` of the
// opaque type we're printing, then skip the `::{opaque#1}`.
@@ -737,11 +821,16 @@ pub trait PrettyPrinter<'tcx>:
p!("@", print_def_path(did.to_def_id(), substs));
} else {
let span = self.tcx().def_span(did);
+ let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ FileNameDisplayPreference::Short
+ } else {
+ FileNameDisplayPreference::Remapped
+ };
p!(write(
"@{}",
// This may end up in stderr diagnostics but it may also be emitted
// into MIR. Hence we use the remapped path if available
- self.tcx().sess.source_map().span_to_embeddable_string(span)
+ self.tcx().sess.source_map().span_to_string(span, preference)
));
}
} else {
@@ -765,24 +854,7 @@ pub trait PrettyPrinter<'tcx>:
}
p!("]");
}
- ty::Array(ty, sz) => {
- p!("[", print(ty), "; ");
- if self.should_print_verbose() {
- p!(write("{:?}", sz));
- } else if let ty::ConstKind::Unevaluated(..) = sz.kind() {
- // Do not try to evaluate unevaluated constants. If we are const evaluating an
- // array length anon const, rustc will (with debug assertions) print the
- // constant's path. Which will end up here again.
- p!("_");
- } else if let Some(n) = sz.kind().try_to_bits(self.tcx().data_layout.pointer_size) {
- p!(write("{}", n));
- } else if let ty::ConstKind::Param(param) = sz.kind() {
- p!(print(param));
- } else {
- p!("_");
- }
- p!("]")
- }
+ ty::Array(ty, sz) => p!("[", print(ty), "; ", print(sz), "]"),
ty::Slice(ty) => p!("[", print(ty), "]"),
}
@@ -940,8 +1012,8 @@ pub trait PrettyPrinter<'tcx>:
// Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
// unless we can find out what generator return type it comes from.
let term = if let Some(ty) = term.skip_binder().ty()
- && let ty::Projection(proj) = ty.kind()
- && let Some(assoc) = tcx.opt_associated_item(proj.item_def_id)
+ && let ty::Alias(ty::Projection, proj) = ty.kind()
+ && let Some(assoc) = tcx.opt_associated_item(proj.def_id)
&& assoc.trait_container(tcx) == tcx.lang_items().gen_trait()
&& assoc.name == rustc_span::sym::Return
{
@@ -1214,21 +1286,25 @@ pub trait PrettyPrinter<'tcx>:
match ct.kind() {
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
match self.tcx().def_kind(def.did) {
- DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => {
+ DefKind::Const | DefKind::AssocConst => {
p!(print_value_path(def.did, substs))
}
- _ => {
- if def.is_local() {
- let span = self.tcx().def_span(def.did);
- if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
- p!(write("{}", snip))
- } else {
- print_underscore!()
- }
+ DefKind::AnonConst => {
+ if def.is_local()
+ && let span = self.tcx().def_span(def.did)
+ && let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
+ {
+ p!(write("{}", snip))
} else {
- print_underscore!()
+ // Do not call `print_value_path` as if a parent of this anon const is an impl it will
+ // attempt to print out the impl trait ref i.e. `<T as Trait>::{constant#0}`. This would
+ // cause printing to enter an infinite recursion if the anon const is in the self type i.e.
+ // `impl<T: Default> Default for [T; 32 - 1 - 1 - 1] {`
+ // where we would try to print `<[T; /* print `constant#0` again */] as Default>::{constant#0}`
+ p!(write("{}::{}", self.tcx().crate_name(def.did.krate), self.tcx().def_path(def.did).to_string_no_crate_verbose()))
}
}
+ defkind => bug!("`{:?}` has unexpcted defkind {:?}", ct, defkind),
}
}
ty::ConstKind::Infer(infer_ct) => {
@@ -1250,7 +1326,7 @@ pub trait PrettyPrinter<'tcx>:
ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
// FIXME(generic_const_exprs):
// write out some legible representation of an abstract const?
- ty::ConstKind::Expr(_) => p!("[Const Expr]"),
+ ty::ConstKind::Expr(_) => p!("[const expr]"),
ty::ConstKind::Error(_) => p!("[const error]"),
};
Ok(self)
@@ -1894,6 +1970,10 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
self.0.ty_infer_name_resolver.as_ref().and_then(|func| func(id))
}
+ fn reset_type_limit(&mut self) {
+ self.printed_type_count = 0;
+ }
+
fn const_infer_name(&self, id: ty::ConstVid<'tcx>) -> Option<Symbol> {
self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id))
}
@@ -2039,9 +2119,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
- // These printouts are concise. They do not contain all the information
+ // These printouts are concise. They do not contain all the information
// the user might want to diagnose an error, but there is basically no way
- // to fit that into a short string. Hence the recommendation to use
+ // 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) => {
@@ -2388,7 +2468,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if not_previously_inserted {
ty.super_visit_with(self)
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
}
@@ -2574,7 +2654,7 @@ define_print_and_forward_display! {
}
ty::ExistentialProjection<'tcx> {
- let name = cx.tcx().associated_item(self.item_def_id).name;
+ let name = cx.tcx().associated_item(self.def_id).name;
p!(write("{} = ", name), print(self.term))
}
@@ -2635,11 +2715,15 @@ define_print_and_forward_display! {
}
ty::SubtypePredicate<'tcx> {
- p!(print(self.a), " <: ", print(self.b))
+ p!(print(self.a), " <: ");
+ cx.reset_type_limit();
+ p!(print(self.b))
}
ty::CoercePredicate<'tcx> {
- p!(print(self.a), " -> ", print(self.b))
+ p!(print(self.a), " -> ");
+ cx.reset_type_limit();
+ p!(print(self.b))
}
ty::TraitPredicate<'tcx> {
@@ -2651,7 +2735,9 @@ define_print_and_forward_display! {
}
ty::ProjectionPredicate<'tcx> {
- p!(print(self.projection_ty), " == ", print(self.term))
+ p!(print(self.projection_ty), " == ");
+ cx.reset_type_limit();
+ p!(print(self.term))
}
ty::Term<'tcx> {
@@ -2661,8 +2747,8 @@ define_print_and_forward_display! {
}
}
- ty::ProjectionTy<'tcx> {
- p!(print_def_path(self.item_def_id, self.substs));
+ ty::AliasTy<'tcx> {
+ p!(print_def_path(self.def_id, self.substs));
}
ty::ClosureKind {
@@ -2796,13 +2882,19 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
/// `std::vec::Vec` to just `Vec`, as long as there is no other `Vec` importable anywhere.
///
/// 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> {
let mut map: FxHashMap<DefId, Symbol> = FxHashMap::default();
if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths {
+ // Trimming paths is expensive and not optimized, since we expect it to only be used for error reporting.
+ //
// 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("trimmed_def_paths constructed");
+ tcx.sess.delay_good_path_bug(
+ "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging",
+ );
}
let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index 642900d3a..9d4ee22a7 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -34,7 +34,7 @@ use crate::ty::layout::TyAndLayout;
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::util::AlwaysRequiresDrop;
use crate::ty::GeneratorDiagnosticData;
-use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
+use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams};
use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_attr as attr;
@@ -50,7 +50,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::hir_id::OwnerId;
use rustc_hir::lang_items::{LangItem, LanguageItems};
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
-use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
+use rustc_index::vec::IndexVec;
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::cstore::{CrateDepKind, CrateSource};
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index c759fb6d5..65fd8d975 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -106,7 +106,7 @@ pub trait TypeRelation<'tcx>: Sized {
T: Relate<'tcx>;
}
-pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy {
+pub trait Relate<'tcx>: TypeFoldable<'tcx> + PartialEq + Copy {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: Self,
@@ -270,21 +270,17 @@ impl<'tcx> Relate<'tcx> for abi::Abi {
}
}
-impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
+impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
- a: ty::ProjectionTy<'tcx>,
- b: ty::ProjectionTy<'tcx>,
- ) -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> {
- if a.item_def_id != b.item_def_id {
- Err(TypeError::ProjectionMismatched(expected_found(
- relation,
- a.item_def_id,
- b.item_def_id,
- )))
+ a: ty::AliasTy<'tcx>,
+ b: ty::AliasTy<'tcx>,
+ ) -> RelateResult<'tcx, ty::AliasTy<'tcx>> {
+ if a.def_id != b.def_id {
+ Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
} else {
let substs = relation.relate(a.substs, b.substs)?;
- Ok(ty::ProjectionTy { item_def_id: a.item_def_id, substs: &substs })
+ Ok(relation.tcx().mk_alias_ty(a.def_id, substs))
}
}
}
@@ -295,12 +291,8 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
a: ty::ExistentialProjection<'tcx>,
b: ty::ExistentialProjection<'tcx>,
) -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> {
- if a.item_def_id != b.item_def_id {
- Err(TypeError::ProjectionMismatched(expected_found(
- relation,
- a.item_def_id,
- b.item_def_id,
- )))
+ if a.def_id != b.def_id {
+ Err(TypeError::ProjectionMismatched(expected_found(relation, a.def_id, b.def_id)))
} else {
let term = relation.relate_with_variance(
ty::Invariant,
@@ -314,7 +306,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
a.substs,
b.substs,
)?;
- Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term })
+ Ok(ty::ExistentialProjection { def_id: a.def_id, substs, term })
}
}
}
@@ -330,7 +322,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
} else {
let substs = relate_substs(relation, a.substs, b.substs)?;
- Ok(ty::TraitRef { def_id: a.def_id, substs })
+ Ok(relation.tcx().mk_trait_ref(a.def_id, substs))
}
}
}
@@ -351,7 +343,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
}
}
-#[derive(Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
+#[derive(PartialEq, Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
@@ -422,7 +414,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
bug!("bound types encountered in super_relate_tys")
}
- (&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(tcx.ty_error()),
+ (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error_with_guaranteed(guar)),
(&ty::Never, _)
| (&ty::Char, _)
@@ -436,7 +428,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
Ok(a)
}
- (&ty::Param(ref a_p), &ty::Param(ref b_p)) if a_p.index == b_p.index => Ok(a),
+ (ty::Param(a_p), ty::Param(b_p)) if a_p.index == b_p.index => Ok(a),
(ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
@@ -559,14 +551,15 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
}
// these two are already handled downstream in case of lazy normalization
- (&ty::Projection(a_data), &ty::Projection(b_data)) => {
+ (&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => {
let projection_ty = relation.relate(a_data, b_data)?;
- Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
+ Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs))
}
- (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
- if a_def_id == b_def_id =>
- {
+ (
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }),
+ &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }),
+ ) if a_def_id == b_def_id => {
if relation.intercrate() {
// During coherence, opaque types should be treated as equal to each other, even if their generic params
// differ, as they could resolve to the same hidden type, even for different generic params.
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 9f70b4f1f..7d4d35b7f 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -7,7 +7,7 @@ use crate::mir::{Field, ProjectionKind};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
+use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
use rustc_data_structures::functor::IdFunctor;
use rustc_hir::def::Namespace;
use rustc_index::vec::{Idx, IndexVec};
@@ -99,12 +99,6 @@ impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
}
}
-impl fmt::Debug for ty::RegionVid {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "'_#{}r", self.index())
- }
-}
-
impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
with_no_trimmed_paths!(fmt::Display::fmt(self, f))
@@ -186,6 +180,15 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
}
}
+impl<'tcx> fmt::Debug for AliasTy<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("AliasTy")
+ .field("substs", &self.substs)
+ .field("def_id", &self.def_id)
+ .finish()
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
// Atomic structs
//
@@ -233,6 +236,7 @@ TrivialTypeTraversalAndLiftImpls! {
crate::ty::BoundRegionKind,
crate::ty::AssocItem,
crate::ty::AssocKind,
+ crate::ty::AliasKind,
crate::ty::Placeholder<crate::ty::BoundRegionKind>,
crate::ty::ClosureKind,
crate::ty::FreeRegion,
@@ -363,7 +367,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::AdtDef<'tcx> {
impl<'tcx> TypeVisitable<'tcx> for ty::AdtDef<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
@@ -461,7 +465,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
let slot = Rc::get_mut_unchecked(&mut unique);
// Semantically move the contained type out from `unique`, fold
- // it, then move the folded value back into `unique`. Should
+ // it, then move the folded value back into `unique`. Should
// folding fail, `ManuallyDrop` ensures that the "moved-out"
// value is not re-dropped.
let owned = ManuallyDrop::take(slot);
@@ -507,7 +511,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> {
let slot = Arc::get_mut_unchecked(&mut unique);
// Semantically move the contained type out from `unique`, fold
- // it, then move the folded value back into `unique`. Should
+ // it, then move the folded value back into `unique`. Should
// folding fail, `ManuallyDrop` ensures that the "moved-out"
// value is not re-dropped.
let owned = ManuallyDrop::take(slot);
@@ -651,8 +655,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> {
}
ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?),
ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?),
- ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?),
- ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?),
+ ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
ty::Bool
| ty::Char
@@ -697,8 +700,7 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> {
ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
ty::GeneratorWitness(ref types) => types.visit_with(visitor),
ty::Closure(_did, ref substs) => substs.visit_with(visitor),
- ty::Projection(ref data) => data.visit_with(visitor),
- ty::Opaque(_, ref substs) => substs.visit_with(visitor),
+ ty::Alias(_, ref data) => data.visit_with(visitor),
ty::Bool
| ty::Char
@@ -712,7 +714,7 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> {
| ty::Placeholder(..)
| ty::Param(..)
| ty::Never
- | ty::Foreign(..) => ControlFlow::CONTINUE,
+ | ty::Foreign(..) => ControlFlow::Continue(()),
}
}
}
@@ -740,7 +742,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Region<'tcx> {
impl<'tcx> TypeSuperVisitable<'tcx> for ty::Region<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
@@ -842,7 +844,7 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 9cbda95a4..91a7d5d38 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -7,8 +7,8 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
use crate::ty::visit::ValidateBoundVars;
use crate::ty::InferTy::*;
use crate::ty::{
- self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
- TypeVisitor,
+ self, AdtDef, DefIdTree, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable,
+ TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use crate::ty::{List, ParamEnv};
use hir::def::DefKind;
@@ -100,6 +100,13 @@ impl BoundRegionKind {
None
}
+
+ pub fn get_id(&self) -> Option<DefId> {
+ match *self {
+ BoundRegionKind::BrNamed(id, _) => return Some(id),
+ _ => None,
+ }
+ }
}
pub trait Article {
@@ -205,7 +212,7 @@ static_assert_size!(TyKind<'_>, 32);
///
/// ## Generators
///
-/// Generators are handled similarly in `GeneratorSubsts`. The set of
+/// Generators are handled similarly in `GeneratorSubsts`. The set of
/// type parameters is similar, but `CK` and `CS` are replaced by the
/// following type parameters:
///
@@ -217,7 +224,7 @@ static_assert_size!(TyKind<'_>, 32);
/// * `GR`: The "return type", which is the type of value returned upon
/// completion of the generator.
/// * `GW`: The "generator witness".
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
pub struct ClosureSubsts<'tcx> {
/// Lifetime and type parameters from the enclosing function,
/// concatenated with a tuple containing the types of the upvars.
@@ -348,7 +355,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
}
/// Similar to `ClosureSubsts`; see the above documentation for more.
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)]
pub struct GeneratorSubsts<'tcx> {
pub substs: SubstsRef<'tcx>,
}
@@ -693,7 +700,7 @@ impl<'tcx> ExistentialPredicate<'tcx> {
match (*self, *other) {
(Trait(_), Trait(_)) => Ordering::Equal,
(Projection(ref a), Projection(ref b)) => {
- tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id))
+ tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
}
(AutoTrait(ref a), AutoTrait(ref b)) => {
tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
@@ -816,14 +823,13 @@ impl<'tcx> List<ty::PolyExistentialPredicate<'tcx>> {
pub struct TraitRef<'tcx> {
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
+ /// This field exists to prevent the creation of `TraitRef` without
+ /// calling [TyCtxt::mk_trait_ref].
+ pub(super) _use_mk_trait_ref_instead: (),
}
impl<'tcx> TraitRef<'tcx> {
- pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> {
- TraitRef { def_id, substs }
- }
-
- pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+ pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
tcx.mk_trait_ref(
self.def_id,
[self_ty.into()].into_iter().chain(self.substs.iter().skip(1)),
@@ -833,10 +839,7 @@ impl<'tcx> TraitRef<'tcx> {
/// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
/// are the parameters defined on trait.
pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> {
- ty::Binder::dummy(TraitRef {
- def_id,
- substs: InternalSubsts::identity_for_item(tcx, def_id),
- })
+ ty::Binder::dummy(tcx.mk_trait_ref(def_id, InternalSubsts::identity_for_item(tcx, def_id)))
}
#[inline]
@@ -850,7 +853,7 @@ impl<'tcx> TraitRef<'tcx> {
substs: SubstsRef<'tcx>,
) -> ty::TraitRef<'tcx> {
let defs = tcx.generics_of(trait_id);
- ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) }
+ tcx.mk_trait_ref(trait_id, tcx.intern_substs(&substs[..defs.params.len()]))
}
}
@@ -928,6 +931,12 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
}
}
+impl rustc_errors::IntoDiagnosticArg for PolyExistentialTraitRef<'_> {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum BoundVariableKind {
@@ -980,8 +989,12 @@ where
/// contain any bound vars that would be bound by the
/// binder. This is commonly used to 'inject' a value T into a
/// different binding level.
+ #[track_caller]
pub fn dummy(value: T) -> Binder<'tcx, T> {
- assert!(!value.has_escaping_bound_vars());
+ assert!(
+ !value.has_escaping_bound_vars(),
+ "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
+ );
Binder(value, ty::List::empty())
}
@@ -1128,30 +1141,144 @@ impl<'tcx, T> Binder<'tcx, Option<T>> {
}
}
-/// Represents the projection of an associated type. In explicit UFCS
-/// form this would be written `<T as Trait<..>>::N`.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
+ pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> {
+ let bound_vars = self.1;
+ self.0.into_iter().map(|v| Binder(v, bound_vars))
+ }
+}
+
+struct SkipBindersAt<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ index: ty::DebruijnIndex,
+}
+
+impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> {
+ type Error = ();
+
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
+ where
+ T: ty::TypeFoldable<'tcx>,
+ {
+ self.index.shift_in(1);
+ let value = t.try_map_bound(|t| t.try_fold_with(self));
+ self.index.shift_out(1);
+ value
+ }
+
+ fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+ if !ty.has_escaping_bound_vars() {
+ Ok(ty)
+ } else if let ty::Bound(index, bv) = *ty.kind() {
+ if index == self.index {
+ Err(())
+ } else {
+ Ok(self.tcx().mk_ty(ty::Bound(index.shifted_out(1), bv)))
+ }
+ } else {
+ ty.try_super_fold_with(self)
+ }
+ }
+
+ fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
+ if !r.has_escaping_bound_vars() {
+ Ok(r)
+ } else if let ty::ReLateBound(index, bv) = r.kind() {
+ if index == self.index {
+ Err(())
+ } else {
+ Ok(self.tcx().mk_region(ty::ReLateBound(index.shifted_out(1), bv)))
+ }
+ } else {
+ r.try_super_fold_with(self)
+ }
+ }
+
+ fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
+ if !ct.has_escaping_bound_vars() {
+ Ok(ct)
+ } else if let ty::ConstKind::Bound(index, bv) = ct.kind() {
+ if index == self.index {
+ Err(())
+ } else {
+ Ok(self.tcx().mk_const(
+ ty::ConstKind::Bound(index.shifted_out(1), bv),
+ ct.ty().try_fold_with(self)?,
+ ))
+ }
+ } else {
+ ct.try_super_fold_with(self)
+ }
+ }
+
+ fn try_fold_predicate(
+ &mut self,
+ p: ty::Predicate<'tcx>,
+ ) -> Result<ty::Predicate<'tcx>, Self::Error> {
+ if !p.has_escaping_bound_vars() { Ok(p) } else { p.try_super_fold_with(self) }
+ }
+}
+
+/// Represents the projection of an associated type.
+///
+/// For a projection, this would be `<Ty as Trait<...>>::N`.
+///
+/// For an opaque type, there is no explicit syntax.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct ProjectionTy<'tcx> {
- /// The parameters of the associated item.
+pub struct AliasTy<'tcx> {
+ /// The parameters of the associated or opaque item.
+ ///
+ /// For a projection, these are the substitutions for the trait and the
+ /// GAT substitutions, if there are any.
+ ///
+ /// For RPIT the substitutions are for the generics of the function,
+ /// while for TAIT it is used for the generic parameters of the alias.
pub substs: SubstsRef<'tcx>,
- /// The `DefId` of the `TraitItem` for the associated type `N`.
+ /// The `DefId` of the `TraitItem` for the associated type `N` if this is a projection,
+ /// or the `OpaqueType` item if this is an opaque.
///
- /// Note that this is not the `DefId` of the `TraitRef` containing this
- /// associated type, which is in `tcx.associated_item(item_def_id).container`,
- /// aka. `tcx.parent(item_def_id).unwrap()`.
- pub item_def_id: DefId,
+ /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
+ /// underlying type if the type is an opaque.
+ ///
+ /// Note that if this is an associated type, this is not the `DefId` of the
+ /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`,
+ /// aka. `tcx.parent(def_id)`.
+ pub def_id: DefId,
+
+ /// This field exists to prevent the creation of `AliasTy` without using
+ /// [TyCtxt::mk_alias_ty].
+ pub(super) _use_mk_alias_ty_instead: (),
}
-impl<'tcx> ProjectionTy<'tcx> {
- pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
- match tcx.def_kind(self.item_def_id) {
- DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id),
+impl<'tcx> AliasTy<'tcx> {
+ pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind {
+ match tcx.def_kind(self.def_id) {
+ DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection,
+ DefKind::OpaqueTy => ty::Opaque,
+ kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
+ }
+ }
+
+ pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ tcx.mk_ty(ty::Alias(self.kind(tcx), self))
+ }
+}
+
+/// The following methods work only with associated type projections.
+impl<'tcx> AliasTy<'tcx> {
+ pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
+ match tcx.def_kind(self.def_id) {
+ DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
DefKind::ImplTraitPlaceholder => {
- tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id))
+ tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
}
- kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"),
+ kind => bug!("expected a projection AliasTy; found {kind:?}"),
}
}
@@ -1159,14 +1286,14 @@ impl<'tcx> ProjectionTy<'tcx> {
/// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
/// then this function would return a `T: Iterator` trait reference and `['a]` as the own substs
pub fn trait_ref_and_own_substs(
- &self,
+ self,
tcx: TyCtxt<'tcx>,
) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
- let def_id = tcx.parent(self.item_def_id);
- assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
- let trait_generics = tcx.generics_of(def_id);
+ debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst));
+ let trait_def_id = self.trait_def_id(tcx);
+ let trait_generics = tcx.generics_of(trait_def_id);
(
- ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
+ tcx.mk_trait_ref(trait_def_id, self.substs.truncate_to(tcx, trait_generics)),
&self.substs[trait_generics.count()..],
)
}
@@ -1178,14 +1305,18 @@ impl<'tcx> ProjectionTy<'tcx> {
/// WARNING: This will drop the substs for generic associated types
/// consider calling [Self::trait_ref_and_own_substs] to get those
/// as well.
- pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
+ pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
let def_id = self.trait_def_id(tcx);
- ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) }
+ tcx.mk_trait_ref(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
}
- pub fn self_ty(&self) -> Ty<'tcx> {
+ pub fn self_ty(self) -> Ty<'tcx> {
self.substs.type_at(0)
}
+
+ pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+ tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)))
+ }
}
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
@@ -1354,9 +1485,8 @@ pub struct ConstVid<'tcx> {
rustc_index::newtype_index! {
/// A **region** (lifetime) **v**ariable **ID**.
#[derive(HashStable)]
- pub struct RegionVid {
- DEBUG_FORMAT = custom,
- }
+ #[debug_format = "'_#{}r"]
+ pub struct RegionVid {}
}
impl Atom for RegionVid {
@@ -1367,7 +1497,7 @@ impl Atom for RegionVid {
rustc_index::newtype_index! {
#[derive(HashStable)]
- pub struct BoundVar { .. }
+ pub struct BoundVar {}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
@@ -1394,7 +1524,7 @@ impl From<BoundVar> for BoundTy {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct ExistentialProjection<'tcx> {
- pub item_def_id: DefId,
+ pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
pub term: Term<'tcx>,
}
@@ -1407,7 +1537,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
/// then this function would return an `exists T. T: Iterator` existential trait
/// reference.
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
- let def_id = tcx.parent(self.item_def_id);
+ let def_id = tcx.parent(self.def_id);
let subst_count = tcx.generics_of(def_id).count() - 1;
let substs = tcx.intern_substs(&self.substs[..subst_count]);
ty::ExistentialTraitRef { def_id, substs }
@@ -1422,10 +1552,8 @@ impl<'tcx> ExistentialProjection<'tcx> {
debug_assert!(!self_ty.has_escaping_bound_vars());
ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- item_def_id: self.item_def_id,
- substs: tcx.mk_substs_trait(self_ty, self.substs),
- },
+ projection_ty: tcx
+ .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs)),
term: self.term,
}
}
@@ -1438,7 +1566,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
projection_predicate.projection_ty.substs.type_at(0);
Self {
- item_def_id: projection_predicate.projection_ty.item_def_id,
+ def_id: projection_predicate.projection_ty.def_id,
substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
term: projection_predicate.term,
}
@@ -1455,7 +1583,7 @@ impl<'tcx> PolyExistentialProjection<'tcx> {
}
pub fn item_def_id(&self) -> DefId {
- self.skip_binder().item_def_id
+ self.skip_binder().def_id
}
}
@@ -1661,7 +1789,7 @@ impl<'tcx> Ty<'tcx> {
}
#[inline]
- pub fn is_ty_infer(self) -> bool {
+ pub fn is_ty_or_numeric_infer(self) -> bool {
matches!(self.kind(), Infer(_))
}
@@ -1904,7 +2032,7 @@ impl<'tcx> Ty<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if self.0 == t { ControlFlow::BREAK } else { t.super_visit_with(self) }
+ if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) }
}
}
@@ -1962,7 +2090,7 @@ impl<'tcx> Ty<'tcx> {
#[inline]
pub fn is_impl_trait(self) -> bool {
- matches!(self.kind(), Opaque(..))
+ matches!(self.kind(), Alias(ty::Opaque, ..))
}
#[inline]
@@ -2029,7 +2157,7 @@ impl<'tcx> Ty<'tcx> {
ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
- ty::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => {
+ ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
let assoc_items = tcx.associated_item_def_ids(
tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
);
@@ -2109,7 +2237,7 @@ impl<'tcx> Ty<'tcx> {
// type parameters only have unit metadata if they're sized, so return true
// to make sure we double check this during confirmation
- ty::Param(_) | ty::Projection(_) | ty::Opaque(..) => (tcx.types.unit, true),
+ ty::Param(_) | ty::Alias(..) => (tcx.types.unit, true),
ty::Infer(ty::TyVar(_))
| ty::Bound(..)
@@ -2185,7 +2313,7 @@ impl<'tcx> Ty<'tcx> {
ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
- ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false,
+ ty::Alias(..) | ty::Param(_) => false,
ty::Infer(ty::TyVar(_)) => false,
@@ -2241,9 +2369,12 @@ impl<'tcx> Ty<'tcx> {
ty::Generator(..) | ty::GeneratorWitness(..) => false,
// Might be, but not "trivial" so just giving the safe answer.
- ty::Adt(..) | ty::Closure(..) | ty::Opaque(..) => false,
+ ty::Adt(..) | ty::Closure(..) => false,
+
+ // Needs normalization or revealing to determine, so no is the safe answer.
+ ty::Alias(..) => false,
- ty::Projection(..) | ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
+ ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
ty::Bound(..) | ty::Placeholder(..) => {
bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self);
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index a1b084a5e..a07582fc8 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -7,6 +7,7 @@ use crate::ty::visit::{TypeVisitable, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
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};
@@ -36,6 +37,12 @@ pub struct GenericArg<'tcx> {
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>,
}
+impl<'tcx> IntoDiagnosticArg for GenericArg<'tcx> {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
const TAG_MASK: usize = 0b11;
const TYPE_TAG: usize = 0b00;
const REGION_TAG: usize = 0b01;
@@ -90,7 +97,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::ConstS<'tcx> as usize)
+ (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
}
};
@@ -166,7 +173,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::ConstS<'tcx>),
+ &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
))),
_ => intrinsics::unreachable(),
}
@@ -202,7 +209,7 @@ impl<'tcx> GenericArg<'tcx> {
pub fn is_non_region_infer(self) -> bool {
match self.unpack() {
GenericArgKind::Lifetime(_) => false,
- GenericArgKind::Type(ty) => ty.is_ty_infer(),
+ GenericArgKind::Type(ty) => ty.is_ty_or_numeric_infer(),
GenericArgKind::Const(ct) => ct.is_ct_infer(),
}
}
@@ -252,7 +259,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArg<'tcx> {
}
}
-/// A substitution mapping generic parameters to new values.
+/// List of generic arguments that are gonna be used to substitute generic parameters.
pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>;
pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
@@ -348,7 +355,7 @@ impl<'tcx> InternalSubsts<'tcx> {
substs.reserve(defs.params.len());
for param in &defs.params {
let kind = mk_kind(param, substs);
- assert_eq!(param.index as usize, substs.len());
+ assert_eq!(param.index as usize, substs.len(), "{substs:#?}, {defs:#?}");
substs.push(kind);
}
}
@@ -400,6 +407,7 @@ impl<'tcx> InternalSubsts<'tcx> {
}
#[inline]
+ #[track_caller]
pub fn type_at(&self, i: usize) -> Ty<'tcx> {
if let GenericArgKind::Type(ty) = self[i].unpack() {
ty
@@ -409,6 +417,7 @@ impl<'tcx> InternalSubsts<'tcx> {
}
#[inline]
+ #[track_caller]
pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
if let GenericArgKind::Lifetime(lt) = self[i].unpack() {
lt
@@ -418,6 +427,7 @@ impl<'tcx> InternalSubsts<'tcx> {
}
#[inline]
+ #[track_caller]
pub fn const_at(&self, i: usize) -> ty::Const<'tcx> {
if let GenericArgKind::Const(ct) = self[i].unpack() {
ct
@@ -427,6 +437,7 @@ impl<'tcx> InternalSubsts<'tcx> {
}
#[inline]
+ #[track_caller]
pub fn type_for_def(&self, def: &ty::GenericParamDef) -> GenericArg<'tcx> {
self.type_at(def.index as usize).into()
}
@@ -534,6 +545,9 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> {
/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)`
/// needs `T` substituted immediately. This type primarily exists to avoid forgetting to call
/// `subst`.
+///
+/// If you don't have anything to `subst`, you may be looking for
+/// [`subst_identity`](EarlyBinder::subst_identity) or [`skip_binder`](EarlyBinder::skip_binder).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Encodable, Decodable, HashStable)]
pub struct EarlyBinder<T>(pub T);
@@ -573,6 +587,18 @@ impl<T> EarlyBinder<T> {
pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
EarlyBinder(value)
}
+
+ /// Skips the binder and returns the "bound" value.
+ /// This can be used to extract data that does not depend on generic parameters
+ /// (e.g., getting the `DefId` of the inner value or getting the number of
+ /// arguments of an `FnSig`). Otherwise, consider using
+ /// [`subst_identity`](EarlyBinder::subst_identity).
+ ///
+ /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is
+ /// the analogous operation on [`super::Binder`].
+ pub fn skip_binder(self) -> T {
+ self.0
+ }
}
impl<T> EarlyBinder<Option<T>> {
@@ -631,6 +657,13 @@ where
}
}
+impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIter<'_, 'tcx, I>
+where
+ I::IntoIter: ExactSizeIterator,
+ I::Item: TypeFoldable<'tcx>,
+{
+}
+
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
where
I::Item: Deref,
@@ -678,6 +711,14 @@ where
}
}
+impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIterCopied<'_, 'tcx, I>
+where
+ I::IntoIter: ExactSizeIterator,
+ I::Item: Deref,
+ <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
+{
+}
+
pub struct EarlyBinderIter<T> {
t: T,
}
@@ -705,6 +746,18 @@ impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder<T> {
let mut folder = SubstFolder { tcx, substs, binders_passed: 0 };
self.0.fold_with(&mut folder)
}
+
+ /// Makes the identity substitution `T0 => T0, ..., TN => TN`.
+ /// Conceptually, this converts universally bound variables into placeholders
+ /// when inside of a given item.
+ ///
+ /// For example, consider `for<T> fn foo<T>(){ .. }`:
+ /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`).
+ /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling
+ /// `subst_identity` to discharge the `EarlyBinder`.
+ pub fn subst_identity(self) -> T {
+ self.0
+ }
}
///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
new file mode 100644
index 000000000..2902c6dc5
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -0,0 +1,707 @@
+use crate::{
+ hir::place::Place as HirPlace,
+ infer::canonical::Canonical,
+ ty::{
+ self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData,
+ GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
+ },
+};
+use rustc_data_structures::{
+ fx::FxHashMap,
+ sync::Lrc,
+ unord::{UnordItems, UnordSet},
+ vec_map::VecMap,
+};
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
+use rustc_hir::{
+ def::{DefKind, Res},
+ def_id::{DefId, LocalDefId, LocalDefIdMap},
+ hir_id::OwnerId,
+ HirId, ItemLocalId, ItemLocalMap, ItemLocalSet,
+};
+use rustc_index::vec::{Idx, IndexVec};
+use rustc_macros::HashStable;
+use rustc_middle::mir::FakeReadCause;
+use rustc_session::Session;
+use rustc_span::Span;
+use std::{collections::hash_map::Entry, hash::Hash, iter};
+
+use super::RvalueScopes;
+
+#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
+pub struct TypeckResults<'tcx> {
+ /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
+ pub hir_owner: OwnerId,
+
+ /// Resolved definitions for `<T>::X` associated paths and
+ /// method calls, including those of overloaded operators.
+ type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
+
+ /// Resolved field indices for field accesses in expressions (`S { field }`, `obj.field`)
+ /// or patterns (`S { field }`). The index is often useful by itself, but to learn more
+ /// about the field you also need definition of the variant to which the field
+ /// belongs, but it may not exist if it's a tuple field (`tuple.0`).
+ field_indices: ItemLocalMap<usize>,
+
+ /// Stores the types for various nodes in the AST. Note that this table
+ /// is not guaranteed to be populated outside inference. See
+ /// typeck::check::fn_ctxt for details.
+ node_types: ItemLocalMap<Ty<'tcx>>,
+
+ /// Stores the type parameters which were substituted to obtain the type
+ /// of this node. This only applies to nodes that refer to entities
+ /// parameterized by type parameters, such as generic fns, types, or
+ /// other items.
+ node_substs: ItemLocalMap<SubstsRef<'tcx>>,
+
+ /// This will either store the canonicalized types provided by the user
+ /// or the substitutions that the user explicitly gave (if any) attached
+ /// to `id`. These will not include any inferred values. The canonical form
+ /// is used to capture things like `_` or other unspecified values.
+ ///
+ /// For example, if the user wrote `foo.collect::<Vec<_>>()`, then the
+ /// canonical substitutions would include only `for<X> { Vec<X> }`.
+ ///
+ /// See also `AscribeUserType` statement in MIR.
+ user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
+
+ /// Stores the canonicalized types provided by the user. See also
+ /// `AscribeUserType` statement in MIR.
+ pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
+
+ adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
+
+ /// Stores the actual binding mode for all instances of hir::BindingAnnotation.
+ pat_binding_modes: ItemLocalMap<BindingMode>,
+
+ /// Stores the types which were implicitly dereferenced in pattern binding modes
+ /// for later usage in THIR lowering. For example,
+ ///
+ /// ```
+ /// match &&Some(5i32) {
+ /// Some(n) => {},
+ /// _ => {},
+ /// }
+ /// ```
+ /// leads to a `vec![&&Option<i32>, &Option<i32>]`. Empty vectors are not stored.
+ ///
+ /// See:
+ /// <https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md#definitions>
+ pat_adjustments: ItemLocalMap<Vec<Ty<'tcx>>>,
+
+ /// Records the reasons that we picked the kind of each closure;
+ /// not all closures are present in the map.
+ closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
+
+ /// For each fn, records the "liberated" types of its arguments
+ /// and return type. Liberated means that all bound regions
+ /// (including late-bound regions) are replaced with free
+ /// equivalents. This table is not used in codegen (since regions
+ /// are erased there) and hence is not serialized to metadata.
+ ///
+ /// This table also contains the "revealed" values for any `impl Trait`
+ /// that appear in the signature and whose values are being inferred
+ /// by this function.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use std::fmt::Debug;
+ /// fn foo(x: &u32) -> impl Debug { *x }
+ /// ```
+ ///
+ /// The function signature here would be:
+ ///
+ /// ```ignore (illustrative)
+ /// for<'a> fn(&'a u32) -> Foo
+ /// ```
+ ///
+ /// where `Foo` is an opaque type created for this function.
+ ///
+ ///
+ /// The *liberated* form of this would be
+ ///
+ /// ```ignore (illustrative)
+ /// fn(&'a u32) -> u32
+ /// ```
+ ///
+ /// Note that `'a` is not bound (it would be an `ReFree`) and
+ /// that the `Foo` opaque type is replaced by its hidden type.
+ liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
+
+ /// For each FRU expression, record the normalized types of the fields
+ /// of the struct - this is needed because it is non-trivial to
+ /// normalize while preserving regions. This table is used only in
+ /// MIR construction and hence is not serialized to metadata.
+ fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
+
+ /// For every coercion cast we add the HIR node ID of the cast
+ /// expression to this set.
+ coercion_casts: ItemLocalSet,
+
+ /// Set of trait imports actually used in the method resolution.
+ /// This is used for warning unused imports. During type
+ /// checking, this `Lrc` should not be cloned: it must have a ref-count
+ /// of 1 so that we can insert things into the set mutably.
+ pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
+
+ /// If any errors occurred while type-checking this body,
+ /// this field will be set to `Some(ErrorGuaranteed)`.
+ pub tainted_by_errors: Option<ErrorGuaranteed>,
+
+ /// All the opaque types that have hidden types set
+ /// by this function. We also store the
+ /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
+ /// even if they are only set in dead code (which doesn't show up in MIR).
+ pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
+
+ /// Tracks the minimum captures required for a closure;
+ /// see `MinCaptureInformationMap` for more details.
+ pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
+
+ /// Tracks the fake reads required for a closure and the reason for the fake read.
+ /// When performing pattern matching for closures, there are times we don't end up
+ /// reading places that are mentioned in a closure (because of _ patterns). However,
+ /// to ensure the places are initialized, we introduce fake reads.
+ /// Consider these two examples:
+ /// ``` (discriminant matching with only wildcard arm)
+ /// let x: u8;
+ /// let c = || match x { _ => () };
+ /// ```
+ /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
+ /// want to capture it. However, we do still want an error here, because `x` should have
+ /// to be initialized at the point where c is created. Therefore, we add a "fake read"
+ /// instead.
+ /// ``` (destructured assignments)
+ /// let c = || {
+ /// let (t1, t2) = t;
+ /// }
+ /// ```
+ /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
+ /// we never capture `t`. This becomes an issue when we build MIR as we require
+ /// information on `t` in order to create place `t.0` and `t.1`. We can solve this
+ /// issue by fake reading `t`.
+ pub closure_fake_reads: FxHashMap<LocalDefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
+
+ /// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
+ /// by applying extended parameter rules.
+ /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
+ pub rvalue_scopes: RvalueScopes,
+
+ /// Stores the type, expression, span and optional scope span of all types
+ /// that are live across the yield of this generator (if a generator).
+ pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
+
+ /// We sometimes treat byte string literals (which are of type `&[u8; N]`)
+ /// as `&[u8]`, depending on the pattern in which they are used.
+ /// This hashset records all instances where we behave
+ /// like this to allow `const_to_pat` to reliably handle this situation.
+ pub treat_byte_string_as_slice: ItemLocalSet,
+
+ /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
+ /// on closure size.
+ pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
+}
+
+/// Whenever a value may be live across a generator yield, the type of that value winds up in the
+/// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
+/// captured types that can be useful for diagnostics. In particular, it stores the span that
+/// caused a given type to be recorded, along with the scope that enclosed the value (which can
+/// be used to find the await that the value is live across).
+///
+/// For example:
+///
+/// ```ignore (pseudo-Rust)
+/// async move {
+/// let x: T = expr;
+/// foo.await
+/// ...
+/// }
+/// ```
+///
+/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
+/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
+#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub struct GeneratorInteriorTypeCause<'tcx> {
+ /// Type of the captured binding.
+ pub ty: Ty<'tcx>,
+ /// Span of the binding that was captured.
+ pub span: Span,
+ /// Span of the scope of the captured binding.
+ pub scope_span: Option<Span>,
+ /// Span of `.await` or `yield` expression.
+ pub yield_span: Span,
+ /// Expr which the type evaluated from.
+ pub expr: Option<hir::HirId>,
+}
+
+// This type holds diagnostic information on generators and async functions across crate boundaries
+// and is used to provide better error messages
+#[derive(TyEncodable, TyDecodable, Clone, Debug, HashStable)]
+pub struct GeneratorDiagnosticData<'tcx> {
+ pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
+ pub hir_owner: DefId,
+ pub nodes_types: ItemLocalMap<Ty<'tcx>>,
+ pub adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
+}
+
+impl<'tcx> TypeckResults<'tcx> {
+ pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
+ TypeckResults {
+ hir_owner,
+ type_dependent_defs: Default::default(),
+ field_indices: Default::default(),
+ user_provided_types: Default::default(),
+ user_provided_sigs: Default::default(),
+ node_types: Default::default(),
+ node_substs: Default::default(),
+ adjustments: Default::default(),
+ pat_binding_modes: Default::default(),
+ pat_adjustments: Default::default(),
+ closure_kind_origins: Default::default(),
+ liberated_fn_sigs: Default::default(),
+ fru_field_types: Default::default(),
+ coercion_casts: Default::default(),
+ used_trait_imports: Lrc::new(Default::default()),
+ tainted_by_errors: None,
+ concrete_opaque_types: Default::default(),
+ closure_min_captures: Default::default(),
+ closure_fake_reads: Default::default(),
+ rvalue_scopes: Default::default(),
+ generator_interior_types: ty::Binder::dummy(Default::default()),
+ treat_byte_string_as_slice: Default::default(),
+ closure_size_eval: Default::default(),
+ }
+ }
+
+ /// 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::TypeRelative(..) | hir::QPath::LangItem(..) => self
+ .type_dependent_def(id)
+ .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
+ }
+ }
+
+ pub fn type_dependent_defs(
+ &self,
+ ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
+ }
+
+ pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
+ }
+
+ pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
+ self.type_dependent_def(id).map(|(_, def_id)| def_id)
+ }
+
+ pub fn type_dependent_defs_mut(
+ &mut self,
+ ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
+ }
+
+ pub fn field_indices(&self) -> LocalTableInContext<'_, usize> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
+ }
+
+ pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
+ }
+
+ pub fn field_index(&self, id: hir::HirId) -> usize {
+ self.field_indices().get(id).cloned().expect("no index for a field")
+ }
+
+ pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> {
+ self.field_indices().get(id).cloned()
+ }
+
+ pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
+ }
+
+ pub fn user_provided_types_mut(
+ &mut self,
+ ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
+ }
+
+ pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
+ }
+
+ pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
+ }
+
+ pub fn get_generator_diagnostic_data(&self) -> GeneratorDiagnosticData<'tcx> {
+ let generator_interior_type = self.generator_interior_types.map_bound_ref(|vec| {
+ vec.iter()
+ .map(|item| {
+ GeneratorInteriorTypeCause {
+ ty: item.ty,
+ span: item.span,
+ scope_span: item.scope_span,
+ yield_span: item.yield_span,
+ expr: None, //FIXME: Passing expression over crate boundaries is impossible at the moment
+ }
+ })
+ .collect::<Vec<_>>()
+ });
+ GeneratorDiagnosticData {
+ generator_interior_types: generator_interior_type,
+ hir_owner: self.hir_owner.to_def_id(),
+ nodes_types: self.node_types.clone(),
+ adjustments: self.adjustments.clone(),
+ }
+ }
+
+ pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
+ self.node_type_opt(id).unwrap_or_else(|| {
+ bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
+ })
+ }
+
+ pub fn node_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.node_types.get(&id.local_id).cloned()
+ }
+
+ pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<'_, SubstsRef<'tcx>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_substs }
+ }
+
+ pub fn node_substs(&self, id: hir::HirId) -> SubstsRef<'tcx> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.node_substs.get(&id.local_id).cloned().unwrap_or_else(|| InternalSubsts::empty())
+ }
+
+ pub fn node_substs_opt(&self, id: hir::HirId) -> Option<SubstsRef<'tcx>> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.node_substs.get(&id.local_id).cloned()
+ }
+
+ /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function
+ /// doesn't provide type parameter substitutions.
+ ///
+ /// [`expr_ty`]: TypeckResults::expr_ty
+ pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
+ self.node_type(pat.hir_id)
+ }
+
+ /// Returns the type of an expression as a monotype.
+ ///
+ /// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
+ /// some cases, we insert `Adjustment` annotations such as auto-deref or
+ /// auto-ref. The type returned by this function does not consider such
+ /// adjustments. See `expr_ty_adjusted()` instead.
+ ///
+ /// NB (2): This type doesn't provide type parameter substitutions; e.g., if you
+ /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize`
+ /// instead of `fn(ty) -> T with T = isize`.
+ pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
+ self.node_type(expr.hir_id)
+ }
+
+ pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
+ self.node_type_opt(expr.hir_id)
+ }
+
+ pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
+ }
+
+ pub fn adjustments_mut(
+ &mut self,
+ ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
+ }
+
+ pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
+ validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
+ self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
+ }
+
+ /// Returns the type of `expr`, considering any `Adjustment`
+ /// entry recorded for that expression.
+ pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
+ self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
+ }
+
+ pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
+ self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
+ }
+
+ pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
+ // Only paths and method calls/overloaded operators have
+ // entries in type_dependent_defs, ignore the former here.
+ if let hir::ExprKind::Path(_) = expr.kind {
+ return false;
+ }
+
+ matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
+ }
+
+ 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");
+ None
+ })
+ }
+
+ pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
+ }
+
+ pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
+ }
+
+ pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
+ }
+
+ pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
+ }
+
+ /// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
+ /// by the closure.
+ pub fn closure_min_captures_flattened(
+ &self,
+ closure_def_id: LocalDefId,
+ ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
+ self.closure_min_captures
+ .get(&closure_def_id)
+ .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
+ .into_iter()
+ .flatten()
+ }
+
+ pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
+ }
+
+ pub fn closure_kind_origins_mut(
+ &mut self,
+ ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
+ }
+
+ pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
+ }
+
+ pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
+ }
+
+ pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
+ }
+
+ pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
+ }
+
+ pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
+ validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
+ self.coercion_casts.contains(&hir_id.local_id)
+ }
+
+ pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
+ self.coercion_casts.insert(id);
+ }
+
+ pub fn coercion_casts(&self) -> &ItemLocalSet {
+ &self.coercion_casts
+ }
+}
+
+/// Validate that the given HirId (respectively its `local_id` part) can be
+/// safely used as a key in the maps of a TypeckResults. For that to be
+/// the case, the HirId must have the same `owner` as all the other IDs in
+/// this table (signified by `hir_owner`). Otherwise the HirId
+/// would be in a different frame of reference and using its `local_id`
+/// would result in lookup errors, or worse, in silently wrong data being
+/// stored/returned.
+#[inline]
+fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
+ if hir_id.owner != hir_owner {
+ invalid_hir_id_for_typeck_results(hir_owner, hir_id);
+ }
+}
+
+#[cold]
+#[inline(never)]
+fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
+ ty::tls::with(|tcx| {
+ bug!(
+ "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
+ tcx.hir().node_to_string(hir_id),
+ hir_id.owner,
+ hir_owner
+ )
+ });
+}
+
+pub struct LocalTableInContext<'a, V> {
+ hir_owner: OwnerId,
+ data: &'a ItemLocalMap<V>,
+}
+
+impl<'a, V> LocalTableInContext<'a, V> {
+ pub fn contains_key(&self, id: hir::HirId) -> bool {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.contains_key(&id.local_id)
+ }
+
+ pub fn get(&self, id: hir::HirId) -> Option<&V> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.get(&id.local_id)
+ }
+
+ pub fn items(
+ &'a self,
+ ) -> UnordItems<(hir::ItemLocalId, &'a V), impl Iterator<Item = (hir::ItemLocalId, &'a V)>>
+ {
+ self.data.items().map(|(id, value)| (*id, value))
+ }
+
+ pub fn items_in_stable_order(&self) -> Vec<(ItemLocalId, &'a V)> {
+ self.data.to_sorted_stable_ord()
+ }
+}
+
+impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
+ type Output = V;
+
+ fn index(&self, key: hir::HirId) -> &V {
+ self.get(key).expect("LocalTableInContext: key not found")
+ }
+}
+
+pub struct LocalTableInContextMut<'a, V> {
+ hir_owner: OwnerId,
+ data: &'a mut ItemLocalMap<V>,
+}
+
+impl<'a, V> LocalTableInContextMut<'a, V> {
+ pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.get_mut(&id.local_id)
+ }
+
+ pub fn entry(&mut self, id: hir::HirId) -> Entry<'_, hir::ItemLocalId, V> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.entry(id.local_id)
+ }
+
+ pub fn insert(&mut self, id: hir::HirId, val: V) -> Option<V> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.insert(id.local_id, val)
+ }
+
+ pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ self.data.remove(&id.local_id)
+ }
+
+ pub fn extend(
+ &mut self,
+ items: UnordItems<(hir::HirId, V), impl Iterator<Item = (hir::HirId, V)>>,
+ ) {
+ self.data.extend(items.map(|(id, value)| {
+ validate_hir_id_for_typeck_results(self.hir_owner, id);
+ (id.local_id, value)
+ }))
+ }
+}
+
+rustc_index::newtype_index! {
+ #[derive(HashStable)]
+ #[debug_format = "UserType({})"]
+ pub struct UserTypeAnnotationIndex {
+ const START_INDEX = 0;
+ }
+}
+
+/// Mapping of type annotation indices to canonical user type annotations.
+pub type CanonicalUserTypeAnnotations<'tcx> =
+ IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
+
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct CanonicalUserTypeAnnotation<'tcx> {
+ pub user_ty: Box<CanonicalUserType<'tcx>>,
+ pub span: Span,
+ pub inferred_ty: Ty<'tcx>,
+}
+
+/// Canonical user type annotation.
+pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
+
+impl<'tcx> CanonicalUserType<'tcx> {
+ /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
+ /// i.e., each thing is mapped to a canonical variable with the same index.
+ pub fn is_identity(&self) -> bool {
+ match self.value {
+ UserType::Ty(_) => false,
+ UserType::TypeOf(_, user_substs) => {
+ if user_substs.user_self_ty.is_some() {
+ return false;
+ }
+
+ iter::zip(user_substs.substs, BoundVar::new(0)..).all(|(kind, cvar)| {
+ match kind.unpack() {
+ GenericArgKind::Type(ty) => match ty.kind() {
+ ty::Bound(debruijn, b) => {
+ // We only allow a `ty::INNERMOST` index in substitutions.
+ assert_eq!(*debruijn, ty::INNERMOST);
+ cvar == b.var
+ }
+ _ => false,
+ },
+
+ GenericArgKind::Lifetime(r) => match *r {
+ ty::ReLateBound(debruijn, br) => {
+ // We only allow a `ty::INNERMOST` index in substitutions.
+ assert_eq!(debruijn, ty::INNERMOST);
+ cvar == br.var
+ }
+ _ => false,
+ },
+
+ GenericArgKind::Const(ct) => match ct.kind() {
+ ty::ConstKind::Bound(debruijn, b) => {
+ // We only allow a `ty::INNERMOST` index in substitutions.
+ assert_eq!(debruijn, ty::INNERMOST);
+ cvar == b
+ }
+ _ => false,
+ },
+ }
+ })
+ }
+ }
+ }
+}
+
+/// A user-given type annotation attached to a constant. These arise
+/// from constants that are named via paths, like `Foo::<A>::new` and
+/// so forth.
+#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
+#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub enum UserType<'tcx> {
+ Ty(Ty<'tcx>),
+
+ /// The canonical type is the result of `type_of(def_id)` with the
+ /// given substitutions applied.
+ TypeOf(DefId, UserSubsts<'tcx>),
+}
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 47c1ce807..d0d1dcc58 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1,7 +1,9 @@
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use crate::mir;
use crate::ty::layout::IntegerExt;
+use crate::ty::query::TyCtxtAt;
use crate::ty::{
self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitable,
@@ -15,6 +17,7 @@ use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_index::bit_set::GrowableBitSet;
+use rustc_index::vec::{Idx, IndexVec};
use rustc_macros::HashStable;
use rustc_span::{sym, DUMMY_SP};
use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout};
@@ -257,7 +260,7 @@ impl<'tcx> TyCtxt<'tcx> {
ty::Tuple(_) => break,
- ty::Projection(_) | ty::Opaque(..) => {
+ ty::Alias(..) => {
let normalized = normalize(ty);
if ty == normalized {
return ty;
@@ -330,8 +333,7 @@ impl<'tcx> TyCtxt<'tcx> {
break;
}
}
- (ty::Projection(_) | ty::Opaque(..), _)
- | (_, ty::Projection(_) | ty::Opaque(..)) => {
+ (ty::Alias(..), _) | (_, ty::Alias(..)) => {
// If either side is a projection, attempt to
// progress via normalization. (Should be safe to
// apply to both sides as normalization is
@@ -639,24 +641,17 @@ impl<'tcx> TyCtxt<'tcx> {
ty::EarlyBinder(self.type_of(def_id))
}
- pub fn bound_trait_impl_trait_tys(
+ pub fn bound_return_position_impl_trait_in_trait_tys(
self,
def_id: DefId,
) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> {
- ty::EarlyBinder(self.collect_trait_impl_trait_tys(def_id))
+ ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id))
}
pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
ty::EarlyBinder(self.fn_sig(def_id))
}
- pub fn bound_impl_trait_ref(
- self,
- def_id: DefId,
- ) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
- self.impl_trait_ref(def_id).map(|i| ty::EarlyBinder(i))
- }
-
pub fn bound_explicit_item_bounds(
self,
def_id: DefId,
@@ -664,33 +659,88 @@ impl<'tcx> TyCtxt<'tcx> {
ty::EarlyBinder(self.explicit_item_bounds(def_id))
}
- pub fn bound_item_bounds(
- self,
- def_id: DefId,
- ) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
- ty::EarlyBinder(self.item_bounds(def_id))
- }
-
- pub fn bound_const_param_default(self, def_id: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> {
- ty::EarlyBinder(self.const_param_default(def_id))
+ pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> {
+ ty::EarlyBinder(self.impl_subject(def_id))
}
- pub fn bound_predicates_of(
+ /// Returns names of captured upvars for closures and generators.
+ ///
+ /// Here are some examples:
+ /// - `name__field1__field2` when the upvar is captured by value.
+ /// - `_ref__name__field` when the upvar is captured by reference.
+ ///
+ /// For generators this only contains upvars that are shared by all states.
+ pub fn closure_saved_names_of_captured_variables(
self,
def_id: DefId,
- ) -> ty::EarlyBinder<ty::generics::GenericPredicates<'tcx>> {
- ty::EarlyBinder(self.predicates_of(def_id))
+ ) -> SmallVec<[String; 16]> {
+ let body = self.optimized_mir(def_id);
+
+ body.var_debug_info
+ .iter()
+ .filter_map(|var| {
+ let is_ref = match var.value {
+ mir::VarDebugInfoContents::Place(place)
+ if place.local == mir::Local::new(1) =>
+ {
+ // The projection is either `[.., Field, Deref]` or `[.., Field]`. It
+ // implies whether the variable is captured by value or by reference.
+ matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
+ }
+ _ => return None,
+ };
+ let prefix = if is_ref { "_ref__" } else { "" };
+ Some(prefix.to_owned() + var.name.as_str())
+ })
+ .collect()
}
- pub fn bound_explicit_predicates_of(
+ // FIXME(eddyb) maybe precompute this? Right now it's computed once
+ // per generator monomorphization, but it doesn't depend on substs.
+ pub fn generator_layout_and_saved_local_names(
self,
def_id: DefId,
- ) -> ty::EarlyBinder<ty::generics::GenericPredicates<'tcx>> {
- ty::EarlyBinder(self.explicit_predicates_of(def_id))
+ ) -> (
+ &'tcx ty::GeneratorLayout<'tcx>,
+ IndexVec<mir::GeneratorSavedLocal, Option<rustc_span::Symbol>>,
+ ) {
+ let tcx = self;
+ let body = tcx.optimized_mir(def_id);
+ let generator_layout = body.generator_layout().unwrap();
+ let mut generator_saved_local_names =
+ IndexVec::from_elem(None, &generator_layout.field_tys);
+
+ let state_arg = mir::Local::new(1);
+ for var in &body.var_debug_info {
+ let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
+ if place.local != state_arg {
+ continue;
+ }
+ match place.projection[..] {
+ [
+ // Deref of the `Pin<&mut Self>` state argument.
+ mir::ProjectionElem::Field(..),
+ mir::ProjectionElem::Deref,
+ // Field of a variant of the state.
+ mir::ProjectionElem::Downcast(_, variant),
+ mir::ProjectionElem::Field(field, _),
+ ] => {
+ let name = &mut generator_saved_local_names
+ [generator_layout.variant_fields[variant][field]];
+ if name.is_none() {
+ name.replace(var.name);
+ }
+ }
+ _ => {}
+ }
+ }
+ (generator_layout, generator_saved_local_names)
}
+}
- pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> {
- ty::EarlyBinder(self.impl_subject(def_id))
+impl<'tcx> TyCtxtAt<'tcx> {
+ pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
+ ty::EarlyBinder(self.type_of(def_id))
}
}
@@ -750,7 +800,7 @@ impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- if let ty::Opaque(def_id, substs) = *t.kind() {
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() {
self.expand_opaque_ty(def_id, substs).unwrap_or(t)
} else if t.has_opaque_types() {
t.super_fold_with(self)
@@ -862,10 +912,9 @@ impl<'tcx> Ty<'tcx> {
| ty::Generator(..)
| ty::GeneratorWitness(_)
| ty::Infer(_)
- | ty::Opaque(..)
+ | ty::Alias(..)
| ty::Param(_)
- | ty::Placeholder(_)
- | ty::Projection(_) => false,
+ | ty::Placeholder(_) => false,
}
}
@@ -902,10 +951,9 @@ impl<'tcx> Ty<'tcx> {
| ty::Generator(..)
| ty::GeneratorWitness(_)
| ty::Infer(_)
- | ty::Opaque(..)
+ | ty::Alias(..)
| ty::Param(_)
- | ty::Placeholder(_)
- | ty::Projection(_) => false,
+ | ty::Placeholder(_) => false,
}
}
@@ -1025,12 +1073,9 @@ impl<'tcx> Ty<'tcx> {
//
// FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be
// called for known, fully-monomorphized types.
- ty::Projection(_)
- | ty::Opaque(..)
- | ty::Param(_)
- | ty::Bound(..)
- | ty::Placeholder(_)
- | ty::Infer(_) => false,
+ ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => {
+ false
+ }
ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
}
@@ -1161,18 +1206,17 @@ pub fn needs_drop_components<'tcx>(
// These require checking for `Copy` bounds or `Adt` destructors.
ty::Adt(..)
- | ty::Projection(..)
+ | ty::Alias(..)
| ty::Param(_)
| ty::Bound(..)
| ty::Placeholder(..)
- | ty::Opaque(..)
| ty::Infer(_)
| ty::Closure(..)
| ty::Generator(..) => Ok(smallvec![ty]),
}
}
-pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
+pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
match *ty.kind() {
ty::Bool
| ty::Char
@@ -1189,13 +1233,12 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
| ty::Never
| ty::Foreign(_) => true,
- ty::Opaque(..)
+ ty::Alias(..)
| ty::Dynamic(..)
| ty::Error(_)
| ty::Bound(..)
| ty::Param(_)
| ty::Placeholder(_)
- | ty::Projection(_)
| ty::Infer(_) => false,
// Not trivial because they have components, and instead of looking inside,
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 4cdfd9e59..bee3cc4d7 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -88,9 +88,11 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
self.has_vars_bound_at_or_above(ty::INNERMOST)
}
- #[instrument(level = "trace", ret)]
fn has_type_flags(&self, flags: TypeFlags) -> bool {
- self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
+ let res =
+ self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags);
+ trace!(?self, ?flags, ?res, "has_type_flags");
+ res
}
fn has_projections(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_PROJECTION)
@@ -163,6 +165,14 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
fn has_late_bound_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_LATE_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)
+ }
+ /// True if there are any late-bound variables
+ fn has_late_bound_vars(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_LATE_BOUND)
+ }
/// Indicates whether this value still has parameters/placeholders/inference variables
/// which could be replaced later, in a way that would change the results of `impl`
@@ -284,13 +294,13 @@ 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 => {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
_ => {
if (self.callback)(r) {
- ControlFlow::BREAK
+ ControlFlow::Break(())
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
}
@@ -301,7 +311,7 @@ impl<'tcx> TyCtxt<'tcx> {
if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
ty.super_visit_with(self)
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
}
@@ -384,7 +394,7 @@ impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
if t.outer_exclusive_binder() < self.binder_index
|| !self.visited.insert((self.binder_index, t))
{
- return ControlFlow::BREAK;
+ return ControlFlow::Break(());
}
match *t.kind() {
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
@@ -502,7 +512,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
if t.outer_exclusive_binder() > self.outer_index {
ControlFlow::Break(FoundEscapingVars)
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
@@ -514,7 +524,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
if r.bound_at_or_above_binder(self.outer_index) {
ControlFlow::Break(FoundEscapingVars)
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
@@ -537,7 +547,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
if predicate.outer_exclusive_binder() > self.outer_index {
ControlFlow::Break(FoundEscapingVars)
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
}
@@ -560,54 +570,42 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags;
#[inline]
- #[instrument(skip(self), level = "trace", ret)]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = t.flags();
- trace!(t.flags=?t.flags());
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
#[inline]
- #[instrument(skip(self), level = "trace", ret)]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = r.type_flags();
- trace!(r.flags=?flags);
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
#[inline]
- #[instrument(level = "trace", ret)]
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = FlagComputation::for_const(c);
trace!(r.flags=?flags);
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
#[inline]
- #[instrument(level = "trace", ret)]
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
- debug!(
- "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
- predicate,
- predicate.flags(),
- self.flags
- );
if predicate.flags().intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
}
@@ -654,8 +652,8 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
// ignore the inputs to a projection, as they may not appear
// in the normalized form
if self.just_constrained {
- if let ty::Projection(..) | ty::Opaque(..) = t.kind() {
- return ControlFlow::CONTINUE;
+ if let ty::Alias(..) = t.kind() {
+ return ControlFlow::Continue(());
}
}
@@ -668,7 +666,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
// in the normalized form
if self.just_constrained {
if let ty::ConstKind::Unevaluated(..) = c.kind() {
- return ControlFlow::CONTINUE;
+ return ControlFlow::Continue(());
}
}
@@ -681,7 +679,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
self.regions.insert(br.kind);
}
}
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
@@ -728,6 +726,6 @@ impl<'tcx> TypeVisitor<'tcx> for MaxUniverse {
);
}
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
}
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index 6eae94511..f77bd9f0c 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -1,4 +1,3 @@
-use std::convert::TryFrom;
use std::fmt;
use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar};
@@ -89,8 +88,8 @@ pub(super) fn vtable_allocation_provider<'tcx>(
let fn_ptr = Pointer::from(fn_alloc_id);
Scalar::from_pointer(fn_ptr, &tcx)
}
- VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size).into(),
- VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size).into(),
+ VtblEntry::MetadataSize => Scalar::from_uint(size, ptr_size),
+ VtblEntry::MetadataAlign => Scalar::from_uint(align, ptr_size),
VtblEntry::Vacant => continue,
VtblEntry::Method(instance) => {
// Prepare the fn ptr we write into the vtable.
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 4fab5abe9..708a5e4d0 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -4,7 +4,7 @@
use crate::ty::subst::{GenericArg, GenericArgKind};
use crate::ty::{self, Ty};
use rustc_data_structures::sso::SsoHashSet;
-use smallvec::{self, SmallVec};
+use smallvec::SmallVec;
// The TypeWalker's stack is hot enough that it's worth going to some effort to
// avoid heap allocations.
@@ -165,7 +165,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
stack.push(ty.into());
stack.push(lt.into());
}
- ty::Projection(data) => {
+ ty::Alias(_, data) => {
stack.extend(data.substs.iter().rev());
}
ty::Dynamic(obj, lt, _) => {
@@ -188,7 +188,6 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
}));
}
ty::Adt(_, substs)
- | ty::Opaque(_, substs)
| ty::Closure(_, substs)
| ty::Generator(_, substs, _)
| ty::FnDef(_, substs) => {
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index fd7045d6a..b73ae5939 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -35,8 +35,7 @@ fn opt_span_bug_fmt<S: Into<MultiSpan>>(
(Some(tcx), None) => tcx.sess.diagnostic().bug(&msg),
(None, _) => panic_any(msg),
}
- });
- unreachable!();
+ })
}
/// A query to trigger a `delay_span_bug`. Clearly, if one has a `tcx` one can already trigger a
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 70b98e59a..34e8a5597 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -1,3 +1,4 @@
+use crate::dep_graph::DepKind;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
use rustc_hir as hir;
@@ -11,16 +12,16 @@ use rustc_span::Span;
use std::fmt::Write;
-impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Ty<'_> {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo<DepKind>]) -> Self {
// SAFETY: This is never called when `Self` is not `Ty<'tcx>`.
// FIXME: Represent the above fact in the trait system somehow.
unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error()) }
}
}
-impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::SymbolName<'_> {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo<DepKind>]) -> Self {
// SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`.
// FIXME: Represent the above fact in the trait system somehow.
unsafe {
@@ -31,12 +32,12 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> {
}
}
-impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::Binder<'_, ty::FnSig<'_>> {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo<DepKind>]) -> Self {
let err = tcx.ty_error();
let arity = if let Some(frame) = stack.get(0)
- && frame.query.name == "fn_sig"
+ && frame.query.dep_kind == DepKind::fn_sig
&& let Some(def_id) = frame.query.def_id
&& let Some(node) = tcx.hir().get_if_local(def_id)
&& let Some(sig) = node.fn_sig()
@@ -61,12 +62,12 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> {
}
}
-impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
- fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo]) -> Self {
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Representability {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self {
let mut item_and_field_ids = Vec::new();
let mut representable_ids = FxHashSet::default();
for info in cycle {
- if info.query.name == "representability"
+ if info.query.dep_kind == DepKind::representability
&& let Some(field_id) = info.query.def_id
&& let Some(field_id) = field_id.as_local()
&& let Some(DefKind::Field) = info.query.def_kind
@@ -80,7 +81,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
}
}
for info in cycle {
- if info.query.name == "representability_adt_ty"
+ if info.query.dep_kind == DepKind::representability_adt_ty
&& let Some(def_id) = info.query.ty_adt_id
&& let Some(def_id) = def_id.as_local()
&& !item_and_field_ids.iter().any(|&(id, _)| id == def_id)
@@ -93,6 +94,18 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
}
}
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<Ty<'_>> {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self {
+ ty::EarlyBinder(Ty::from_cycle_error(tcx, cycle))
+ }
+}
+
+impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>> {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self {
+ ty::EarlyBinder(ty::Binder::from_cycle_error(tcx, cycle))
+ }
+}
+
// item_and_field_ids should form a cycle where each field contains the
// type in the next element in the list
pub fn recursive_type_error(