summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:43 +0000
commit3e3e70d529d8c7d7c4d7bc4fefc9f109393b9245 (patch)
treedaf049b282ab10e8c3d03e409b3cd84ff3f7690c /compiler/rustc_middle
parentAdding debian version 1.68.2+dfsg1-1. (diff)
downloadrustc-3e3e70d529d8c7d7c4d7bc4fefc9f109393b9245.tar.xz
rustc-3e3e70d529d8c7d7c4d7bc4fefc9f109393b9245.zip
Merging upstream version 1.69.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_middle')
-rw-r--r--compiler/rustc_middle/Cargo.toml2
-rw-r--r--compiler/rustc_middle/locales/en-US.ftl36
-rw-r--r--compiler/rustc_middle/src/arena.rs9
-rw-r--r--compiler/rustc_middle/src/dep_graph/mod.rs6
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs102
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs23
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs162
-rw-r--r--compiler/rustc_middle/src/infer/mod.rs3
-rw-r--r--compiler/rustc_middle/src/lib.rs10
-rw-r--r--compiler/rustc_middle/src/macros.rs154
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs3
-rw-r--r--compiler/rustc_middle/src/middle/mod.rs2
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs25
-rw-r--r--compiler/rustc_middle/src/middle/resolve_bound_vars.rs (renamed from compiler/rustc_middle/src/middle/resolve_lifetime.rs)16
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs4
-rw-r--r--compiler/rustc_middle/src/mir/basic_blocks.rs99
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs5
-rw-r--r--compiler/rustc_middle/src/mir/graph_cyclic_cache.rs63
-rw-r--r--compiler/rustc_middle/src/mir/graphviz.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs82
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs9
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs17
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs22
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs18
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs100
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs9
-rw-r--r--compiler/rustc_middle/src/mir/predecessors.rs78
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs24
-rw-r--r--compiler/rustc_middle/src/mir/query.rs73
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs5
-rw-r--r--compiler/rustc_middle/src/mir/switch_sources.rs78
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs22
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs18
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs50
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs29
-rw-r--r--compiler/rustc_middle/src/mir/type_visitable.rs9
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs11
-rw-r--r--compiler/rustc_middle/src/query/keys.rs28
-rw-r--r--compiler/rustc_middle/src/query/mod.rs259
-rw-r--r--compiler/rustc_middle/src/thir.rs32
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs48
-rw-r--r--compiler/rustc_middle/src/traits/query.rs4
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs66
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs12
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs4
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs8
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs5
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs16
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs60
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs65
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs55
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs16
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs934
-rw-r--r--compiler/rustc_middle/src/ty/context/tls.rs186
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs124
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs11
-rw-r--r--compiler/rustc_middle/src/ty/error.rs864
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs12
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs30
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs281
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs8
-rw-r--r--compiler/rustc_middle/src/ty/impls_ty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs4
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs24
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs119
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs183
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs31
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs112
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs5
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs3
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs147
-rw-r--r--compiler/rustc_middle/src/ty/query.rs182
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs102
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs446
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs128
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs100
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs35
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs14
-rw-r--r--compiler/rustc_middle/src/ty/util.rs193
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs135
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs2
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs1
-rw-r--r--compiler/rustc_middle/src/values.rs9
87 files changed, 3172 insertions, 3327 deletions
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 543bd56a2..a2b78cc29 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -34,7 +34,7 @@ rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.9"
+thin-vec = "0.2.12"
tracing = "0.1"
[features]
diff --git a/compiler/rustc_middle/locales/en-US.ftl b/compiler/rustc_middle/locales/en-US.ftl
new file mode 100644
index 000000000..4f4e5c6a2
--- /dev/null
+++ b/compiler/rustc_middle/locales/en-US.ftl
@@ -0,0 +1,36 @@
+middle_drop_check_overflow =
+ overflow while adding drop-check rules for {$ty}
+ .note = overflowed on {$overflow_ty}
+
+middle_opaque_hidden_type_mismatch =
+ concrete type differs from previous defining opaque type use
+ .label = expected `{$self_ty}`, got `{$other_ty}`
+
+middle_conflict_types =
+ this expression supplies two conflicting concrete types for the same opaque type
+
+middle_previous_use_here =
+ previous use here
+
+middle_limit_invalid =
+ `limit` must be a non-negative integer
+ .label = {$error_str}
+
+middle_const_eval_non_int =
+ constant evaluation of enum discriminant resulted in non-integer
+
+middle_unknown_layout =
+ the type `{$ty}` has an unknown layout
+
+middle_values_too_big =
+ values of the type `{$ty}` are too big for the current architecture
+
+middle_cannot_be_normalized =
+ unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
+
+middle_strict_coherence_needs_negative_coherence =
+ to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
+ .label = due to this attribute
+
+middle_const_not_used_in_type_alias =
+ const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index f816d6145..62e44b629 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -8,7 +8,7 @@
macro_rules! arena_types {
($macro:path) => (
$macro!([
- [] layout: rustc_target::abi::LayoutS<rustc_target::abi::VariantIdx>,
+ [] layout: rustc_target::abi::LayoutS,
[] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
// AdtDef are interned and compared by address
[decode] adt_def: rustc_middle::ty::AdtDefData,
@@ -35,6 +35,8 @@ macro_rules! arena_types {
rustc_data_structures::sync::Lrc<rustc_ast::Crate>,
)>,
[] output_filenames: std::sync::Arc<rustc_session::config::OutputFilenames>,
+ [] metadata_loader: rustc_data_structures::steal::Steal<Box<rustc_session::cstore::MetadataLoaderDyn>>,
+ [] crate_for_resolver: rustc_data_structures::steal::Steal<rustc_ast::ast::Crate>,
[] resolutions: rustc_middle::ty::ResolverGlobalCtxt,
[decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
[decode] code_region: rustc_middle::mir::coverage::CodeRegion,
@@ -105,13 +107,16 @@ macro_rules! arena_types {
// (during lowering) and the `librustc_middle` arena (for decoding MIR)
[decode] asm_template: rustc_ast::InlineAsmTemplatePiece,
[decode] used_trait_imports: rustc_data_structures::unord::UnordSet<rustc_hir::def_id::LocalDefId>,
- [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet<rustc_hir::def_id::LocalDefId>,
+ [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet<rustc_hir::ItemLocalId>,
[decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>,
[] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>,
[decode] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap<rustc_hir::def_id::DefId, rustc_middle::ty::Ty<'tcx>>,
[] bit_set_u32: rustc_index::bit_set::BitSet<u32>,
+ [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
+ [decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
+ [] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>),
]);
)
}
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index 2e62bebc8..84510fe21 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -55,7 +55,7 @@ impl rustc_query_system::dep_graph::DepKind for DepKind {
ty::tls::with_context(|icx| {
let icx = ty::tls::ImplicitCtxt { task_deps, ..icx.clone() };
- ty::tls::enter_context(&icx, |_| op())
+ ty::tls::enter_context(&icx, op)
})
}
@@ -74,8 +74,8 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
type DepKind = DepKind;
#[inline]
- fn with_stable_hashing_context<R>(&self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R {
- TyCtxt::with_stable_hashing_context(*self, f)
+ fn with_stable_hashing_context<R>(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R {
+ TyCtxt::with_stable_hashing_context(self, f)
}
#[inline]
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 9e63c2bd2..4b5bacac8 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -18,24 +18,30 @@ use rustc_span::Span;
use rustc_target::spec::abi::Abi;
#[inline]
-pub fn associated_body(node: Node<'_>) -> Option<BodyId> {
+pub fn associated_body(node: Node<'_>) -> Option<(LocalDefId, BodyId)> {
match node {
Node::Item(Item {
+ owner_id,
kind: ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body),
..
})
| Node::TraitItem(TraitItem {
+ owner_id,
kind:
TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)),
..
})
| Node::ImplItem(ImplItem {
+ owner_id,
kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body),
..
- })
- | Node::Expr(Expr { kind: ExprKind::Closure(Closure { body, .. }), .. }) => Some(*body),
+ }) => Some((owner_id.def_id, *body)),
+
+ Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => {
+ Some((*def_id, *body))
+ }
- Node::AnonConst(constant) => Some(constant.body),
+ Node::AnonConst(constant) => Some((constant.def_id, constant.body)),
_ => None,
}
@@ -43,7 +49,7 @@ pub fn associated_body(node: Node<'_>) -> Option<BodyId> {
fn is_body_owner(node: Node<'_>, hir_id: HirId) -> bool {
match associated_body(node) {
- Some(b) => b.hir_id == hir_id,
+ Some((_, b)) => b.hir_id == hir_id,
None => false,
}
}
@@ -154,10 +160,6 @@ impl<'hir> Map<'hir> {
self.tcx.definitions_untracked().def_key(def_id)
}
- pub fn def_path_from_hir_id(self, id: HirId) -> Option<DefPath> {
- self.opt_local_def_id(id).map(|def_id| self.def_path(def_id))
- }
-
pub fn def_path(self, def_id: LocalDefId) -> DefPath {
// Accessing the DefPath is ok, since it is part of DefPathHash.
self.tcx.definitions_untracked().def_path(def_id)
@@ -170,32 +172,6 @@ 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!(
- "local_def_id: no entry for `{:?}`, which has a map of `{:?}`",
- hir_id,
- self.find(hir_id)
- )
- })
- }
-
- #[inline]
- pub fn opt_local_def_id(self, hir_id: HirId) -> Option<LocalDefId> {
- if hir_id.local_id == ItemLocalId::new(0) {
- Some(hir_id.owner.def_id)
- } else {
- self.tcx
- .hir_owner_nodes(hir_id.owner)
- .as_owner()?
- .local_id_to_def_id
- .get(&hir_id.local_id)
- .copied()
- }
- }
-
- #[inline]
pub fn local_def_id_to_hir_id(self, def_id: LocalDefId) -> HirId {
self.tcx.local_def_id_to_hir_id(def_id)
}
@@ -227,7 +203,7 @@ impl<'hir> Map<'hir> {
ItemKind::Use(..) => DefKind::Use,
ItemKind::ForeignMod { .. } => DefKind::ForeignMod,
ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
- ItemKind::Impl { .. } => DefKind::Impl,
+ ItemKind::Impl(impl_) => DefKind::Impl { of_trait: impl_.of_trait.is_some() },
},
Node::ForeignItem(item) => match item.kind {
ForeignItemKind::Fn(..) => DefKind::Fn,
@@ -314,7 +290,7 @@ impl<'hir> Map<'hir> {
#[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)))
+ .unwrap_or_else(|| bug!("No parent for node {}", self.node_to_string(hir_id)))
}
pub fn get_parent(self, hir_id: HirId) -> Node<'hir> {
@@ -410,8 +386,8 @@ 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) {
- return self.body_owner_def_id(body);
+ if let Some((def_id, _)) = associated_body(node) {
+ return def_id;
}
}
@@ -427,14 +403,17 @@ impl<'hir> Map<'hir> {
parent
}
- pub fn body_owner_def_id(self, id: BodyId) -> LocalDefId {
- self.local_def_id(self.body_owner(id))
+ pub fn body_owner_def_id(self, BodyId { hir_id }: BodyId) -> LocalDefId {
+ let parent = self.parent_id(hir_id);
+ associated_body(self.get(parent)).unwrap().0
}
/// 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.find_by_def_id(id).and_then(associated_body)
+ let node = self.find_by_def_id(id)?;
+ let (_, body_id) = associated_body(node)?;
+ Some(body_id)
}
/// Given a body owner's id, returns the `BodyId` associated with it.
@@ -870,6 +849,13 @@ impl<'hir> Map<'hir> {
}
}
+ pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> {
+ match self.tcx.hir_owner(OwnerId { def_id }) {
+ Some(Owner { node, .. }) => node.fn_decl().map(|fn_decl| &fn_decl.output),
+ _ => None,
+ }
+ }
+
pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> {
match self.find(id) {
Some(Node::Variant(variant)) => variant,
@@ -917,6 +903,11 @@ impl<'hir> Map<'hir> {
}
#[inline]
+ pub fn ident(self, id: HirId) -> Ident {
+ self.opt_ident(id).unwrap()
+ }
+
+ #[inline]
pub fn opt_name(self, id: HirId) -> Option<Symbol> {
self.opt_ident(id).map(|ident| ident.name)
}
@@ -1083,7 +1074,7 @@ impl<'hir> Map<'hir> {
}
pub fn span_if_local(self, id: DefId) -> Option<Span> {
- if id.is_local() { Some(self.tcx.def_span(id)) } else { None }
+ id.is_local().then(|| self.tcx.def_span(id))
}
pub fn res_span(self, res: Res) -> Option<Span> {
@@ -1212,12 +1203,10 @@ fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
}
fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
- let id_str = format!(" (hir_id={})", id);
-
let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id.to_def_id());
let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
- let node_str = |prefix| format!("{} {}{}", prefix, span_str(), id_str);
+ let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
match map.find(id) {
Some(Node::Item(item)) => {
@@ -1246,10 +1235,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
ItemKind::TraitAlias(..) => "trait alias",
ItemKind::Impl { .. } => "impl",
};
- format!("{} {}{}", item_str, path_str(item.owner_id.def_id), id_str)
+ format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
}
Some(Node::ForeignItem(item)) => {
- format!("foreign item {}{}", path_str(item.owner_id.def_id), id_str)
+ format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
}
Some(Node::ImplItem(ii)) => {
let kind = match ii.kind {
@@ -1257,7 +1246,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
ImplItemKind::Fn(..) => "method",
ImplItemKind::Type(_) => "assoc type",
};
- format!("{} {} in {}{}", kind, ii.ident, path_str(ii.owner_id.def_id), id_str)
+ format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
}
Some(Node::TraitItem(ti)) => {
let kind = match ti.kind {
@@ -1266,13 +1255,13 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
TraitItemKind::Type(..) => "assoc type",
};
- format!("{} {} in {}{}", kind, ti.ident, path_str(ti.owner_id.def_id), id_str)
+ format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
}
Some(Node::Variant(ref variant)) => {
- format!("variant {} in {}{}", variant.ident, path_str(variant.def_id), id_str)
+ format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
}
Some(Node::Field(ref field)) => {
- format!("field {} in {}{}", field.ident, path_str(field.def_id), id_str)
+ format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
}
Some(Node::AnonConst(_)) => node_str("const"),
Some(Node::Expr(_)) => node_str("expr"),
@@ -1290,16 +1279,15 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
Some(Node::Infer(_)) => node_str("infer"),
Some(Node::Local(_)) => node_str("local"),
Some(Node::Ctor(ctor)) => format!(
- "ctor {}{}",
+ "{id} (ctor {})",
ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
- id_str
),
Some(Node::Lifetime(_)) => node_str("lifetime"),
Some(Node::GenericParam(ref param)) => {
- format!("generic_param {}{}", path_str(param.def_id), id_str)
+ format!("{id} (generic_param {})", path_str(param.def_id))
}
- Some(Node::Crate(..)) => String::from("root_crate"),
- None => format!("unknown node{}", id_str),
+ Some(Node::Crate(..)) => String::from("(root_crate)"),
+ None => format!("{id} (unknown node)"),
}
}
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index dedc65f4c..c9da711e5 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -64,13 +64,17 @@ impl ModuleItems {
self.foreign_items.iter().copied()
}
- pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> + '_ {
+ pub fn owners(&self) -> impl Iterator<Item = OwnerId> + '_ {
self.items
.iter()
- .map(|id| id.owner_id.def_id)
- .chain(self.trait_items.iter().map(|id| id.owner_id.def_id))
- .chain(self.impl_items.iter().map(|id| id.owner_id.def_id))
- .chain(self.foreign_items.iter().map(|id| id.owner_id.def_id))
+ .map(|id| id.owner_id)
+ .chain(self.trait_items.iter().map(|id| id.owner_id))
+ .chain(self.impl_items.iter().map(|id| id.owner_id))
+ .chain(self.foreign_items.iter().map(|id| id.owner_id))
+ }
+
+ pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> + '_ {
+ self.owners().map(|id| id.def_id)
}
pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
@@ -104,7 +108,7 @@ impl<'tcx> TyCtxt<'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)))
+ .unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id).subst_identity()))
}
}
@@ -121,13 +125,13 @@ pub fn provide(providers: &mut Providers) {
let node = owner.node();
Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies })
};
- providers.local_def_id_to_hir_id = |tcx, id| {
+ providers.opt_local_def_id_to_hir_id = |tcx, id| {
let owner = tcx.hir_crate(()).owners[id].map(|_| ());
- match owner {
+ Some(match owner {
MaybeOwner::Owner(_) => HirId::make_owner(id),
MaybeOwner::Phantom => bug!("No HirId for {:?}", id),
MaybeOwner::NonOwner(hir_id) => hir_id,
- }
+ })
};
providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id.def_id].map(|i| &i.nodes);
providers.hir_owner_parent = |tcx, id| {
@@ -173,6 +177,7 @@ pub fn provide(providers: &mut Providers) {
}
};
providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
+ providers.opt_rpitit_info = |_, _| None;
providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
providers.expn_that_defined = |tcx, id| {
let id = id.expect_local();
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 43583b572..7f8fc1774 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -25,10 +25,8 @@ use crate::infer::MemberConstraint;
use crate::mir::ConstraintCategory;
use crate::ty::subst::GenericArg;
use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
-use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
use smallvec::SmallVec;
-use std::iter;
use std::ops::Index;
/// A "canonicalized" type `V` is one where all free inference
@@ -44,12 +42,12 @@ pub struct Canonical<'tcx, V> {
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
-impl<'tcx> ty::TypeFoldable<'tcx> for CanonicalVarInfos<'tcx> {
- fn try_fold_with<F: ty::FallibleTypeFolder<'tcx>>(
+impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
+ fn try_fold_with<F: ty::FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.intern_canonical_var_infos(v))
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_canonical_var_infos(v))
}
}
@@ -62,23 +60,23 @@ impl<'tcx> ty::TypeFoldable<'tcx> for CanonicalVarInfos<'tcx> {
/// vectors with the original values that were replaced by canonical
/// variables. You will need to supply it later to instantiate the
/// canonicalized query response.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct CanonicalVarValues<'tcx> {
- pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
+ pub var_values: ty::SubstsRef<'tcx>,
}
impl CanonicalVarValues<'_> {
pub fn is_identity(&self) -> bool {
- self.var_values.iter_enumerated().all(|(bv, arg)| match arg.unpack() {
+ self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
ty::GenericArgKind::Lifetime(r) => {
- matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var == bv)
+ matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var.as_usize() == bv)
}
ty::GenericArgKind::Type(ty) => {
- matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var == bv)
+ matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
}
ty::GenericArgKind::Const(ct) => {
- matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc == bv)
+ matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
}
})
}
@@ -125,6 +123,11 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
self.kind.universe()
}
+ #[must_use]
+ pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarInfo<'tcx> {
+ CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
+ }
+
pub fn is_existential(&self) -> bool {
match self.kind {
CanonicalVarKind::Ty(_) => true,
@@ -135,6 +138,28 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
CanonicalVarKind::PlaceholderConst(_, _) => false,
}
}
+
+ pub fn is_region(&self) -> bool {
+ match self.kind {
+ CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
+ CanonicalVarKind::Ty(_)
+ | CanonicalVarKind::PlaceholderTy(_)
+ | CanonicalVarKind::Const(_, _)
+ | CanonicalVarKind::PlaceholderConst(_, _) => false,
+ }
+ }
+
+ pub fn expect_anon_placeholder(self) -> u32 {
+ match self.kind {
+ CanonicalVarKind::Ty(_)
+ | CanonicalVarKind::Region(_)
+ | CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
+
+ CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.name.expect_anon(),
+ CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.name.expect_anon(),
+ CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.name.as_u32(),
+ }
+ }
}
/// Describes the "kind" of the canonical variable. This is a "kind"
@@ -179,6 +204,38 @@ impl<'tcx> CanonicalVarKind<'tcx> {
CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe,
}
}
+
+ /// Replaces the universe of this canonical variable with `ui`.
+ ///
+ /// In case this is a float or int variable, this causes an ICE if
+ /// the updated universe is not the root.
+ pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx> {
+ match self {
+ CanonicalVarKind::Ty(kind) => match kind {
+ CanonicalTyVarKind::General(_) => {
+ CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
+ }
+ CanonicalTyVarKind::Int | CanonicalTyVarKind::Float => {
+ assert_eq!(ui, ty::UniverseIndex::ROOT);
+ CanonicalVarKind::Ty(kind)
+ }
+ },
+ CanonicalVarKind::PlaceholderTy(placeholder) => {
+ CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder })
+ }
+ CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
+ CanonicalVarKind::PlaceholderRegion(placeholder) => {
+ CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe: ui, ..placeholder })
+ }
+ CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
+ CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
+ CanonicalVarKind::PlaceholderConst(
+ ty::Placeholder { universe: ui, ..placeholder },
+ ty,
+ )
+ }
+ }
+ }
}
/// Rust actually has more than one category of type variables;
@@ -215,7 +272,8 @@ pub struct QueryResponse<'tcx, R> {
pub value: R,
}
-#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct QueryRegionConstraints<'tcx> {
pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
pub member_constraints: Vec<MemberConstraint<'tcx>>,
@@ -326,10 +384,8 @@ impl<'tcx, V> Canonical<'tcx, V> {
}
}
-pub type QueryOutlivesConstraint<'tcx> = (
- ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>,
- ConstraintCategory<'tcx>,
-);
+pub type QueryOutlivesConstraint<'tcx> =
+ (ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>, ConstraintCategory<'tcx>);
TrivialTypeTraversalAndLiftImpls! {
for <'tcx> {
@@ -339,57 +395,57 @@ TrivialTypeTraversalAndLiftImpls! {
}
impl<'tcx> CanonicalVarValues<'tcx> {
+ // Given a list of canonical variables, construct a set of values which are
+ // the identity response.
+ pub fn make_identity(
+ tcx: TyCtxt<'tcx>,
+ infos: CanonicalVarInfos<'tcx>,
+ ) -> CanonicalVarValues<'tcx> {
+ CanonicalVarValues {
+ var_values: tcx.mk_substs_from_iter(infos.iter().enumerate().map(
+ |(i, info)| -> ty::GenericArg<'tcx> {
+ match info.kind {
+ CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
+ tcx.mk_bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into()).into()
+ }
+ CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
+ let br = ty::BoundRegion {
+ var: ty::BoundVar::from_usize(i),
+ kind: ty::BrAnon(i as u32, None),
+ };
+ tcx.mk_re_late_bound(ty::INNERMOST, br).into()
+ }
+ CanonicalVarKind::Const(_, ty)
+ | CanonicalVarKind::PlaceholderConst(_, ty) => tcx
+ .mk_const(
+ ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)),
+ ty,
+ )
+ .into(),
+ }
+ },
+ )),
+ }
+ }
+
/// Creates dummy var values which should not be used in a
/// canonical response.
pub fn dummy() -> CanonicalVarValues<'tcx> {
- CanonicalVarValues { var_values: Default::default() }
+ CanonicalVarValues { var_values: ty::List::empty() }
}
#[inline]
pub fn len(&self) -> usize {
self.var_values.len()
}
-
- /// Makes an identity substitution from this one: each bound var
- /// is matched to the same bound var, preserving the original kinds.
- /// For example, if we have:
- /// `self.var_values == [Type(u32), Lifetime('a), Type(u64)]`
- /// we'll return a substitution `subst` with:
- /// `subst.var_values == [Type(^0), Lifetime(^1), Type(^2)]`.
- pub fn make_identity(&self, tcx: TyCtxt<'tcx>) -> Self {
- use crate::ty::subst::GenericArgKind;
-
- CanonicalVarValues {
- var_values: iter::zip(&self.var_values, 0..)
- .map(|(kind, i)| match kind.unpack() {
- GenericArgKind::Type(..) => {
- tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
- }
- GenericArgKind::Lifetime(..) => {
- let br = ty::BoundRegion {
- var: ty::BoundVar::from_u32(i),
- kind: ty::BrAnon(i, None),
- };
- tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
- }
- GenericArgKind::Const(ct) => tcx
- .mk_const(
- ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)),
- ct.ty(),
- )
- .into(),
- })
- .collect(),
- }
- }
}
impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
type Item = GenericArg<'tcx>;
- type IntoIter = ::std::iter::Cloned<::std::slice::Iter<'a, GenericArg<'tcx>>>;
+ type IntoIter = ::std::iter::Copied<::std::slice::Iter<'a, GenericArg<'tcx>>>;
fn into_iter(self) -> Self::IntoIter {
- self.var_values.iter().cloned()
+ self.var_values.iter()
}
}
@@ -397,6 +453,6 @@ impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
type Output = GenericArg<'tcx>;
fn index(&self, value: BoundVar) -> &GenericArg<'tcx> {
- &self.var_values[value]
+ &self.var_values[value.as_usize()]
}
}
diff --git a/compiler/rustc_middle/src/infer/mod.rs b/compiler/rustc_middle/src/infer/mod.rs
index 38868c210..2db59f37f 100644
--- a/compiler/rustc_middle/src/infer/mod.rs
+++ b/compiler/rustc_middle/src/infer/mod.rs
@@ -12,7 +12,8 @@ use rustc_span::Span;
/// ```text
/// R0 member of [O1..On]
/// ```
-#[derive(Debug, Clone, HashStable, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct MemberConstraint<'tcx> {
/// The `DefId` and substs of the opaque type causing this constraint.
/// Used for error reporting.
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 7e4063c2f..c33b9d84e 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -34,6 +34,7 @@
#![feature(get_mut_unchecked)]
#![feature(if_let_guard)]
#![feature(iter_from_generator)]
+#![feature(local_key_cell_methods)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(extern_types)]
@@ -43,21 +44,21 @@
#![feature(min_specialization)]
#![feature(trusted_len)]
#![feature(type_alias_impl_trait)]
+#![feature(strict_provenance)]
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
#![feature(control_flow_enum)]
-#![feature(associated_type_defaults)]
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(try_reserve_kind)]
#![feature(nonzero_ops)]
-#![feature(unwrap_infallible)]
#![feature(decl_macro)]
#![feature(drain_filter)]
#![feature(intra_doc_pointers)]
#![feature(yeet_expr)]
#![feature(result_option_inspect)]
#![feature(const_option)]
+#![feature(trait_alias)]
#![recursion_limit = "512"]
#![allow(rustc::potential_query_instability)]
@@ -72,6 +73,9 @@ extern crate tracing;
#[macro_use]
extern crate smallvec;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
#[cfg(test)]
mod tests;
@@ -104,3 +108,5 @@ pub mod util {
// Allows macros to refer to this crate as `::rustc_middle`
extern crate self as rustc_middle;
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 250f3d079..a8d71ce03 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -69,8 +69,8 @@ macro_rules! CloneLiftImpls {
macro_rules! TrivialTypeTraversalImpls {
(for <$tcx:lifetime> { $($ty:ty,)+ }) => {
$(
- impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty {
- fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$tcx>>(
+ impl<$tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<$tcx>> for $ty {
+ fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$crate::ty::TyCtxt<$tcx>>>(
self,
_: &mut F,
) -> ::std::result::Result<Self, F::Error> {
@@ -78,7 +78,7 @@ macro_rules! TrivialTypeTraversalImpls {
}
#[inline]
- fn fold_with<F: $crate::ty::fold::TypeFolder<$tcx>>(
+ fn fold_with<F: $crate::ty::fold::TypeFolder<$crate::ty::TyCtxt<$tcx>>>(
self,
_: &mut F,
) -> Self {
@@ -86,9 +86,9 @@ macro_rules! TrivialTypeTraversalImpls {
}
}
- impl<$tcx> $crate::ty::visit::TypeVisitable<$tcx> for $ty {
+ impl<$tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<$tcx>> for $ty {
#[inline]
- fn visit_with<F: $crate::ty::visit::TypeVisitor<$tcx>>(
+ fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<$tcx>>>(
&self,
_: &mut F)
-> ::std::ops::ControlFlow<F::BreakTy>
@@ -101,7 +101,7 @@ macro_rules! TrivialTypeTraversalImpls {
($($ty:ty,)+) => {
TrivialTypeTraversalImpls! {
- for <'tcx> {
+ for<'tcx> {
$($ty,)+
}
}
@@ -115,145 +115,3 @@ macro_rules! TrivialTypeTraversalAndLiftImpls {
CloneLiftImpls! { $($t)* }
}
}
-
-#[macro_export]
-macro_rules! EnumTypeTraversalImpl {
- (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
- $($variants:tt)*
- } $(where $($wc:tt)*)*) => {
- impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
- $(where $($wc)*)*
- {
- fn try_fold_with<V: $crate::ty::fold::FallibleTypeFolder<$tcx>>(
- self,
- folder: &mut V,
- ) -> ::std::result::Result<Self, V::Error> {
- EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output())
- }
- }
- };
-
- (impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path {
- $($variants:tt)*
- } $(where $($wc:tt)*)*) => {
- impl<$($p),*> $crate::ty::visit::TypeVisitable<$tcx> for $s
- $(where $($wc)*)*
- {
- fn visit_with<V: $crate::ty::visit::TypeVisitor<$tcx>>(
- &self,
- visitor: &mut V,
- ) -> ::std::ops::ControlFlow<V::BreakTy> {
- EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
- }
- }
- };
-
- (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
- Ok(match $this {
- $($output)*
- })
- };
-
- (@FoldVariants($this:expr, $folder:expr)
- input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @FoldVariants($this, $folder)
- input($($input)*)
- output(
- $variant ( $($variant_arg),* ) => {
- $variant (
- $($crate::ty::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),*
- )
- }
- $($output)*
- )
- )
- };
-
- (@FoldVariants($this:expr, $folder:expr)
- input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @FoldVariants($this, $folder)
- input($($input)*)
- output(
- $variant { $($variant_arg),* } => {
- $variant {
- $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with(
- $variant_arg, $folder
- )?),* }
- }
- $($output)*
- )
- )
- };
-
- (@FoldVariants($this:expr, $folder:expr)
- input( ($variant:path), $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @FoldVariants($this, $folder)
- input($($input)*)
- output(
- $variant => { $variant }
- $($output)*
- )
- )
- };
-
- (@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => {
- match $this {
- $($output)*
- }
- };
-
- (@VisitVariants($this:expr, $visitor:expr)
- input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @VisitVariants($this, $visitor)
- input($($input)*)
- output(
- $variant ( $($variant_arg),* ) => {
- $($crate::ty::visit::TypeVisitable::visit_with(
- $variant_arg, $visitor
- )?;)*
- ::std::ops::ControlFlow::Continue(())
- }
- $($output)*
- )
- )
- };
-
- (@VisitVariants($this:expr, $visitor:expr)
- input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @VisitVariants($this, $visitor)
- input($($input)*)
- output(
- $variant { $($variant_arg),* } => {
- $($crate::ty::visit::TypeVisitable::visit_with(
- $variant_arg, $visitor
- )?;)*
- ::std::ops::ControlFlow::Continue(())
- }
- $($output)*
- )
- )
- };
-
- (@VisitVariants($this:expr, $visitor:expr)
- input( ($variant:path), $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @VisitVariants($this, $visitor)
- input($($input)*)
- output(
- $variant => { ::std::ops::ControlFlow::Continue(()) }
- $($output)*
- )
- )
- };
-}
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index bea884c85..c4601a1fb 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -91,7 +91,8 @@ bitflags! {
/// the MIR `InstrumentCoverage` pass and not added to the coverage map
/// during codegen.
const NO_COVERAGE = 1 << 15;
- /// `#[used(linker)]`: indicates that LLVM nor the linker can eliminate this function.
+ /// `#[used(linker)]`:
+ /// indicates that neither LLVM nor the linker will eliminate this function.
const USED_LINKER = 1 << 16;
/// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory.
const DEALLOCATOR = 1 << 17;
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 8dc68b1f5..0b6774f1b 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -29,7 +29,7 @@ pub mod lib_features {
pub mod limits;
pub mod privacy;
pub mod region;
-pub mod resolve_lifetime;
+pub mod resolve_bound_vars;
pub mod stability;
pub fn provide(providers: &mut crate::ty::query::Providers) {
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 0e18ba73d..893bf54b8 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -194,11 +194,6 @@ impl EffectiveVisibilities {
}
}
-pub trait IntoDefIdTree {
- type Tree: DefIdTree;
- fn tree(self) -> Self::Tree;
-}
-
impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> {
self.map.iter()
@@ -217,25 +212,21 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
self.map.entry(id).or_insert_with(|| EffectiveVisibility::from_vis(lazy_private_vis()))
}
- pub fn update<T: IntoDefIdTree>(
+ pub fn update(
&mut self,
id: Id,
nominal_vis: Visibility,
- lazy_private_vis: impl FnOnce(T) -> (Visibility, T),
+ lazy_private_vis: impl FnOnce() -> Visibility,
inherited_effective_vis: EffectiveVisibility,
level: Level,
- mut into_tree: T,
+ tree: impl DefIdTree,
) -> bool {
let mut changed = false;
- let mut current_effective_vis = match self.map.get(&id).copied() {
- Some(eff_vis) => eff_vis,
- None => {
- let private_vis;
- (private_vis, into_tree) = lazy_private_vis(into_tree);
- EffectiveVisibility::from_vis(private_vis)
- }
- };
- let tree = into_tree.tree();
+ let mut current_effective_vis = self
+ .map
+ .get(&id)
+ .copied()
+ .unwrap_or_else(|| EffectiveVisibility::from_vis(lazy_private_vis()));
let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.at_level(level);
let mut calculated_effective_vis = inherited_effective_vis_at_prev_level;
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
index c3bf1c717..c59704fc0 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
@@ -1,18 +1,20 @@
-//! Name resolution for lifetimes: type declarations.
+//! Name resolution for lifetimes and late-bound type and const variables: type declarations.
use crate::ty;
use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_hir::{ItemLocalId, OwnerId};
use rustc_macros::HashStable;
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
-pub enum Region {
- Static,
- EarlyBound(/* lifetime decl */ DefId),
- LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* lifetime decl */ DefId),
+pub enum ResolvedArg {
+ StaticLifetime,
+ EarlyBound(/* decl */ DefId),
+ LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId),
Free(DefId, /* lifetime decl */ DefId),
+ Error(ErrorGuaranteed),
}
/// A set containing, at most, one known element.
@@ -46,10 +48,10 @@ pub enum ObjectLifetimeDefault {
/// Maps the id of each lifetime reference to the lifetime decl
/// that it corresponds to.
#[derive(Default, HashStable, Debug)]
-pub struct ResolveLifetimes {
+pub struct ResolveBoundVars {
/// Maps from every use of a named (not anonymous) lifetime to a
/// `Region` describing how that region is bound
- pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Region>>,
+ pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, ResolvedArg>>,
pub late_bound_vars: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
}
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 0836f236e..354c84e22 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -255,7 +255,7 @@ fn late_report_deprecation(
let method_span = method_span.unwrap_or(span);
tcx.struct_span_lint_hir(lint, hir_id, method_span, message, |diag| {
if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
- let kind = tcx.def_kind(def_id).descr(def_id);
+ let kind = tcx.def_descr(def_id);
deprecation_suggestion(diag, kind, suggestion, method_span);
}
diag
@@ -392,7 +392,7 @@ impl<'tcx> TyCtxt<'tcx> {
let lint = deprecation_lint(is_in_effect);
if self.lint_level_at_node(lint, id).0 != Level::Allow {
let def_path = with_no_trimmed_paths!(self.def_path_str(def_id));
- let def_kind = self.def_kind(def_id).descr(def_id);
+ let def_kind = self.def_descr(def_id);
late_report_deprecation(
self,
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index 752cbdeae..b93871769 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -1,41 +1,46 @@
-use crate::mir::graph_cyclic_cache::GraphIsCyclicCache;
-use crate::mir::predecessors::{PredecessorCache, Predecessors};
-use crate::mir::switch_sources::{SwitchSourceCache, SwitchSources};
-use crate::mir::traversal::PostorderCache;
-use crate::mir::{BasicBlock, BasicBlockData, Successors, START_BLOCK};
+use crate::mir::traversal::Postorder;
+use crate::mir::{BasicBlock, BasicBlockData, Successors, Terminator, TerminatorKind, START_BLOCK};
+use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::graph;
use rustc_data_structures::graph::dominators::{dominators, Dominators};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::OnceCell;
use rustc_index::vec::IndexVec;
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use smallvec::SmallVec;
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
pub struct BasicBlocks<'tcx> {
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
- predecessor_cache: PredecessorCache,
- switch_source_cache: SwitchSourceCache,
- is_cyclic: GraphIsCyclicCache,
- postorder_cache: PostorderCache,
+ cache: Cache,
+}
+
+// Typically 95%+ of basic blocks have 4 or fewer predecessors.
+pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
+
+pub type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>; 1]>>;
+
+#[derive(Clone, Default, Debug)]
+struct Cache {
+ predecessors: OnceCell<Predecessors>,
+ switch_sources: OnceCell<SwitchSources>,
+ is_cyclic: OnceCell<bool>,
+ postorder: OnceCell<Vec<BasicBlock>>,
}
impl<'tcx> BasicBlocks<'tcx> {
#[inline]
pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
- BasicBlocks {
- basic_blocks,
- predecessor_cache: PredecessorCache::new(),
- switch_source_cache: SwitchSourceCache::new(),
- is_cyclic: GraphIsCyclicCache::new(),
- postorder_cache: PostorderCache::new(),
- }
+ BasicBlocks { basic_blocks, cache: Cache::default() }
}
/// Returns true if control-flow graph contains a cycle reachable from the `START_BLOCK`.
#[inline]
pub fn is_cfg_cyclic(&self) -> bool {
- self.is_cyclic.is_cyclic(self)
+ *self.cache.is_cyclic.get_or_init(|| graph::is_cyclic(self))
}
- #[inline]
pub fn dominators(&self) -> Dominators<BasicBlock> {
dominators(&self)
}
@@ -43,20 +48,46 @@ impl<'tcx> BasicBlocks<'tcx> {
/// Returns predecessors for each basic block.
#[inline]
pub fn predecessors(&self) -> &Predecessors {
- self.predecessor_cache.compute(&self.basic_blocks)
+ self.cache.predecessors.get_or_init(|| {
+ let mut preds = IndexVec::from_elem(SmallVec::new(), &self.basic_blocks);
+ for (bb, data) in self.basic_blocks.iter_enumerated() {
+ if let Some(term) = &data.terminator {
+ for succ in term.successors() {
+ preds[succ].push(bb);
+ }
+ }
+ }
+ preds
+ })
}
/// Returns basic blocks in a postorder.
#[inline]
pub fn postorder(&self) -> &[BasicBlock] {
- self.postorder_cache.compute(&self.basic_blocks)
+ self.cache.postorder.get_or_init(|| {
+ Postorder::new(&self.basic_blocks, START_BLOCK).map(|(bb, _)| bb).collect()
+ })
}
/// `switch_sources()[&(target, switch)]` returns a list of switch
/// values that lead to a `target` block from a `switch` block.
#[inline]
pub fn switch_sources(&self) -> &SwitchSources {
- self.switch_source_cache.compute(&self.basic_blocks)
+ self.cache.switch_sources.get_or_init(|| {
+ let mut switch_sources: SwitchSources = FxHashMap::default();
+ for (bb, data) in self.basic_blocks.iter_enumerated() {
+ if let Some(Terminator {
+ kind: TerminatorKind::SwitchInt { targets, .. }, ..
+ }) = &data.terminator
+ {
+ for (value, target) in targets.iter() {
+ switch_sources.entry((target, bb)).or_default().push(Some(value));
+ }
+ switch_sources.entry((targets.otherwise(), bb)).or_default().push(None);
+ }
+ }
+ switch_sources
+ })
}
/// Returns mutable reference to basic blocks. Invalidates CFG cache.
@@ -88,10 +119,7 @@ impl<'tcx> BasicBlocks<'tcx> {
/// All other methods that allow you to mutate the basic blocks also call this method
/// themselves, thereby avoiding any risk of accidentally cache invalidation.
pub fn invalidate_cfg_cache(&mut self) {
- self.predecessor_cache.invalidate();
- self.switch_source_cache.invalidate();
- self.is_cyclic.invalidate();
- self.postorder_cache.invalidate();
+ self.cache = Cache::default();
}
}
@@ -145,3 +173,24 @@ impl<'tcx> graph::WithPredecessors for BasicBlocks<'tcx> {
self.predecessors()[node].iter().copied()
}
}
+
+TrivialTypeTraversalAndLiftImpls! {
+ Cache,
+}
+
+impl<S: Encoder> Encodable<S> for Cache {
+ #[inline]
+ fn encode(&self, _s: &mut S) {}
+}
+
+impl<D: Decoder> Decodable<D> for Cache {
+ #[inline]
+ fn decode(_: &mut D) -> Self {
+ Default::default()
+ }
+}
+
+impl<CTX> HashStable<CTX> for Cache {
+ #[inline]
+ fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {}
+}
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index e7bb3ab0b..db24dae11 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -135,7 +135,10 @@ impl Debug for CoverageKind {
"Expression({:?}) = {} {} {}",
id.index(),
lhs.index(),
- if *op == Op::Add { "+" } else { "-" },
+ match op {
+ Op::Add => "+",
+ Op::Subtract => "-",
+ },
rhs.index(),
),
Unreachable => write!(fmt, "Unreachable"),
diff --git a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
deleted file mode 100644
index f97bf2883..000000000
--- a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use rustc_data_structures::graph::{
- self, DirectedGraph, WithNumNodes, WithStartNode, WithSuccessors,
-};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::OnceCell;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-
-/// Helper type to cache the result of `graph::is_cyclic`.
-#[derive(Clone, Debug)]
-pub(super) struct GraphIsCyclicCache {
- cache: OnceCell<bool>,
-}
-
-impl GraphIsCyclicCache {
- #[inline]
- pub(super) fn new() -> Self {
- GraphIsCyclicCache { cache: OnceCell::new() }
- }
-
- pub(super) fn is_cyclic<G>(&self, graph: &G) -> bool
- where
- G: ?Sized + DirectedGraph + WithStartNode + WithSuccessors + WithNumNodes,
- {
- *self.cache.get_or_init(|| graph::is_cyclic(graph))
- }
-
- /// Invalidates the cache.
- #[inline]
- pub(super) fn invalidate(&mut self) {
- // Invalidating the cache requires mutating the MIR, which in turn requires a unique
- // reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
- // callers of `invalidate` have a unique reference to the MIR and thus to the
- // cache. This means we never need to do synchronization when `invalidate` is called,
- // we can simply reinitialize the `OnceCell`.
- self.cache = OnceCell::new();
- }
-}
-
-impl<S: Encoder> Encodable<S> for GraphIsCyclicCache {
- #[inline]
- fn encode(&self, s: &mut S) {
- Encodable::encode(&(), s);
- }
-}
-
-impl<D: Decoder> Decodable<D> for GraphIsCyclicCache {
- #[inline]
- fn decode(d: &mut D) -> Self {
- let () = Decodable::decode(d);
- Self::new()
- }
-}
-
-impl<CTX> HashStable<CTX> for GraphIsCyclicCache {
- #[inline]
- fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
- // do nothing
- }
-}
-
-TrivialTypeTraversalAndLiftImpls! {
- GraphIsCyclicCache,
-}
diff --git a/compiler/rustc_middle/src/mir/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs
index 5de56dad0..cf6d46e1e 100644
--- a/compiler/rustc_middle/src/mir/graphviz.rs
+++ b/compiler/rustc_middle/src/mir/graphviz.rs
@@ -110,7 +110,7 @@ fn write_graph_label<'tcx, W: std::fmt::Write>(
let decl = &body.local_decls[local];
write!(w, "let ")?;
- if decl.mutability == Mutability::Mut {
+ if decl.mutability.is_mut() {
write!(w, "mut ")?;
}
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 221105ac4..48375ed30 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -8,7 +8,8 @@ mod tests;
use std::borrow::Cow;
use std::fmt;
use std::hash;
-use std::ops::Range;
+use std::hash::Hash;
+use std::ops::{Deref, DerefMut, Range};
use std::ptr;
use either::{Left, Right};
@@ -29,6 +30,39 @@ use provenance_map::*;
pub use init_mask::{InitChunk, InitChunkIter};
+/// Functionality required for the bytes of an `Allocation`.
+pub trait AllocBytes:
+ Clone + fmt::Debug + Eq + PartialEq + Hash + Deref<Target = [u8]> + DerefMut<Target = [u8]>
+{
+ /// Adjust the bytes to the specified alignment -- by default, this is a no-op.
+ fn adjust_to_align(self, _align: Align) -> Self;
+
+ /// Create an `AllocBytes` from a slice of `u8`.
+ fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self;
+
+ /// Create a zeroed `AllocBytes` of the specified size and alignment;
+ /// call the callback error handler if there is an error in allocating the memory.
+ fn zeroed(size: Size, _align: Align) -> Option<Self>;
+}
+
+// Default `bytes` for `Allocation` is a `Box<[u8]>`.
+impl AllocBytes for Box<[u8]> {
+ fn adjust_to_align(self, _align: Align) -> Self {
+ self
+ }
+
+ fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self {
+ Box::<[u8]>::from(slice.into())
+ }
+
+ fn zeroed(size: Size, _align: Align) -> Option<Self> {
+ let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).ok()?;
+ // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
+ let bytes = unsafe { bytes.assume_init() };
+ Some(bytes)
+ }
+}
+
/// This type represents an Allocation in the Miri/CTFE core engine.
///
/// Its public API is rather low-level, working directly with allocation offsets and a custom error
@@ -38,10 +72,10 @@ pub use init_mask::{InitChunk, InitChunkIter};
// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
#[derive(Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
#[derive(HashStable)]
-pub struct Allocation<Prov: Provenance = AllocId, Extra = ()> {
+pub struct Allocation<Prov: Provenance = AllocId, Extra = (), Bytes = Box<[u8]>> {
/// The actual bytes of the allocation.
/// Note that the bytes of a pointer represent the offset of the pointer.
- bytes: Box<[u8]>,
+ bytes: Bytes,
/// Maps from byte addresses to extra provenance data for each pointer.
/// Only the first byte of a pointer is inserted into the map; i.e.,
/// every entry in this map applies to `pointer_size` consecutive bytes starting
@@ -220,14 +254,27 @@ impl AllocRange {
}
// The constructors are all without extra; the extra gets added by a machine hook later.
-impl<Prov: Provenance> Allocation<Prov> {
+impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
+ /// Creates an allocation from an existing `Bytes` value - this is needed for miri FFI support
+ pub fn from_raw_bytes(bytes: Bytes, align: Align, mutability: Mutability) -> Self {
+ let size = Size::from_bytes(bytes.len());
+ Self {
+ bytes,
+ provenance: ProvenanceMap::new(),
+ init_mask: InitMask::new(size, true),
+ align,
+ mutability,
+ extra: (),
+ }
+ }
+
/// Creates an allocation initialized by the given bytes
pub fn from_bytes<'a>(
slice: impl Into<Cow<'a, [u8]>>,
align: Align,
mutability: Mutability,
) -> Self {
- let bytes = Box::<[u8]>::from(slice.into());
+ let bytes = Bytes::from_bytes(slice, align);
let size = Size::from_bytes(bytes.len());
Self {
bytes,
@@ -248,7 +295,7 @@ impl<Prov: Provenance> Allocation<Prov> {
///
/// If `panic_on_fail` is true, this will never return `Err`.
pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> {
- let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| {
+ let bytes = Bytes::zeroed(size, align).ok_or_else(|| {
// This results in an error that can happen non-deterministically, since the memory
// available to the compiler can change between runs. Normally queries are always
// deterministic. However, we can be non-deterministic here because all uses of const
@@ -262,8 +309,7 @@ impl<Prov: Provenance> Allocation<Prov> {
});
InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
})?;
- // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
- let bytes = unsafe { bytes.assume_init() };
+
Ok(Allocation {
bytes,
provenance: ProvenanceMap::new(),
@@ -275,7 +321,7 @@ impl<Prov: Provenance> Allocation<Prov> {
}
}
-impl Allocation {
+impl<Bytes: AllocBytes> Allocation<AllocId, (), Bytes> {
/// Adjust allocation from the ones in tcx to a custom Machine instance
/// with a different Provenance and Extra type.
pub fn adjust_from_tcx<Prov: Provenance, Extra, Err>(
@@ -283,9 +329,11 @@ impl Allocation {
cx: &impl HasDataLayout,
extra: Extra,
mut adjust_ptr: impl FnMut(Pointer<AllocId>) -> Result<Pointer<Prov>, Err>,
- ) -> Result<Allocation<Prov, Extra>, Err> {
- // Compute new pointer provenance, which also adjusts the bytes.
- let mut bytes = self.bytes;
+ ) -> Result<Allocation<Prov, Extra, Bytes>, Err> {
+ // Compute new pointer provenance, which also adjusts the bytes, and realign the pointer if
+ // necessary.
+ let mut bytes = self.bytes.adjust_to_align(self.align);
+
let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len());
let ptr_size = cx.data_layout().pointer_size.bytes_usize();
let endian = cx.data_layout().endian;
@@ -311,7 +359,7 @@ impl Allocation {
}
/// Raw accessors. Provide access to otherwise private bytes.
-impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
+impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
pub fn len(&self) -> usize {
self.bytes.len()
}
@@ -340,7 +388,11 @@ impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
}
/// Byte accessors.
-impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
+impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
+ pub fn base_addr(&self) -> *const u8 {
+ self.bytes.as_ptr()
+ }
+
/// This is the entirely abstraction-violating way to just grab the raw bytes without
/// caring about provenance or initialization.
///
@@ -412,7 +464,7 @@ impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
}
/// Reading and writing.
-impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
+impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
/// Sets the init bit for the given range.
fn mark_init(&mut self, range: AllocRange, is_init: bool) {
if range.size.bytes() == 0 {
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index bd9cd53e1..c5137cf06 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -323,7 +323,7 @@ impl fmt::Display for UndefinedBehaviorInfo {
write!(
f,
"{msg}{pointer} is a dangling pointer (it has no provenance)",
- pointer = Pointer::<Option<AllocId>>::from_addr(*i),
+ pointer = Pointer::<Option<AllocId>>::from_addr_invalid(*i),
)
}
AlignmentCheckFailed { required, has } => write!(
@@ -430,8 +430,10 @@ pub enum ResourceExhaustionInfo {
///
/// The exact limit is set by the `const_eval_limit` attribute.
StepLimitReached,
- /// There is not enough memory to perform an allocation.
+ /// There is not enough memory (on the host) to perform an allocation.
MemoryExhausted,
+ /// The address space (of the target) is full.
+ AddressSpaceFull,
}
impl fmt::Display for ResourceExhaustionInfo {
@@ -447,6 +449,9 @@ impl fmt::Display for ResourceExhaustionInfo {
MemoryExhausted => {
write!(f, "tried to allocate more memory than available to compiler")
}
+ AddressSpaceFull => {
+ write!(f, "there are no more free addresses in the address space")
+ }
}
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 5f425a287..1766d7a66 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -110,7 +110,7 @@ use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_serialize::{Decodable, Encodable};
-use rustc_target::abi::Endian;
+use rustc_target::abi::{AddressSpace, Endian, HasDataLayout};
use crate::mir;
use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -127,8 +127,8 @@ pub use self::error::{
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
pub use self::allocation::{
- alloc_range, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation, InitChunk,
- InitChunkIter,
+ alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation,
+ InitChunk, InitChunkIter,
};
pub use self::pointer::{Pointer, PointerArithmetic, Provenance};
@@ -438,6 +438,17 @@ impl<'tcx> GlobalAlloc<'tcx> {
_ => bug!("expected vtable, got {:?}", self),
}
}
+
+ /// The address space that this `GlobalAlloc` should be placed in.
+ #[inline]
+ pub fn address_space(&self, cx: &impl HasDataLayout) -> AddressSpace {
+ match self {
+ GlobalAlloc::Function(..) => cx.data_layout().instruction_address_space,
+ GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) | GlobalAlloc::VTable(..) => {
+ AddressSpace::DATA
+ }
+ }
+ }
}
pub(crate) struct AllocMap<'tcx> {
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index b08309910..60927eed8 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -19,29 +19,29 @@ pub trait PointerArithmetic: HasDataLayout {
#[inline(always)]
fn max_size_of_val(&self) -> Size {
- Size::from_bytes(self.machine_isize_max())
+ Size::from_bytes(self.target_isize_max())
}
#[inline]
- fn machine_usize_max(&self) -> u64 {
+ fn target_usize_max(&self) -> u64 {
self.pointer_size().unsigned_int_max().try_into().unwrap()
}
#[inline]
- fn machine_isize_min(&self) -> i64 {
+ fn target_isize_min(&self) -> i64 {
self.pointer_size().signed_int_min().try_into().unwrap()
}
#[inline]
- fn machine_isize_max(&self) -> i64 {
+ fn target_isize_max(&self) -> i64 {
self.pointer_size().signed_int_max().try_into().unwrap()
}
#[inline]
- fn machine_usize_to_isize(&self, val: u64) -> i64 {
+ fn target_usize_to_isize(&self, val: u64) -> i64 {
let val = val as i64;
// Now wrap-around into the machine_isize range.
- if val > self.machine_isize_max() {
+ if val > self.target_isize_max() {
// This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into
// i64.
debug_assert!(self.pointer_size().bits() < 64);
@@ -76,11 +76,11 @@ pub trait PointerArithmetic: HasDataLayout {
let n = i.unsigned_abs();
if i >= 0 {
let (val, over) = self.overflowing_offset(val, n);
- (val, over || i > self.machine_isize_max())
+ (val, over || i > self.target_isize_max())
} else {
let res = val.overflowing_sub(n);
let (val, over) = self.truncate_to_ptr(res);
- (val, over || i < self.machine_isize_min())
+ (val, over || i < self.target_isize_min())
}
}
@@ -251,14 +251,16 @@ impl<Prov> Pointer<Option<Prov>> {
}
impl<Prov> Pointer<Option<Prov>> {
+ /// Creates a pointer to the given address, with invalid provenance (i.e., cannot be used for
+ /// any memory access).
#[inline(always)]
- pub fn from_addr(addr: u64) -> Self {
+ pub fn from_addr_invalid(addr: u64) -> Self {
Pointer { provenance: None, offset: Size::from_bytes(addr) }
}
#[inline(always)]
pub fn null() -> Self {
- Pointer::from_addr(0)
+ Pointer::from_addr_invalid(0)
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index b6c6e9d55..856d821a5 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -2,7 +2,7 @@ use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId}
use crate::mir;
use crate::ty::subst::InternalSubsts;
-use crate::ty::visit::TypeVisitable;
+use crate::ty::visit::TypeVisitableExt;
use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 88fb14eb3..36dbbe4bf 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -75,8 +75,8 @@ impl<'tcx> ConstValue<'tcx> {
self.try_to_scalar_int()?.try_into().ok()
}
- pub fn try_to_machine_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
- self.try_to_scalar_int()?.try_to_machine_usize(tcx).ok()
+ pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
+ self.try_to_scalar_int()?.try_to_target_usize(tcx).ok()
}
pub fn try_to_bits_for_ty(
@@ -97,8 +97,8 @@ impl<'tcx> ConstValue<'tcx> {
ConstValue::Scalar(Scalar::from_u64(i))
}
- pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
- ConstValue::Scalar(Scalar::from_machine_usize(i, cx))
+ pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
+ ConstValue::Scalar(Scalar::from_target_usize(i, cx))
}
}
@@ -241,7 +241,7 @@ impl<Prov> Scalar<Prov> {
}
#[inline]
- pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
+ pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
Self::from_uint(i, cx.data_layout().pointer_size)
}
@@ -268,7 +268,7 @@ impl<Prov> Scalar<Prov> {
}
#[inline]
- pub fn from_machine_isize(i: i64, cx: &impl HasDataLayout) -> Self {
+ pub fn from_target_isize(i: i64, cx: &impl HasDataLayout) -> Self {
Self::from_int(i, cx.data_layout().pointer_size)
}
@@ -322,7 +322,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
Right(ptr) => Ok(ptr.into()),
Left(bits) => {
let addr = u64::try_from(bits).unwrap();
- Ok(Pointer::from_addr(addr))
+ Ok(Pointer::from_addr_invalid(addr))
}
}
}
@@ -429,7 +429,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized unsigned integer.
/// Fails if the scalar is a pointer.
- pub fn to_machine_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
+ pub fn to_target_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
let b = self.to_uint(cx.data_layout().pointer_size)?;
Ok(u64::try_from(b).unwrap())
}
@@ -469,7 +469,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized signed integer.
/// Fails if the scalar is a pointer.
- pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
+ pub fn to_target_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
let b = self.to_int(cx.data_layout().pointer_size)?;
Ok(i64::try_from(b).unwrap())
}
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index e52b243ec..99cdb769d 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -9,7 +9,7 @@ use crate::mir::visit::MirVisitable;
use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
use crate::ty::print::{FmtPrinter, Printer};
-use crate::ty::visit::{TypeVisitable, TypeVisitor};
+use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
use crate::ty::{self, DefIdTree, List, Ty, TyCtxt};
use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
@@ -27,7 +27,6 @@ use polonius_engine::Atom;
pub use rustc_ast::Mutability;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::dominators::Dominators;
-use rustc_index::bit_set::BitMatrix;
use rustc_index::vec::{Idx, IndexVec};
use rustc_serialize::{Decodable, Encodable};
use rustc_span::symbol::Symbol;
@@ -47,25 +46,21 @@ mod basic_blocks;
pub mod coverage;
mod generic_graph;
pub mod generic_graphviz;
-mod graph_cyclic_cache;
pub mod graphviz;
pub mod interpret;
pub mod mono;
pub mod patch;
-mod predecessors;
pub mod pretty;
mod query;
pub mod spanview;
mod syntax;
pub use syntax::*;
-mod switch_sources;
pub mod tcx;
pub mod terminator;
pub use terminator::*;
pub mod traversal;
mod type_foldable;
-mod type_visitable;
pub mod visit;
pub use self::generic_graph::graphviz_safe_def_name;
@@ -419,11 +414,7 @@ impl<'tcx> Body<'tcx> {
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
let decl = &self.local_decls[local];
- if decl.is_user_variable() && decl.mutability == Mutability::Mut {
- Some(local)
- } else {
- None
- }
+ (decl.is_user_variable() && decl.mutability.is_mut()).then_some(local)
})
}
@@ -712,7 +703,11 @@ pub enum BindingForm<'tcx> {
RefForGuard,
}
-TrivialTypeTraversalAndLiftImpls! { BindingForm<'tcx>, }
+TrivialTypeTraversalAndLiftImpls! {
+ for<'tcx> {
+ BindingForm<'tcx>,
+ }
+}
mod binding_form_impl {
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -905,6 +900,8 @@ pub enum LocalInfo<'tcx> {
AggregateTemp,
/// A temporary created during the pass `Derefer` to avoid it's retagging
DerefTemp,
+ /// A temporary created for borrow checking.
+ FakeBorrow,
}
impl<'tcx> LocalDecl<'tcx> {
@@ -1464,6 +1461,7 @@ impl Debug for Statement<'_> {
}
Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind),
Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"),
+ ConstEvalCounter => write!(fmt, "ConstEvalCounter"),
Nop => write!(fmt, "nop"),
}
}
@@ -1622,7 +1620,7 @@ impl<'tcx> Place<'tcx> {
&v
};
- Place { local: self.local, projection: tcx.intern_place_elems(new_projections) }
+ Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
}
}
@@ -1644,6 +1642,14 @@ impl<'tcx> PlaceRef<'tcx> {
}
}
+ /// Returns `true` if this `Place` contains a `Deref` projection.
+ ///
+ /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the
+ /// same region of memory as its base.
+ pub fn is_indirect(&self) -> bool {
+ self.projection.iter().any(|elem| elem.is_indirect())
+ }
+
/// If MirPhase >= Derefered and if projection contains Deref,
/// It's guaranteed to be in the first place
pub fn has_deref(&self) -> bool {
@@ -2102,10 +2108,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
let name = if tcx.sess.opts.unstable_opts.span_free_formats {
let substs = tcx.lift(substs).unwrap();
- format!(
- "[closure@{}]",
- tcx.def_path_str_with_substs(def_id.to_def_id(), substs),
- )
+ format!("[closure@{}]", tcx.def_path_str_with_substs(def_id, substs),)
} else {
let span = tcx.def_span(def_id);
format!(
@@ -2116,11 +2119,17 @@ impl<'tcx> Debug for Rvalue<'tcx> {
let mut struct_fmt = fmt.debug_struct(&name);
// FIXME(project-rfc-2229#48): This should be a list of capture names/places
- if let Some(upvars) = tcx.upvars_mentioned(def_id) {
+ if let Some(def_id) = def_id.as_local()
+ && let Some(upvars) = tcx.upvars_mentioned(def_id)
+ {
for (&var_id, place) in iter::zip(upvars.keys(), places) {
let var_name = tcx.hir().name(var_id);
struct_fmt.field(var_name.as_str(), place);
}
+ } else {
+ for (index, place) in places.iter().enumerate() {
+ struct_fmt.field(&format!("{index}"), place);
+ }
}
struct_fmt.finish()
@@ -2131,11 +2140,17 @@ impl<'tcx> Debug for Rvalue<'tcx> {
let mut struct_fmt = fmt.debug_struct(&name);
// FIXME(project-rfc-2229#48): This should be a list of capture names/places
- if let Some(upvars) = tcx.upvars_mentioned(def_id) {
+ if let Some(def_id) = def_id.as_local()
+ && let Some(upvars) = tcx.upvars_mentioned(def_id)
+ {
for (&var_id, place) in iter::zip(upvars.keys(), places) {
let var_name = tcx.hir().name(var_id);
struct_fmt.field(var_name.as_str(), place);
}
+ } else {
+ for (index, place) in places.iter().enumerate() {
+ struct_fmt.field(&format!("{index}"), place);
+ }
}
struct_fmt.finish()
@@ -2335,13 +2350,17 @@ impl<'tcx> ConstantKind<'tcx> {
}
#[inline]
- pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<u64> {
+ pub fn try_eval_target_usize(
+ &self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ ) -> Option<u64> {
match self {
- Self::Ty(ct) => ct.try_eval_usize(tcx, param_env),
- Self::Val(val, _) => val.try_to_machine_usize(tcx),
+ Self::Ty(ct) => ct.try_eval_target_usize(tcx, param_env),
+ Self::Val(val, _) => val.try_to_target_usize(tcx),
Self::Unevaluated(uneval, _) => {
match tcx.const_eval_resolve(param_env, *uneval, None) {
- Ok(val) => val.try_to_machine_usize(tcx),
+ Ok(val) => val.try_to_target_usize(tcx),
Err(_) => None,
}
}
@@ -2478,7 +2497,7 @@ impl<'tcx> ConstantKind<'tcx> {
};
debug!("expr.kind: {:?}", expr.kind);
- let ty = tcx.type_of(def.def_id_for_type_of());
+ let ty = tcx.type_of(def.def_id_for_type_of()).subst_identity();
debug!(?ty);
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
@@ -2506,20 +2525,19 @@ 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().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 {
- tcx.mk_substs(Vec::<GenericArg<'tcx>>::new().into_iter())
- }
+ let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
+ && let Some(parent_did) = parent_hir_id.as_owner()
+ {
+ InternalSubsts::identity_for_item(tcx, parent_did.to_def_id())
} else {
- tcx.mk_substs(Vec::<GenericArg<'tcx>>::new().into_iter())
+ List::empty()
};
debug!(?parent_substs);
let did = def.did.to_def_id();
let child_substs = InternalSubsts::identity_for_item(tcx, did);
- let substs = tcx.mk_substs(parent_substs.into_iter().chain(child_substs.into_iter()));
+ let substs =
+ tcx.mk_substs_from_iter(parent_substs.into_iter().chain(child_substs.into_iter()));
debug!(?substs);
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
@@ -2737,8 +2755,11 @@ impl UserTypeProjection {
}
}
-impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for UserTypeProjection {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(UserTypeProjection {
base: self.base.try_fold_with(folder)?,
projs: self.projs.try_fold_with(folder)?,
@@ -2746,8 +2767,11 @@ impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
}
}
-impl<'tcx> TypeVisitable<'tcx> for UserTypeProjection {
- fn visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<Vs::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for UserTypeProjection {
+ fn visit_with<Vs: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut Vs,
+ ) -> ControlFlow<Vs::BreakTy> {
self.base.visit_with(visitor)
// Note: there's nothing in `self.proj` to visit.
}
@@ -2884,7 +2908,7 @@ fn pretty_print_const_value<'tcx>(
// the `destructure_const` query with an empty `ty::ParamEnv` without
// introducing ICEs (e.g. via `layout_of`) from missing bounds.
// E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
- // to be able to destructure the tuple into `(0u8, *mut T)
+ // to be able to destructure the tuple into `(0u8, *mut T)`
//
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
// correct `ty::ParamEnv` to allow printing *all* constant values.
@@ -3049,7 +3073,7 @@ impl Location {
if self.block == other.block {
self.statement_index <= other.statement_index
} else {
- dominators.is_dominated_by(other.block, self.block)
+ dominators.dominates(self.block, other.block)
}
}
}
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 1e8d5f7ea..7a05ee2ff 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -318,16 +318,19 @@ impl<'tcx> CodegenUnit<'tcx> {
base_n::encode(hash, base_n::CASE_INSENSITIVE)
}
- pub fn estimate_size(&mut self, tcx: TyCtxt<'tcx>) {
+ pub fn create_size_estimate(&mut self, tcx: TyCtxt<'tcx>) {
// Estimate the size of a codegen unit as (approximately) the number of MIR
// statements it corresponds to.
self.size_estimate = Some(self.items.keys().map(|mi| mi.size_estimate(tcx)).sum());
}
#[inline]
+ /// Should only be called if [`create_size_estimate`] has previously been called.
+ ///
+ /// [`create_size_estimate`]: Self::create_size_estimate
pub fn size_estimate(&self) -> usize {
- // Should only be called if `estimate_size` has previously been called.
- self.size_estimate.expect("estimate_size must be called before getting a size_estimate")
+ self.size_estimate
+ .expect("create_size_estimate must be called before getting a size_estimate")
}
pub fn modify_size_estimate(&mut self, delta: usize) {
diff --git a/compiler/rustc_middle/src/mir/predecessors.rs b/compiler/rustc_middle/src/mir/predecessors.rs
deleted file mode 100644
index 5f1fadaf3..000000000
--- a/compiler/rustc_middle/src/mir/predecessors.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-//! Lazily compute the reverse control-flow graph for the MIR.
-
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::OnceCell;
-use rustc_index::vec::IndexVec;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use smallvec::SmallVec;
-
-use crate::mir::{BasicBlock, BasicBlockData};
-
-// Typically 95%+ of basic blocks have 4 or fewer predecessors.
-pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
-
-#[derive(Clone, Debug)]
-pub(super) struct PredecessorCache {
- cache: OnceCell<Predecessors>,
-}
-
-impl PredecessorCache {
- #[inline]
- pub(super) fn new() -> Self {
- PredecessorCache { cache: OnceCell::new() }
- }
-
- /// Invalidates the predecessor cache.
- #[inline]
- pub(super) fn invalidate(&mut self) {
- // Invalidating the predecessor cache requires mutating the MIR, which in turn requires a
- // unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
- // callers of `invalidate` have a unique reference to the MIR and thus to the predecessor
- // cache. This means we never need to do synchronization when `invalidate` is called, we can
- // simply reinitialize the `OnceCell`.
- self.cache = OnceCell::new();
- }
-
- /// Returns the predecessor graph for this MIR.
- #[inline]
- pub(super) fn compute(
- &self,
- basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
- ) -> &Predecessors {
- self.cache.get_or_init(|| {
- let mut preds = IndexVec::from_elem(SmallVec::new(), basic_blocks);
- for (bb, data) in basic_blocks.iter_enumerated() {
- if let Some(term) = &data.terminator {
- for succ in term.successors() {
- preds[succ].push(bb);
- }
- }
- }
-
- preds
- })
- }
-}
-
-impl<S: Encoder> Encodable<S> for PredecessorCache {
- #[inline]
- fn encode(&self, _s: &mut S) {}
-}
-
-impl<D: Decoder> Decodable<D> for PredecessorCache {
- #[inline]
- fn decode(_: &mut D) -> Self {
- Self::new()
- }
-}
-
-impl<CTX> HashStable<CTX> for PredecessorCache {
- #[inline]
- fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
- // do nothing
- }
-}
-
-TrivialTypeTraversalAndLiftImpls! {
- PredecessorCache,
-}
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 40289af25..d8829e3e7 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -12,8 +12,8 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_index::vec::Idx;
use rustc_middle::mir::interpret::{
- alloc_range, read_target_uint, AllocId, Allocation, ConstAllocation, ConstValue, GlobalAlloc,
- Pointer, Provenance,
+ alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, ConstAllocation, ConstValue,
+ GlobalAlloc, Pointer, Provenance,
};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
@@ -580,7 +580,7 @@ fn write_scope_tree(
continue;
}
- let mut_str = if local_decl.mutability == Mutability::Mut { "mut " } else { "" };
+ let mut_str = local_decl.mutability.prefix_str();
let mut indented_decl =
format!("{0:1$}let {2}{3:?}: {4:?}", INDENT, indent, mut_str, local, local_decl.ty);
@@ -787,21 +787,21 @@ pub fn write_allocations<'tcx>(
/// After the hex dump, an ascii dump follows, replacing all unprintable characters (control
/// characters or characters whose value is larger than 127) with a `.`
/// This also prints provenance adequately.
-pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra>(
+pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
tcx: TyCtxt<'tcx>,
- alloc: &'a Allocation<Prov, Extra>,
-) -> RenderAllocation<'a, 'tcx, Prov, Extra> {
+ alloc: &'a Allocation<Prov, Extra, Bytes>,
+) -> RenderAllocation<'a, 'tcx, Prov, Extra, Bytes> {
RenderAllocation { tcx, alloc }
}
#[doc(hidden)]
-pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra> {
+pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> {
tcx: TyCtxt<'tcx>,
- alloc: &'a Allocation<Prov, Extra>,
+ alloc: &'a Allocation<Prov, Extra, Bytes>,
}
-impl<'a, 'tcx, Prov: Provenance, Extra> std::fmt::Display
- for RenderAllocation<'a, 'tcx, Prov, Extra>
+impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> std::fmt::Display
+ for RenderAllocation<'a, 'tcx, Prov, Extra, Bytes>
{
fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let RenderAllocation { tcx, alloc } = *self;
@@ -845,9 +845,9 @@ fn write_allocation_newline(
/// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there
/// is only one line). Note that your prefix should contain a trailing space as the lines are
/// printed directly after it.
-fn write_allocation_bytes<'tcx, Prov: Provenance, Extra>(
+fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
tcx: TyCtxt<'tcx>,
- alloc: &Allocation<Prov, Extra>,
+ alloc: &Allocation<Prov, Extra, Bytes>,
w: &mut dyn std::fmt::Write,
prefix: &str,
) -> std::fmt::Result {
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index a8a453222..b964c1852 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -8,7 +8,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_index::bit_set::BitMatrix;
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::{Idx, IndexVec};
use rustc_span::Span;
use rustc_target::abi::VariantIdx;
use smallvec::SmallVec;
@@ -135,11 +135,20 @@ rustc_index::newtype_index! {
pub struct GeneratorSavedLocal {}
}
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
+pub struct GeneratorSavedTy<'tcx> {
+ pub ty: Ty<'tcx>,
+ /// Source info corresponding to the local in the original MIR body.
+ pub source_info: SourceInfo,
+ /// Whether the local should be ignored for trait bound computations.
+ pub ignore_for_traits: bool,
+}
+
/// The layout of generator state.
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct GeneratorLayout<'tcx> {
/// The type of every local stored inside the generator.
- pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
+ pub field_tys: IndexVec<GeneratorSavedLocal, GeneratorSavedTy<'tcx>>,
/// Which of the above fields are in each variant. Note that one field may
/// be stored in multiple variants.
@@ -152,6 +161,8 @@ pub struct GeneratorLayout<'tcx> {
/// Which saved locals are storage-live at the same time. Locals that do not
/// have conflicts with each other are allowed to overlap in the computed
/// layout.
+ #[type_foldable(identity)]
+ #[type_visitable(ignore)]
pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
}
@@ -278,13 +289,6 @@ pub struct ConstQualifs {
/// instance of the closure is created, the corresponding free regions
/// can be extracted from its type and constrained to have the given
/// outlives relationship.
-///
-/// In some cases, we have to record outlives requirements between types and
-/// regions as well. In that case, if those types include any regions, those
-/// regions are recorded using their external names (`ReStatic`,
-/// `ReEarlyBound`, `ReFree`). We use these because in a query response we
-/// cannot use `ReVar` (which is what we use internally within the rest of the
-/// NLL code).
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct ClosureRegionRequirements<'tcx> {
/// The number of external regions defined on the closure. In our
@@ -381,16 +385,59 @@ pub enum ClosureOutlivesSubject<'tcx> {
/// Subject is a type, typically a type parameter, but could also
/// be a projection. Indicates a requirement like `T: 'a` being
/// passed to the caller, where the type here is `T`.
- ///
- /// The type here is guaranteed not to contain any free regions at
- /// present.
- Ty(Ty<'tcx>),
+ Ty(ClosureOutlivesSubjectTy<'tcx>),
/// Subject is a free region from the closure. Indicates a requirement
/// like `'a: 'b` being passed to the caller; the region here is `'a`.
Region(ty::RegionVid),
}
+/// Represents a `ty::Ty` for use in [`ClosureOutlivesSubject`].
+///
+/// This abstraction is necessary because the type may include `ReVar` regions,
+/// which is what we use internally within NLL code, and they can't be used in
+/// a query response.
+///
+/// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this
+/// type is not recognized as a binder for late-bound region.
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
+pub struct ClosureOutlivesSubjectTy<'tcx> {
+ inner: Ty<'tcx>,
+}
+
+impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
+ /// All regions of `ty` must be of kind `ReVar` and must represent
+ /// universal regions *external* to the closure.
+ pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
+ let inner = tcx.fold_regions(ty, |r, depth| match r.kind() {
+ ty::ReVar(vid) => {
+ let br = ty::BoundRegion {
+ var: ty::BoundVar::new(vid.index()),
+ kind: ty::BrAnon(vid.as_u32(), None),
+ };
+ tcx.mk_re_late_bound(depth, br)
+ }
+ _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
+ });
+
+ Self { inner }
+ }
+
+ pub fn instantiate(
+ self,
+ tcx: TyCtxt<'tcx>,
+ mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>,
+ ) -> Ty<'tcx> {
+ tcx.fold_regions(self.inner, |r, depth| match r.kind() {
+ ty::ReLateBound(debruijn, br) => {
+ debug_assert_eq!(debruijn, depth);
+ map(ty::RegionVid::new(br.var.index()))
+ }
+ _ => bug!("unexpected region {r:?}"),
+ })
+ }
+}
+
/// The constituent parts of a mir constant of kind ADT or array.
#[derive(Copy, Clone, Debug, HashStable)]
pub struct DestructuredConstant<'tcx> {
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 887ee5715..28a3b51b7 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -11,7 +11,7 @@ use std::io::{self, Write};
pub const TOOLTIP_INDENT: &str = " ";
const CARET: char = '\u{2038}'; // Unicode `CARET`
-const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT BINDING BRACKET
+const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT BINDING BRACKET`
const ANNOTATION_RIGHT_BRACKET: char = '\u{2989}'; // Unicode `Z NOTATION LEFT BINDING BRACKET`
const NEW_LINE_SPAN: &str = "</span>\n<span class=\"line\">";
const HEADER: &str = r#"<!DOCTYPE html>
@@ -250,6 +250,7 @@ pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str {
AscribeUserType(..) => "AscribeUserType",
Coverage(..) => "Coverage",
Intrinsic(..) => "Intrinsic",
+ ConstEvalCounter => "ConstEvalCounter",
Nop => "Nop",
}
}
@@ -670,7 +671,7 @@ fn fn_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
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))
+ hir::map::associated_body(hir_node).map(|(_, fn_body_id)| tcx.hir().body(fn_body_id))
}
fn escape_html(s: &str) -> String {
diff --git a/compiler/rustc_middle/src/mir/switch_sources.rs b/compiler/rustc_middle/src/mir/switch_sources.rs
deleted file mode 100644
index b91c0c257..000000000
--- a/compiler/rustc_middle/src/mir/switch_sources.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-//! Lazily compute the inverse of each `SwitchInt`'s switch targets. Modeled after
-//! `Predecessors`/`PredecessorCache`.
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::OnceCell;
-use rustc_index::vec::IndexVec;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use smallvec::SmallVec;
-
-use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind};
-
-pub type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>; 1]>>;
-
-#[derive(Clone, Debug)]
-pub(super) struct SwitchSourceCache {
- cache: OnceCell<SwitchSources>,
-}
-
-impl SwitchSourceCache {
- #[inline]
- pub(super) fn new() -> Self {
- SwitchSourceCache { cache: OnceCell::new() }
- }
-
- /// Invalidates the switch source cache.
- #[inline]
- pub(super) fn invalidate(&mut self) {
- self.cache = OnceCell::new();
- }
-
- /// Returns the switch sources for this MIR.
- #[inline]
- pub(super) fn compute(
- &self,
- basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
- ) -> &SwitchSources {
- self.cache.get_or_init(|| {
- let mut switch_sources: SwitchSources = FxHashMap::default();
- for (bb, data) in basic_blocks.iter_enumerated() {
- if let Some(Terminator {
- kind: TerminatorKind::SwitchInt { targets, .. }, ..
- }) = &data.terminator
- {
- for (value, target) in targets.iter() {
- switch_sources.entry((target, bb)).or_default().push(Some(value));
- }
- switch_sources.entry((targets.otherwise(), bb)).or_default().push(None);
- }
- }
-
- switch_sources
- })
- }
-}
-
-impl<S: Encoder> Encodable<S> for SwitchSourceCache {
- #[inline]
- fn encode(&self, _s: &mut S) {}
-}
-
-impl<D: Decoder> Decodable<D> for SwitchSourceCache {
- #[inline]
- fn decode(_: &mut D) -> Self {
- Self::new()
- }
-}
-
-impl<CTX> HashStable<CTX> for SwitchSourceCache {
- #[inline]
- fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
- // do nothing
- }
-}
-
-TrivialTypeTraversalAndLiftImpls! {
- SwitchSourceCache,
-}
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 52c2b10cb..ae09562a8 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -355,6 +355,12 @@ pub enum StatementKind<'tcx> {
/// This avoids adding a new block and a terminator for simple intrinsics.
Intrinsic(Box<NonDivergingIntrinsic<'tcx>>),
+ /// Instructs the const eval interpreter to increment a counter; this counter is used to track
+ /// how many steps the interpreter has taken. It is used to prevent the user from writing const
+ /// code that runs for too long or infinitely. Other than in the const eval interpreter, this
+ /// is a no-op.
+ ConstEvalCounter,
+
/// No-op. Useful for deleting instructions without affecting statement indices.
Nop,
}
@@ -665,6 +671,12 @@ pub enum TerminatorKind<'tcx> {
/// as parameters, and `None` for the destination. Keep in mind that the `cleanup` path is not
/// necessarily executed even in the case of a panic, for example in `-C panic=abort`. If the
/// assertion does not fail, execution continues at the specified basic block.
+ ///
+ /// When overflow checking is disabled and this is run-time MIR (as opposed to compile-time MIR
+ /// that is used for CTFE), the following variants of this terminator behave as `goto target`:
+ /// - `OverflowNeg(..)`,
+ /// - `Overflow(op, ..)` if op is a "checkable" operation (add, sub, mul, shl, shr, but NOT
+ /// div or rem).
Assert {
cond: Operand<'tcx>,
expected: bool,
@@ -1097,10 +1109,6 @@ pub enum Rvalue<'tcx> {
/// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
///
- /// When overflow checking is disabled and we are generating run-time code, the error condition
- /// is false. Otherwise, and always during CTFE, the error condition is determined as described
- /// below.
- ///
/// For addition, subtraction, and multiplication on integers the error condition is set when
/// the infinite precision result would be unequal to the actual result.
///
@@ -1197,10 +1205,8 @@ pub enum AggregateKind<'tcx> {
/// active field index would identity the field `c`
Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
- // Note: We can use LocalDefId since closures and generators a deaggregated
- // before codegen.
- Closure(LocalDefId, SubstsRef<'tcx>),
- Generator(LocalDefId, SubstsRef<'tcx>, hir::Movability),
+ Closure(DefId, SubstsRef<'tcx>),
+ Generator(DefId, SubstsRef<'tcx>, hir::Movability),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 599f0b9d3..0aa2c500f 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -97,7 +97,7 @@ impl<'tcx> PlaceTy<'tcx> {
ty::Slice(..) => self.ty,
ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64),
ty::Array(inner, size) if from_end => {
- let size = size.eval_usize(tcx, param_env);
+ let size = size.eval_target_usize(tcx, param_env);
let len = size - (from as u64) - (to as u64);
tcx.mk_array(*inner, len)
}
@@ -162,10 +162,10 @@ impl<'tcx> Rvalue<'tcx> {
match *self {
Rvalue::Use(ref operand) => operand.ty(local_decls, tcx),
Rvalue::Repeat(ref operand, count) => {
- tcx.mk_ty(ty::Array(operand.ty(local_decls, tcx), count))
+ tcx.mk_array_with_const_len(operand.ty(local_decls, tcx), count)
}
Rvalue::ThreadLocalRef(did) => {
- let static_ty = tcx.type_of(did);
+ let static_ty = tcx.type_of(did).subst_identity();
if tcx.is_mutable_static(did) {
tcx.mk_mut_ptr(static_ty)
} else if tcx.is_foreign_item(did) {
@@ -194,20 +194,20 @@ impl<'tcx> Rvalue<'tcx> {
let lhs_ty = lhs.ty(local_decls, tcx);
let rhs_ty = rhs.ty(local_decls, tcx);
let ty = op.ty(tcx, lhs_ty, rhs_ty);
- tcx.intern_tup(&[ty, tcx.types.bool])
+ tcx.mk_tup(&[ty, tcx.types.bool])
}
Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize,
Rvalue::Aggregate(ref ak, ref ops) => match **ak {
AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64),
- AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))),
- AggregateKind::Adt(did, _, substs, _, _) => {
- tcx.bound_type_of(did).subst(tcx, substs)
+ AggregateKind::Tuple => {
+ tcx.mk_tup_from_iter(ops.iter().map(|op| op.ty(local_decls, tcx)))
}
- AggregateKind::Closure(did, substs) => tcx.mk_closure(did.to_def_id(), substs),
+ AggregateKind::Adt(did, _, substs, _, _) => tcx.type_of(did).subst(tcx, substs),
+ AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs),
AggregateKind::Generator(did, substs, movability) => {
- tcx.mk_generator(did.to_def_id(), substs, movability)
+ tcx.mk_generator(did, substs, movability)
}
},
Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty),
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index 0b461d1ce..f37222cb2 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -1,7 +1,4 @@
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::OnceCell;
use rustc_index::bit_set::BitSet;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use super::*;
@@ -339,50 +336,3 @@ pub fn reverse_postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> ReversePostorderIter
let len = blocks.len();
ReversePostorderIter { body, blocks, idx: len }
}
-
-#[derive(Clone, Debug)]
-pub(super) struct PostorderCache {
- cache: OnceCell<Vec<BasicBlock>>,
-}
-
-impl PostorderCache {
- #[inline]
- pub(super) fn new() -> Self {
- PostorderCache { cache: OnceCell::new() }
- }
-
- /// Invalidates the postorder cache.
- #[inline]
- pub(super) fn invalidate(&mut self) {
- self.cache = OnceCell::new();
- }
-
- /// Returns the `&[BasicBlocks]` represents the postorder graph for this MIR.
- #[inline]
- pub(super) fn compute(&self, body: &IndexVec<BasicBlock, BasicBlockData<'_>>) -> &[BasicBlock] {
- self.cache.get_or_init(|| Postorder::new(body, START_BLOCK).map(|(bb, _)| bb).collect())
- }
-}
-
-impl<S: Encoder> Encodable<S> for PostorderCache {
- #[inline]
- fn encode(&self, _s: &mut S) {}
-}
-
-impl<D: Decoder> Decodable<D> for PostorderCache {
- #[inline]
- fn decode(_: &mut D) -> Self {
- Self::new()
- }
-}
-
-impl<CTX> HashStable<CTX> for PostorderCache {
- #[inline]
- fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
- // do nothing
- }
-}
-
-TrivialTypeTraversalAndLiftImpls! {
- PostorderCache,
-}
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 0705b4cff..988158321 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -30,26 +30,29 @@ TrivialTypeTraversalImpls! {
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx [InlineAsmTemplatePiece] {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ _folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(self)
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx [Span] {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [Span] {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ _folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(self)
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
- }
-}
-
-impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
- Ok(self)
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_place_elems(v))
}
}
diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs
deleted file mode 100644
index d44c6809b..000000000
--- a/compiler/rustc_middle/src/mir/type_visitable.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//! `TypeVisitable` implementations for MIR types
-
-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(())
- }
-}
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 1a264d2d5..5c056b299 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -323,7 +323,7 @@ macro_rules! make_mir_visitor {
self.visit_source_scope($(& $mutability)? *parent_scope);
}
if let Some((callee, callsite_span)) = inlined {
- let location = START_BLOCK.start_location();
+ let location = Location::START;
self.visit_span($(& $mutability)? *callsite_span);
@@ -427,6 +427,7 @@ macro_rules! make_mir_visitor {
}
}
}
+ StatementKind::ConstEvalCounter => {}
StatementKind::Nop => {}
}
}
@@ -836,7 +837,7 @@ macro_rules! make_mir_visitor {
} = var_debug_info;
self.visit_source_info(source_info);
- let location = START_BLOCK.start_location();
+ let location = Location::START;
match value {
VarDebugInfoContents::Const(c) => self.visit_constant(c, location),
VarDebugInfoContents::Place(place) =>
@@ -1025,7 +1026,7 @@ macro_rules! super_body {
$self.visit_span($(& $mutability)? $body.span);
for const_ in &$($mutability)? $body.required_consts {
- let location = START_BLOCK.start_location();
+ let location = Location::START;
$self.visit_constant(const_, location);
}
}
@@ -1044,7 +1045,7 @@ macro_rules! visit_place_fns {
self.visit_local(&mut place.local, context, location);
if let Some(new_projection) = self.process_projection(&place.projection, location) {
- place.projection = self.tcx().intern_place_elems(&new_projection);
+ place.projection = self.tcx().mk_place_elems(&new_projection);
}
}
@@ -1213,7 +1214,7 @@ impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
/// Extra information passed to `visit_ty` and friends to give context
/// about where the type etc appears.
-#[derive(Debug)]
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum TyContext {
LocalDecl {
/// The index of the local variable we are visiting.
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index e4bb3ce3d..78ee8a6a8 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -4,11 +4,12 @@ use crate::infer::canonical::Canonical;
use crate::mir;
use crate::traits;
use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::layout::{TyAndLayout, ValidityRequirement};
use crate::ty::subst::{GenericArg, SubstsRef};
-use crate::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
+use crate::ty::{self, Ty, TyCtxt};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::hir_id::{HirId, OwnerId};
-use rustc_query_system::query::{DefaultCacheSelector, VecCacheSelector};
+use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
@@ -45,7 +46,7 @@ pub trait Key: Sized {
}
impl Key for () {
- type CacheSelector = DefaultCacheSelector<Self>;
+ type CacheSelector = SingleCacheSelector;
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
@@ -696,3 +697,24 @@ impl Key for HirId {
None
}
}
+
+impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
+ // Just forward to `Ty<'tcx>`
+ #[inline(always)]
+ fn query_crate_is_local(&self) -> bool {
+ true
+ }
+
+ fn default_span(&self, _: TyCtxt<'_>) -> Span {
+ DUMMY_SP
+ }
+
+ fn ty_adt_id(&self) -> Option<DefId> {
+ match self.1.value.kind() {
+ ty::Adt(adt, _) => Some(adt.did()),
+ _ => None,
+ }
+ }
+}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 6bbf7fa39..5133da342 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -33,7 +33,7 @@ rustc_queries! {
}
query resolver_for_lowering(_: ()) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
- feedable
+ eval_always
no_hash
desc { "getting the resolver for lowering" }
}
@@ -54,14 +54,14 @@ rustc_queries! {
/// This is because the `hir_crate` query gives you access to all other items.
/// To avoid this fate, do not call `tcx.hir().krate()`; instead,
/// prefer wrappers like `tcx.visit_all_items_in_krate()`.
- query hir_crate(key: ()) -> Crate<'tcx> {
+ query hir_crate(key: ()) -> &'tcx Crate<'tcx> {
arena_cache
eval_always
desc { "getting the crate HIR" }
}
/// All items in the crate.
- query hir_crate_items(_: ()) -> rustc_middle::hir::ModuleItems {
+ query hir_crate_items(_: ()) -> &'tcx rustc_middle::hir::ModuleItems {
arena_cache
eval_always
desc { "getting HIR crate items" }
@@ -71,7 +71,7 @@ rustc_queries! {
///
/// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
/// Avoid calling this query directly.
- query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems {
+ query hir_module_items(key: LocalDefId) -> &'tcx rustc_middle::hir::ModuleItems {
arena_cache
desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
@@ -85,12 +85,12 @@ rustc_queries! {
desc { |tcx| "getting HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) }
}
- /// Gives access to the HIR ID for the given `LocalDefId` owner `key`.
+ /// Gives access to the HIR ID for the given `LocalDefId` owner `key` if any.
///
- /// This can be conveniently accessed by methods on `tcx.hir()`.
- /// Avoid calling this query directly.
- query local_def_id_to_hir_id(key: LocalDefId) -> hir::HirId {
+ /// Definitions that were generated with no HIR, would be feeded to return `None`.
+ query opt_local_def_id_to_hir_id(key: LocalDefId) -> Option<hir::HirId>{
desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) }
+ feedable
}
/// Gives access to the HIR node's parent for the HIR owner `key`.
@@ -152,7 +152,7 @@ rustc_queries! {
/// to an alias, it will "skip" this alias to return the aliased type.
///
/// [`DefId`]: rustc_hir::def_id::DefId
- query type_of(key: DefId) -> Ty<'tcx> {
+ query type_of(key: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
desc { |tcx|
"{action} `{path}`",
action = {
@@ -167,6 +167,7 @@ rustc_queries! {
}
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
query collect_return_position_impl_trait_in_trait_tys(key: DefId)
@@ -183,6 +184,15 @@ rustc_queries! {
separate_provide_extern
}
+ query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32>
+ {
+ arena_cache
+ desc { |tcx|
+ "determining what parameters of `{}` can participate in unsizing",
+ tcx.def_path_str(key),
+ }
+ }
+
query analysis(key: ()) -> Result<(), ErrorGuaranteed> {
eval_always
desc { "running analysis passes on this crate" }
@@ -209,11 +219,12 @@ rustc_queries! {
/// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
/// associated generics.
- query generics_of(key: DefId) -> ty::Generics {
+ query generics_of(key: DefId) -> &'tcx ty::Generics {
desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) }
arena_cache
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
/// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
@@ -256,6 +267,7 @@ rustc_queries! {
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
/// Elaborated version of the predicates from `explicit_item_bounds`.
@@ -286,19 +298,19 @@ rustc_queries! {
/// These are assembled from the following places:
/// - `extern` blocks (depending on their `link` attributes)
/// - the `libs` (`-l`) option
- query native_libraries(_: CrateNum) -> Vec<NativeLib> {
+ query native_libraries(_: CrateNum) -> &'tcx Vec<NativeLib> {
arena_cache
desc { "looking up the native libraries of a linked crate" }
separate_provide_extern
}
- query shallow_lint_levels_on(key: hir::OwnerId) -> rustc_middle::lint::ShallowLintLevelMap {
+ query shallow_lint_levels_on(key: hir::OwnerId) -> &'tcx rustc_middle::lint::ShallowLintLevelMap {
eval_always // fetches `resolutions`
arena_cache
desc { |tcx| "looking up lint levels for `{}`", tcx.def_path_str(key.to_def_id()) }
}
- query lint_expectations(_: ()) -> Vec<(LintExpectationId, LintExpectation)> {
+ query lint_expectations(_: ()) -> &'tcx Vec<(LintExpectationId, LintExpectation)> {
arena_cache
desc { "computing `#[expect]`ed lints in this crate" }
}
@@ -338,7 +350,7 @@ rustc_queries! {
}
/// Set of param indexes for type params that are in the type's representation
- query params_in_repr(key: DefId) -> rustc_index::bit_set::BitSet<u32> {
+ query params_in_repr(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32> {
desc { "finding type parameters in the representation" }
arena_cache
no_hash
@@ -355,16 +367,23 @@ rustc_queries! {
}
/// Create a THIR tree for debugging.
- query thir_tree(key: ty::WithOptConstParam<LocalDefId>) -> String {
+ query thir_tree(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx String {
no_hash
arena_cache
desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key.did.to_def_id()) }
}
+ /// Create a list-like THIR representation for debugging.
+ query thir_flat(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx String {
+ no_hash
+ arena_cache
+ desc { |tcx| "constructing flat THIR representation for `{}`", tcx.def_path_str(key.did.to_def_id()) }
+ }
+
/// Set of all the `DefId`s in this crate that have MIR associated with
/// them. This includes all the body owners, but also things like struct
/// constructors.
- query mir_keys(_: ()) -> rustc_data_structures::fx::FxIndexSet<LocalDefId> {
+ query mir_keys(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexSet<LocalDefId> {
arena_cache
desc { "getting a list of all mir_keys" }
}
@@ -460,17 +479,24 @@ rustc_queries! {
}
}
- query symbols_for_closure_captures(
- key: (LocalDefId, LocalDefId)
- ) -> Vec<rustc_span::Symbol> {
- arena_cache
+ query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> {
desc {
- |tcx| "finding symbols for captures of closure `{}` in `{}`",
- tcx.def_path_str(key.1.to_def_id()),
- tcx.def_path_str(key.0.to_def_id())
+ |tcx| "finding symbols for captures of closure `{}`",
+ tcx.def_path_str(key.to_def_id())
}
}
+ query mir_generator_witnesses(key: DefId) -> &'tcx mir::GeneratorLayout<'tcx> {
+ arena_cache
+ desc { |tcx| "generator witness types for `{}`", tcx.def_path_str(key) }
+ cache_on_disk_if { key.is_local() }
+ separate_provide_extern
+ }
+
+ query check_generator_obligations(key: LocalDefId) {
+ desc { |tcx| "verify auto trait bounds for generator interior type `{}`", tcx.def_path_str(key.to_def_id()) }
+ }
+
/// MIR after our optimization passes have run. This is MIR that is ready
/// for codegen. This is also the only query that can fetch non-local MIR, at present.
query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
@@ -481,14 +507,14 @@ rustc_queries! {
/// Returns coverage summary info for a function, after executing the `InstrumentCoverage`
/// MIR pass (assuming the -Cinstrument-coverage option is enabled).
- query coverageinfo(key: ty::InstanceDef<'tcx>) -> mir::CoverageInfo {
+ query coverageinfo(key: ty::InstanceDef<'tcx>) -> &'tcx mir::CoverageInfo {
desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key.def_id()) }
arena_cache
}
/// Returns the `CodeRegions` for a function that has instrumented coverage, in case the
/// function was optimized out before codegen, and before being added to the Coverage Map.
- query covered_code_regions(key: DefId) -> Vec<&'tcx mir::coverage::CodeRegion> {
+ query covered_code_regions(key: DefId) -> &'tcx Vec<&'tcx mir::coverage::CodeRegion> {
desc {
|tcx| "retrieving the covered `CodeRegion`s, if instrumented, for `{}`",
tcx.def_path_str(key)
@@ -530,7 +556,7 @@ rustc_queries! {
desc { "erasing regions from `{}`", ty }
}
- query wasm_import_module_map(_: CrateNum) -> FxHashMap<DefId, String> {
+ query wasm_import_module_map(_: CrateNum) -> &'tcx FxHashMap<DefId, String> {
arena_cache
desc { "getting wasm import module map" }
}
@@ -566,6 +592,7 @@ rustc_queries! {
desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
/// Returns the inferred outlives predicates (e.g., for `struct
@@ -574,6 +601,7 @@ rustc_queries! {
desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
/// Maps from the `DefId` of a trait to the list of
@@ -605,7 +633,7 @@ rustc_queries! {
desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir().ty_param_name(key.1) }
}
- query trait_def(key: DefId) -> ty::TraitDef {
+ query trait_def(key: DefId) -> &'tcx ty::TraitDef {
desc { |tcx| "computing trait definition for `{}`", tcx.def_path_str(key) }
arena_cache
cache_on_disk_if { key.is_local() }
@@ -676,7 +704,7 @@ rustc_queries! {
}
/// Gets a map with the variance of every item; use `item_variance` instead.
- query crate_variances(_: ()) -> ty::CrateVariancesMap<'tcx> {
+ query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> {
arena_cache
desc { "computing the variances for items in this crate" }
}
@@ -689,7 +717,7 @@ rustc_queries! {
}
/// Maps from thee `DefId` of a type to its (inferred) outlives.
- query inferred_outlives_crate(_: ()) -> ty::CratePredicatesMap<'tcx> {
+ query inferred_outlives_crate(_: ()) -> &'tcx ty::CratePredicatesMap<'tcx> {
arena_cache
desc { "computing the inferred outlives predicates for items in this crate" }
}
@@ -704,13 +732,13 @@ rustc_queries! {
/// Maps from a trait item to the trait item "descriptor".
query associated_item(key: DefId) -> ty::AssocItem {
desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) }
- arena_cache
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
/// Collects the associated items defined on a trait or impl.
- query associated_items(key: DefId) -> ty::AssocItems<'tcx> {
+ query associated_items(key: DefId) -> &'tcx ty::AssocItems {
arena_cache
desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) }
}
@@ -736,11 +764,31 @@ rustc_queries! {
///
/// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be
///`{ trait_f: impl_f, trait_g: impl_g }`
- query impl_item_implementor_ids(impl_id: DefId) -> FxHashMap<DefId, DefId> {
+ query impl_item_implementor_ids(impl_id: DefId) -> &'tcx FxHashMap<DefId, DefId> {
arena_cache
desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) }
}
+ /// Given `fn_def_id` of a trait or of an impl that implements a given trait:
+ /// if `fn_def_id` is the def id of a function defined inside a trait, then it creates and returns
+ /// the associated items that correspond to each impl trait in return position for that trait.
+ /// if `fn_def_id` is the def id of a function defined inside an impl that implements a trait, then it
+ /// creates and returns the associated items that correspond to each impl trait in return position
+ /// of the implemented trait.
+ query associated_items_for_impl_trait_in_trait(fn_def_id: DefId) -> &'tcx [DefId] {
+ desc { |tcx| "creating associated items for impl trait in trait returned by `{}`", tcx.def_path_str(fn_def_id) }
+ cache_on_disk_if { fn_def_id.is_local() }
+ separate_provide_extern
+ }
+
+ /// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
+ /// associated item.
+ query associated_item_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {
+ desc { |tcx| "creates the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) }
+ cache_on_disk_if { true }
+ separate_provide_extern
+ }
+
/// Given an `impl_id`, return the trait it implements.
/// Return `None` if this is an inherent impl.
query impl_trait_ref(impl_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
@@ -754,7 +802,7 @@ rustc_queries! {
separate_provide_extern
}
- query issue33140_self_ty(key: DefId) -> Option<ty::Ty<'tcx>> {
+ query issue33140_self_ty(key: DefId) -> Option<ty::EarlyBinder<ty::Ty<'tcx>>> {
desc { |tcx| "computing Self type wrt issue #33140 `{}`", tcx.def_path_str(key) }
}
@@ -796,15 +844,6 @@ rustc_queries! {
}
}
- /// HACK: when evaluated, this reports an "unsafe derive on repr(packed)" error.
- ///
- /// Unsafety checking is executed for each method separately, but we only want
- /// to emit this error once per derive. As there are some impls with multiple
- /// methods, we use a query for deduplication.
- query unsafe_derive_on_repr_packed(key: LocalDefId) -> () {
- desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) }
- }
-
/// Returns the types assumed to be well formed while "inside" of the given item.
///
/// Note that we've liberated the late bound regions of function signatures, so
@@ -814,7 +853,7 @@ rustc_queries! {
}
/// Computes the signature of the function.
- query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> {
+ query fn_sig(key: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
@@ -866,7 +905,7 @@ rustc_queries! {
///
/// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone) and
/// their respective impl (i.e., part of the derive macro)
- query live_symbols_and_ignored_derived_traits(_: ()) -> (
+ query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx (
FxHashSet<LocalDefId>,
FxHashMap<LocalDefId, Vec<(DefId, DefId)>>
) {
@@ -946,7 +985,7 @@ rustc_queries! {
/// Gets a complete map from all types to their inherent impls.
/// Not meant to be used directly outside of coherence.
- query crate_inherent_impls(k: ()) -> CrateInherentImpls {
+ query crate_inherent_impls(k: ()) -> &'tcx CrateInherentImpls {
arena_cache
desc { "finding all inherent impls defined in crate" }
}
@@ -1081,7 +1120,7 @@ rustc_queries! {
desc { "checking for private elements in public interfaces" }
}
- query reachable_set(_: ()) -> FxHashSet<LocalDefId> {
+ query reachable_set(_: ()) -> &'tcx FxHashSet<LocalDefId> {
arena_cache
desc { "reachability" }
}
@@ -1093,7 +1132,7 @@ rustc_queries! {
}
/// Generates a MIR body for the shim.
- query mir_shims(key: ty::InstanceDef<'tcx>) -> mir::Body<'tcx> {
+ query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Body<'tcx> {
arena_cache
desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
}
@@ -1110,6 +1149,15 @@ rustc_queries! {
desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
+ feedable
+ }
+
+ /// The `opt_rpitit_info` query returns the pair of the def id of the function where the RPIT
+ /// is defined and the opaque def id if any.
+ query opt_rpitit_info(def_id: DefId) -> Option<ty::ImplTraitInTraitData> {
+ desc { |tcx| "opt_rpitit_info `{}`", tcx.def_path_str(def_id) }
+ cache_on_disk_if { def_id.is_local() }
+ feedable
}
/// Gets the span for the definition.
@@ -1125,6 +1173,7 @@ rustc_queries! {
desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
+ feedable
}
query lookup_stability(def_id: DefId) -> Option<attr::Stability> {
@@ -1157,6 +1206,7 @@ rustc_queries! {
/// Determines whether an item is annotated with `doc(hidden)`.
query is_doc_hidden(def_id: DefId) -> bool {
desc { |tcx| "checking whether `{}` is `doc(hidden)`", tcx.def_path_str(def_id) }
+ separate_provide_extern
}
/// Determines whether an item is annotated with `doc(notable_trait)`.
@@ -1172,7 +1222,7 @@ rustc_queries! {
separate_provide_extern
}
- query codegen_fn_attrs(def_id: DefId) -> CodegenFnAttrs {
+ query codegen_fn_attrs(def_id: DefId) -> &'tcx CodegenFnAttrs {
desc { |tcx| "computing codegen attributes of `{}`", tcx.def_path_str(def_id) }
arena_cache
cache_on_disk_if { def_id.is_local() }
@@ -1190,7 +1240,7 @@ rustc_queries! {
}
/// Gets the rendered value of the specified constant or associated constant.
/// Used by rustdoc.
- query rendered_const(def_id: DefId) -> String {
+ query rendered_const(def_id: DefId) -> &'tcx String {
arena_cache
desc { |tcx| "rendering constant initializer of `{}`", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
@@ -1249,12 +1299,12 @@ rustc_queries! {
}
/// Given a trait `trait_id`, return all known `impl` blocks.
- query trait_impls_of(trait_id: DefId) -> ty::trait_def::TraitImpls {
+ query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls {
arena_cache
desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) }
}
- query specialization_graph_of(trait_id: DefId) -> specialization_graph::Graph {
+ query specialization_graph_of(trait_id: DefId) -> &'tcx specialization_graph::Graph {
arena_cache
desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) }
cache_on_disk_if { true }
@@ -1262,6 +1312,9 @@ rustc_queries! {
query object_safety_violations(trait_id: DefId) -> &'tcx [traits::ObjectSafetyViolation] {
desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) }
}
+ query check_is_object_safe(trait_id: DefId) -> bool {
+ desc { |tcx| "checking if trait `{}` is object safe", tcx.def_path_str(trait_id) }
+ }
/// Gets the ParameterEnvironment for a given item; this environment
/// will be in "user-facing" mode, meaning that it is suitable for
@@ -1381,7 +1434,7 @@ rustc_queries! {
separate_provide_extern
}
- query dependency_formats(_: ()) -> Lrc<crate::middle::dependency_format::Dependencies> {
+ query dependency_formats(_: ()) -> &'tcx Lrc<crate::middle::dependency_format::Dependencies> {
arena_cache
desc { "getting the linkage format of all dependencies" }
}
@@ -1462,6 +1515,7 @@ rustc_queries! {
desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
+ feedable
}
query check_well_formed(key: hir::OwnerId) -> () {
@@ -1481,7 +1535,7 @@ rustc_queries! {
// Does not include external symbols that don't have a corresponding DefId,
// like the compiler-generated `main` function and so on.
query reachable_non_generics(_: CrateNum)
- -> DefIdMap<SymbolExportInfo> {
+ -> &'tcx DefIdMap<SymbolExportInfo> {
arena_cache
desc { "looking up the exported symbols of a crate" }
separate_provide_extern
@@ -1504,7 +1558,7 @@ rustc_queries! {
/// added or removed in any upstream crate. Instead use the narrower
/// `upstream_monomorphizations_for`, `upstream_drop_glue_for`, or, even
/// better, `Instance::upstream_monomorphization()`.
- query upstream_monomorphizations(_: ()) -> DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
+ query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
arena_cache
desc { "collecting available upstream monomorphizations" }
}
@@ -1519,7 +1573,6 @@ rustc_queries! {
query upstream_monomorphizations_for(def_id: DefId)
-> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>>
{
- arena_cache
desc { |tcx|
"collecting available upstream monomorphizations for `{}`",
tcx.def_path_str(def_id),
@@ -1547,7 +1600,7 @@ rustc_queries! {
}
/// Returns a list of all `extern` blocks of a crate.
- query foreign_modules(_: CrateNum) -> FxHashMap<DefId, ForeignModule> {
+ query foreign_modules(_: CrateNum) -> &'tcx FxHashMap<DefId, ForeignModule> {
arena_cache
desc { "looking up the foreign modules of a linked crate" }
separate_provide_extern
@@ -1581,7 +1634,7 @@ rustc_queries! {
/// Gets the extra data to put in each output filename for a crate.
/// For example, compiling the `foo` crate with `extra-filename=-a` creates a `libfoo-b.rlib` file.
- query extra_filename(_: CrateNum) -> String {
+ query extra_filename(_: CrateNum) -> &'tcx String {
arena_cache
eval_always
desc { "looking up the extra filename for a crate" }
@@ -1589,7 +1642,7 @@ rustc_queries! {
}
/// Gets the paths where the crate came from in the file system.
- query crate_extern_paths(_: CrateNum) -> Vec<PathBuf> {
+ query crate_extern_paths(_: CrateNum) -> &'tcx Vec<PathBuf> {
arena_cache
eval_always
desc { "looking up the paths for extern crates" }
@@ -1619,16 +1672,16 @@ rustc_queries! {
/// Does lifetime resolution on items. Importantly, we can't resolve
/// lifetimes directly on things like trait methods, because of trait params.
- /// See `rustc_resolve::late::lifetimes for details.
- query resolve_lifetimes(_: hir::OwnerId) -> ResolveLifetimes {
+ /// See `rustc_resolve::late::lifetimes` for details.
+ query resolve_bound_vars(_: hir::OwnerId) -> &'tcx ResolveBoundVars {
arena_cache
desc { "resolving lifetimes" }
}
- query named_region_map(_: hir::OwnerId) ->
- Option<&'tcx FxHashMap<ItemLocalId, Region>> {
+ query named_variable_map(_: hir::OwnerId) ->
+ Option<&'tcx FxHashMap<ItemLocalId, ResolvedArg>> {
desc { "looking up a named region" }
}
- query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxIndexSet<LocalDefId>> {
+ query is_late_bound_map(_: hir::OwnerId) -> Option<&'tcx FxIndexSet<ItemLocalId>> {
desc { "testing if a region is late bound" }
}
/// For a given item's generic parameter, gets the default lifetimes to be used
@@ -1660,6 +1713,7 @@ rustc_queries! {
query visibility(def_id: DefId) -> ty::Visibility<DefId> {
desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
separate_provide_extern
+ feedable
}
query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> {
@@ -1691,7 +1745,7 @@ rustc_queries! {
desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
}
- query lib_features(_: ()) -> LibFeatures {
+ query lib_features(_: ()) -> &'tcx LibFeatures {
arena_cache
desc { "calculating the lib features map" }
}
@@ -1699,7 +1753,7 @@ rustc_queries! {
desc { "calculating the lib features defined in a crate" }
separate_provide_extern
}
- query stability_implications(_: CrateNum) -> FxHashMap<Symbol, Symbol> {
+ query stability_implications(_: CrateNum) -> &'tcx FxHashMap<Symbol, Symbol> {
arena_cache
desc { "calculating the implications between `#[unstable]` features defined in a crate" }
separate_provide_extern
@@ -1710,14 +1764,14 @@ rustc_queries! {
separate_provide_extern
}
/// Returns the lang items defined in another crate by loading it from metadata.
- query get_lang_items(_: ()) -> LanguageItems {
+ query get_lang_items(_: ()) -> &'tcx LanguageItems {
arena_cache
eval_always
desc { "calculating the lang items map" }
}
/// Returns all diagnostic items defined in all crates.
- query all_diagnostic_items(_: ()) -> rustc_hir::diagnostic_items::DiagnosticItems {
+ query all_diagnostic_items(_: ()) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems {
arena_cache
eval_always
desc { "calculating the diagnostic items map" }
@@ -1730,7 +1784,7 @@ rustc_queries! {
}
/// Returns the diagnostic items defined in a crate.
- query diagnostic_items(_: CrateNum) -> rustc_hir::diagnostic_items::DiagnosticItems {
+ query diagnostic_items(_: CrateNum) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems {
arena_cache
desc { "calculating the diagnostic items map in a crate" }
separate_provide_extern
@@ -1740,11 +1794,11 @@ rustc_queries! {
desc { "calculating the missing lang items in a crate" }
separate_provide_extern
}
- query visible_parent_map(_: ()) -> DefIdMap<DefId> {
+ query visible_parent_map(_: ()) -> &'tcx DefIdMap<DefId> {
arena_cache
desc { "calculating the visible parent map" }
}
- query trimmed_def_paths(_: ()) -> FxHashMap<DefId, Symbol> {
+ query trimmed_def_paths(_: ()) -> &'tcx FxHashMap<DefId, Symbol> {
arena_cache
desc { "calculating trimmed def paths" }
}
@@ -1753,14 +1807,14 @@ rustc_queries! {
desc { "seeing if we're missing an `extern crate` item for this crate" }
separate_provide_extern
}
- query used_crate_source(_: CrateNum) -> Lrc<CrateSource> {
+ query used_crate_source(_: CrateNum) -> &'tcx Lrc<CrateSource> {
arena_cache
eval_always
desc { "looking at the source for a crate" }
separate_provide_extern
}
/// Returns the debugger visualizers defined for this crate.
- query debugger_visualizers(_: CrateNum) -> Vec<rustc_span::DebuggerVisualizerFile> {
+ query debugger_visualizers(_: CrateNum) -> &'tcx Vec<rustc_span::DebuggerVisualizerFile> {
arena_cache
desc { "looking up the debugger visualizers for this crate" }
separate_provide_extern
@@ -1791,14 +1845,11 @@ rustc_queries! {
query maybe_unused_trait_imports(_: ()) -> &'tcx FxIndexSet<LocalDefId> {
desc { "fetching potentially unused trait imports" }
}
- query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] {
- desc { "looking up all possibly unused extern crates" }
- }
query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxHashSet<Symbol> {
desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
}
- query stability_index(_: ()) -> stability::Index {
+ query stability_index(_: ()) -> &'tcx stability::Index {
arena_cache
eval_always
desc { "calculating the stability index for the local crate" }
@@ -1815,6 +1866,11 @@ rustc_queries! {
separate_provide_extern
}
+ query trait_impls_in_crate(_: CrateNum) -> &'tcx [DefId] {
+ desc { "fetching all trait impls in a crate" }
+ separate_provide_extern
+ }
+
/// The list of symbols exported from the given crate.
///
/// - All names contained in `exported_symbols(cnum)` are guaranteed to
@@ -1865,6 +1921,7 @@ rustc_queries! {
query output_filenames(_: ()) -> &'tcx Arc<OutputFilenames> {
feedable
desc { "getting output filenames" }
+ arena_cache
}
/// Do not call this query directly: invoke `normalize` instead.
@@ -2034,7 +2091,7 @@ rustc_queries! {
remap_env_constness
}
- query supported_target_features(_: CrateNum) -> FxHashMap<String, Option<Symbol>> {
+ query supported_target_features(_: CrateNum) -> &'tcx FxHashMap<String, Option<Symbol>> {
arena_cache
eval_always
desc { "looking up supported target features" }
@@ -2051,6 +2108,18 @@ rustc_queries! {
desc { "looking up enabled feature gates" }
}
+ query metadata_loader((): ()) -> &'tcx Steal<Box<rustc_session::cstore::MetadataLoaderDyn>> {
+ feedable
+ no_hash
+ desc { "raw operations for metadata file access" }
+ }
+
+ query crate_for_resolver((): ()) -> &'tcx Steal<rustc_ast::ast::Crate> {
+ feedable
+ no_hash
+ desc { "the ast before macro expansion and name resolution" }
+ }
+
/// Attempt to resolve the given `DefId` to an `Instance`, for the
/// given generics args (`SubstsRef`), returning one of:
/// * `Ok(Some(instance))` on success
@@ -2093,34 +2162,31 @@ rustc_queries! {
/// span) for an *existing* error. Therefore, it is best-effort, and may never handle
/// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine,
/// because the `ty::Ty`-based wfcheck is always run.
- query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, traits::WellFormedLoc)) -> Option<traits::ObligationCause<'tcx>> {
+ query diagnostic_hir_wf_check(
+ key: (ty::Predicate<'tcx>, traits::WellFormedLoc)
+ ) -> &'tcx Option<traits::ObligationCause<'tcx>> {
arena_cache
eval_always
no_hash
desc { "performing HIR wf-checking for predicate `{:?}` at item `{:?}`", key.0, key.1 }
}
-
/// The list of backend features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
/// `--target` and similar).
- query global_backend_features(_: ()) -> Vec<String> {
+ query global_backend_features(_: ()) -> &'tcx Vec<String> {
arena_cache
eval_always
desc { "computing the backend features for CLI flags" }
}
- query generator_diagnostic_data(key: DefId) -> Option<GeneratorDiagnosticData<'tcx>> {
+ query generator_diagnostic_data(key: DefId) -> &'tcx Option<GeneratorDiagnosticData<'tcx>> {
arena_cache
desc { |tcx| "looking up generator diagnostic data of `{}`", tcx.def_path_str(key) }
separate_provide_extern
}
- query permits_uninit_init(key: TyAndLayout<'tcx>) -> bool {
- desc { "checking to see if `{}` permits being left uninit", key.ty }
- }
-
- query permits_zero_init(key: TyAndLayout<'tcx>) -> bool {
- desc { "checking to see if `{}` permits being left zeroed", key.ty }
+ query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, ty::layout::LayoutError<'tcx>> {
+ desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 }
}
query compare_impl_const(
@@ -2133,4 +2199,23 @@ rustc_queries! {
desc { |tcx| "deducing parameter attributes for {}", tcx.def_path_str(def_id) }
separate_provide_extern
}
+
+ query doc_link_resolutions(def_id: DefId) -> &'tcx DocLinkResMap {
+ eval_always
+ desc { "resolutions for documentation links for a module" }
+ separate_provide_extern
+ }
+
+ query doc_link_traits_in_scope(def_id: DefId) -> &'tcx [DefId] {
+ eval_always
+ desc { "traits in scope for documentation links for a module" }
+ separate_provide_extern
+ }
+
+ /// Used in `super_combine_consts` to ICE if the type of the two consts are definitely not going to end up being
+ /// equal to eachother. This might return `Ok` even if the types are unequal, but will never return `Err` if
+ /// the types might be equal.
+ query check_tys_might_be_eq(arg: Canonical<'tcx, (ty::ParamEnv<'tcx>, Ty<'tcx>, Ty<'tcx>)>) -> Result<(), NoSolution> {
+ desc { "check whether two const param are definitely not equal to eachother"}
+ }
}
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 5f320708c..3b11fab8c 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::AllocId;
use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts};
+use rustc_middle::ty::{self, AdtDef, FnSig, Ty, UpvarSubsts};
use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
@@ -32,7 +32,12 @@ use std::ops::Index;
pub mod visit;
macro_rules! thir_with_elements {
- ($($name:ident: $id:ty => $value:ty => $format:literal,)*) => {
+ (
+ $($field_name:ident: $field_ty:ty,)*
+
+ @elements:
+ $($name:ident: $id:ty => $value:ty => $format:literal,)*
+ ) => {
$(
newtype_index! {
#[derive(HashStable)]
@@ -47,14 +52,20 @@ macro_rules! thir_with_elements {
#[derive(Debug, HashStable, Clone)]
pub struct Thir<'tcx> {
$(
+ pub $field_name: $field_ty,
+ )*
+ $(
pub $name: IndexVec<$id, $value>,
)*
}
impl<'tcx> Thir<'tcx> {
- pub fn new() -> Thir<'tcx> {
+ pub fn new($($field_name: $field_ty,)*) -> Thir<'tcx> {
Thir {
$(
+ $field_name,
+ )*
+ $(
$name: IndexVec::new(),
)*
}
@@ -75,6 +86,9 @@ macro_rules! thir_with_elements {
pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
thir_with_elements! {
+ body_type: BodyTy<'tcx>,
+
+@elements:
arms: ArmId => Arm<'tcx> => "a{}",
blocks: BlockId => Block => "b{}",
exprs: ExprId => Expr<'tcx> => "e{}",
@@ -82,6 +96,12 @@ thir_with_elements! {
params: ParamId => Param<'tcx> => "p{}",
}
+#[derive(Debug, HashStable, Clone)]
+pub enum BodyTy<'tcx> {
+ Const(Ty<'tcx>),
+ Fn(FnSig<'tcx>),
+}
+
/// Description of a type-checked function parameter.
#[derive(Clone, Debug, HashStable)]
pub struct Param<'tcx> {
@@ -217,6 +237,9 @@ pub struct LocalVarId(pub hir::HirId);
/// A THIR expression.
#[derive(Clone, Debug, HashStable)]
pub struct Expr<'tcx> {
+ /// kind of expression
+ pub kind: ExprKind<'tcx>,
+
/// The type of this expression
pub ty: Ty<'tcx>,
@@ -226,9 +249,6 @@ pub struct Expr<'tcx> {
/// span of the expression in the source
pub span: Span,
-
- /// kind of expression
- pub kind: ExprKind<'tcx>,
}
#[derive(Clone, Debug, HashStable)]
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index d00b26a5a..6231dd9b6 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -5,6 +5,7 @@
mod chalk;
pub mod query;
pub mod select;
+pub mod solve;
pub mod specialization_graph;
mod structural_impls;
pub mod util;
@@ -18,7 +19,8 @@ use crate::ty::{self, AdtKind, Ty, TyCtxt};
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, Diagnostic};
use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
+use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use smallvec::SmallVec;
@@ -36,7 +38,7 @@ pub use self::chalk::{ChalkEnvironmentAndGoal, RustInterner as ChalkRustInterner
/// Depending on the stage of compilation, we want projection to be
/// more or less conservative.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable, Encodable, Decodable)]
pub enum Reveal {
/// At type-checking time, we refuse to project any associated
/// type that is marked `default`. Non-`default` ("final") types
@@ -89,7 +91,8 @@ pub enum Reveal {
///
/// We do not want to intern this as there are a lot of obligation causes which
/// only live for a short period of time.
-#[derive(Clone, Debug, PartialEq, Eq, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub struct ObligationCause<'tcx> {
pub span: Span,
@@ -99,7 +102,7 @@ pub struct ObligationCause<'tcx> {
/// (in particular, closures can add new assumptions). See the
/// field `region_obligations` of the `FulfillmentContext` for more
/// information.
- pub body_id: hir::HirId,
+ pub body_id: LocalDefId,
code: InternedObligationCauseCode<'tcx>,
}
@@ -120,13 +123,13 @@ impl<'tcx> ObligationCause<'tcx> {
#[inline]
pub fn new(
span: Span,
- body_id: hir::HirId,
+ body_id: LocalDefId,
code: ObligationCauseCode<'tcx>,
) -> ObligationCause<'tcx> {
ObligationCause { span, body_id, code: code.into() }
}
- pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> {
+ pub fn misc(span: Span, body_id: LocalDefId) -> ObligationCause<'tcx> {
ObligationCause::new(span, body_id, MiscObligation)
}
@@ -137,7 +140,7 @@ impl<'tcx> ObligationCause<'tcx> {
#[inline(always)]
pub fn dummy_with_span(span: Span) -> ObligationCause<'tcx> {
- ObligationCause { span, body_id: hir::CRATE_HIR_ID, code: Default::default() }
+ ObligationCause { span, body_id: CRATE_DEF_ID, code: Default::default() }
}
pub fn span(&self) -> Span {
@@ -196,14 +199,16 @@ impl<'tcx> ObligationCause<'tcx> {
}
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub struct UnifyReceiverContext<'tcx> {
pub assoc_item: ty::AssocItem,
pub param_env: ty::ParamEnv<'tcx>,
pub substs: SubstsRef<'tcx>,
}
-#[derive(Clone, PartialEq, Eq, Hash, Lift, Default)]
+#[derive(Clone, PartialEq, Eq, Hash, Lift, Default, HashStable)]
+#[derive(TypeVisitable, TypeFoldable, TyEncodable, TyDecodable)]
pub struct InternedObligationCauseCode<'tcx> {
/// `None` for `ObligationCauseCode::MiscObligation` (a common case, occurs ~60% of
/// the time). `Some` otherwise.
@@ -238,7 +243,8 @@ impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> {
}
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub enum ObligationCauseCode<'tcx> {
/// Not well classified or should be obvious from the span.
MiscObligation,
@@ -446,7 +452,8 @@ pub enum ObligationCauseCode<'tcx> {
/// This information is used to obtain an `hir::Ty`, which
/// we can walk in order to obtain precise spans for any
/// 'nested' types (e.g. `Foo` in `Option<Foo>`).
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, Encodable, Decodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub enum WellFormedLoc {
/// Use the type of the provided definition.
Ty(LocalDefId),
@@ -463,10 +470,17 @@ pub enum WellFormedLoc {
},
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub struct ImplDerivedObligationCause<'tcx> {
pub derived: DerivedObligationCause<'tcx>,
- pub impl_def_id: DefId,
+ /// The `DefId` of the `impl` that gave rise to the `derived` obligation.
+ /// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
+ /// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
+ /// that exceptional case where appropriate.
+ pub impl_or_alias_def_id: DefId,
+ /// The index of the derived predicate in the parent impl's predicates.
+ pub impl_def_predicate_index: Option<usize>,
pub span: Span,
}
@@ -517,7 +531,8 @@ impl<'tcx> ty::Lift<'tcx> for StatementAsExpression {
}
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub struct MatchExpressionArmCause<'tcx> {
pub arm_block_id: Option<hir::HirId>,
pub arm_ty: Ty<'tcx>,
@@ -533,7 +548,7 @@ pub struct MatchExpressionArmCause<'tcx> {
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-#[derive(Lift, TypeFoldable, TypeVisitable)]
+#[derive(Lift, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
pub struct IfExpressionCause<'tcx> {
pub then_id: hir::HirId,
pub else_id: hir::HirId,
@@ -543,7 +558,8 @@ pub struct IfExpressionCause<'tcx> {
pub opt_suggest_box_span: Option<Span>,
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub struct DerivedObligationCause<'tcx> {
/// The trait predicate of the parent obligation that led to the
/// current obligation. Note that only trait obligations lead to
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 615154a55..c4f871875 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -14,7 +14,7 @@ use rustc_span::source_map::Span;
pub mod type_op {
use crate::ty::fold::TypeFoldable;
- use crate::ty::{Predicate, Ty, UserType};
+ use crate::ty::{Predicate, Ty, TyCtxt, UserType};
use std::fmt;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)]
@@ -64,7 +64,7 @@ pub mod type_op {
impl<'tcx, T> Normalize<T>
where
- T: fmt::Debug + TypeFoldable<'tcx>,
+ T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>>,
{
pub fn new(value: T) -> Self {
Self { value }
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
new file mode 100644
index 000000000..bd43867a3
--- /dev/null
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -0,0 +1,66 @@
+use std::ops::ControlFlow;
+
+use rustc_data_structures::intern::Interned;
+
+use crate::infer::canonical::QueryRegionConstraints;
+use crate::ty::{
+ FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
+};
+
+#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
+pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>);
+
+impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
+ type Target = ExternalConstraintsData<'tcx>;
+
+ fn deref(&self) -> &Self::Target {
+ &*self.0
+ }
+}
+
+/// Additional constraints returned on success.
+#[derive(Debug, PartialEq, Eq, Clone, Hash, Default, TypeFoldable, TypeVisitable)]
+pub struct ExternalConstraintsData<'tcx> {
+ // FIXME: implement this.
+ pub region_constraints: QueryRegionConstraints<'tcx>,
+ pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
+}
+
+// FIXME: Having to clone `region_constraints` for folding feels bad and
+// probably isn't great wrt performance.
+//
+// Not sure how to fix this, maybe we should also intern `opaque_types` and
+// `region_constraints` here or something.
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ Ok(FallibleTypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData {
+ region_constraints: self.region_constraints.clone().try_fold_with(folder)?,
+ opaque_types: self
+ .opaque_types
+ .iter()
+ .map(|opaque| opaque.try_fold_with(folder))
+ .collect::<Result<_, F::Error>>()?,
+ }))
+ }
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ TypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData {
+ region_constraints: self.region_constraints.clone().fold_with(folder),
+ opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(),
+ })
+ }
+}
+
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> std::ops::ControlFlow<V::BreakTy> {
+ self.region_constraints.visit_with(visitor)?;
+ self.opaque_types.visit_with(visitor)?;
+ ControlFlow::Continue(())
+ }
+}
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index aad5b2fbe..c016f7227 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -1,6 +1,6 @@
use crate::error::StrictCoherenceNeedsNegativeCoherence;
use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::visit::TypeVisitable;
+use crate::ty::visit::TypeVisitableExt;
use crate::ty::{self, TyCtxt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed;
@@ -133,11 +133,7 @@ impl Node {
///
/// If this returns `None`, the item can potentially still be found in
/// parents of this node.
- pub fn item<'tcx>(
- &self,
- tcx: TyCtxt<'tcx>,
- trait_item_def_id: DefId,
- ) -> Option<&'tcx ty::AssocItem> {
+ pub fn item<'tcx>(&self, tcx: TyCtxt<'tcx>, trait_item_def_id: DefId) -> Option<ty::AssocItem> {
match *self {
Node::Trait(_) => Some(tcx.associated_item(trait_item_def_id)),
Node::Impl(impl_def_id) => {
@@ -239,7 +235,7 @@ impl<'tcx> Ancestors<'tcx> {
}
}
- Some(LeafDef { item: *item, defining_node: node, finalizing_node })
+ Some(LeafDef { item, defining_node: node, finalizing_node })
} else {
// Item not mentioned. This "finalizes" any defaulted item provided by an ancestor.
finalizing_node = Some(node);
@@ -263,7 +259,7 @@ pub fn ancestors(
if let Some(reported) = specialization_graph.has_errored {
Err(reported)
- } else if let Err(reported) = tcx.type_of(start_from_impl).error_reported() {
+ } else if let Err(reported) = tcx.type_of(start_from_impl).subst_identity().error_reported() {
Err(reported)
} else {
Ok(Ancestors {
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index b9c5a4e0d..df9aa765d 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -89,9 +89,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
Err(TypeError::Sorts(relate::expected_found(self, a, b)))
}
- (&ty::Error(guar), _) | (_, &ty::Error(guar)) => {
- Ok(self.tcx().ty_error_with_guaranteed(guar))
- }
+ (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(self.tcx().ty_error(guar)),
_ => relate::super_relate_tys(self, a, b),
}
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index 5de758ad9..f889ce827 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -1,7 +1,7 @@
//! A subset of a mir body used for const evaluatability checking.
use crate::ty::{
self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
- TypeVisitable,
+ TypeVisitableExt,
};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
@@ -48,13 +48,13 @@ impl<'tcx> TyCtxt<'tcx> {
Ok(ac?.map(|ac| EarlyBinder(ac)))
}
- pub fn expand_abstract_consts<T: TypeFoldable<'tcx>>(self, ac: T) -> T {
+ pub fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, ac: T) -> T {
struct Expander<'tcx> {
tcx: TyCtxt<'tcx>,
}
- impl<'tcx> TypeFolder<'tcx> for Expander<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Expander<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index d3d667f68..ec21030b3 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -54,7 +54,7 @@ bitflags! {
/// The definition of a user-defined type, e.g., a `struct`, `enum`, or `union`.
///
-/// These are all interned (by `alloc_adt_def`) into the global arena.
+/// These are all interned (by `mk_adt_def`) into the global arena.
///
/// The initialism *ADT* stands for an [*algebraic data type (ADT)*][adt].
/// This is slightly wrong because `union`s are not ADTs.
@@ -188,7 +188,7 @@ impl<'tcx> AdtDef<'tcx> {
}
}
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable, TyEncodable, TyDecodable)]
pub enum AdtKind {
Struct,
Union,
@@ -406,6 +406,7 @@ impl<'tcx> AdtDef<'tcx> {
}
/// Return the index of `VariantDef` given a variant id.
+ #[inline]
pub fn variant_index_with_id(self, vid: DefId) -> VariantIdx {
self.variants()
.iter_enumerated()
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index bb7fba3ee..f1a9e50a4 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -79,11 +79,11 @@ impl AssocItem {
// late-bound regions, and we don't want method signatures to show up
// `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()
+ tcx.fn_sig(self.def_id).subst_identity().skip_binder().to_string()
}
ty::AssocKind::Type => format!("type {};", self.name),
ty::AssocKind::Const => {
- format!("const {}: {:?};", self.name, tcx.type_of(self.def_id))
+ format!("const {}: {:?};", self.name, tcx.type_of(self.def_id).subst_identity())
}
}
}
@@ -129,13 +129,13 @@ impl std::fmt::Display for AssocKind {
/// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is
/// done only on items with the same name.
#[derive(Debug, Clone, PartialEq, HashStable)]
-pub struct AssocItems<'tcx> {
- pub(super) items: SortedIndexMultiMap<u32, Symbol, &'tcx ty::AssocItem>,
+pub struct AssocItems {
+ items: SortedIndexMultiMap<u32, Symbol, ty::AssocItem>,
}
-impl<'tcx> AssocItems<'tcx> {
+impl AssocItems {
/// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order.
- pub fn new(items_in_def_order: impl IntoIterator<Item = &'tcx ty::AssocItem>) -> Self {
+ pub fn new(items_in_def_order: impl IntoIterator<Item = ty::AssocItem>) -> Self {
let items = items_in_def_order.into_iter().map(|item| (item.name, item)).collect();
AssocItems { items }
}
@@ -145,7 +145,7 @@ impl<'tcx> AssocItems<'tcx> {
/// New code should avoid relying on definition order. If you need a particular associated item
/// for a known trait, make that trait a lang item instead of indexing this array.
pub fn in_definition_order(&self) -> impl '_ + Iterator<Item = &ty::AssocItem> {
- self.items.iter().map(|(_, v)| *v)
+ self.items.iter().map(|(_, v)| v)
}
pub fn len(&self) -> usize {
@@ -157,7 +157,7 @@ impl<'tcx> AssocItems<'tcx> {
&self,
name: Symbol,
) -> impl '_ + Iterator<Item = &ty::AssocItem> {
- self.items.get_by_key(name).copied()
+ self.items.get_by_key(name)
}
/// Returns the associated item with the given name and `AssocKind`, if one exists.
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 6ade8935f..dc2bd54b7 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -5,10 +5,10 @@ use crate::{mir, ty};
use std::fmt::Write;
-use hir::LangItem;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::{self as hir, LangItem};
+use rustc_span::symbol::Ident;
use rustc_span::{Span, Symbol};
use super::{Ty, TyCtxt};
@@ -129,6 +129,9 @@ impl<'tcx> ClosureKind {
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct CapturedPlace<'tcx> {
+ /// Name and span where the binding happens.
+ pub var_ident: Ident,
+
/// The `Place` that is captured.
pub place: HirPlace<'tcx>,
@@ -148,12 +151,8 @@ impl<'tcx> CapturedPlace<'tcx> {
}
/// Returns a symbol of the captured upvar, which looks like `name__field1__field2`.
- fn to_symbol(&self, tcx: TyCtxt<'tcx>) -> Symbol {
- let hir_id = match self.place.base {
- HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
- base => bug!("Expected an upvar, found {:?}", base),
- };
- let mut symbol = tcx.hir().name(hir_id).as_str().to_string();
+ pub fn to_symbol(&self) -> Symbol {
+ let mut symbol = self.var_ident.to_string();
let mut ty = self.place.base_ty;
for proj in self.place.projections.iter() {
@@ -169,11 +168,7 @@ impl<'tcx> CapturedPlace<'tcx> {
.unwrap();
}
ty => {
- span_bug!(
- self.get_capture_kind_span(tcx),
- "Unexpected type {:?} for `Field` projection",
- ty
- )
+ bug!("Unexpected type {:?} for `Field` projection", ty)
}
},
@@ -238,10 +233,39 @@ impl<'tcx> CapturedPlace<'tcx> {
}
}
-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()
+#[derive(Copy, Clone, Debug, HashStable)]
+pub struct ClosureTypeInfo<'tcx> {
+ user_provided_sig: ty::CanonicalPolyFnSig<'tcx>,
+ captures: &'tcx [&'tcx ty::CapturedPlace<'tcx>],
+ kind_origin: Option<&'tcx (Span, HirPlace<'tcx>)>,
+}
+
+fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo<'tcx> {
+ debug_assert!(tcx.is_closure(def.to_def_id()));
+ let typeck_results = tcx.typeck(def);
+ let user_provided_sig = typeck_results.user_provided_sigs[&def];
+ let captures = typeck_results.closure_min_captures_flattened(def);
+ let captures = tcx.arena.alloc_from_iter(captures);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def);
+ let kind_origin = typeck_results.closure_kind_origins().get(hir_id);
+ ClosureTypeInfo { user_provided_sig, captures, kind_origin }
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+ pub fn closure_kind_origin(self, def_id: LocalDefId) -> Option<&'tcx (Span, HirPlace<'tcx>)> {
+ self.closure_typeinfo(def_id).kind_origin
+ }
+
+ pub fn closure_user_provided_sig(self, def_id: LocalDefId) -> ty::CanonicalPolyFnSig<'tcx> {
+ self.closure_typeinfo(def_id).user_provided_sig
+ }
+
+ pub fn closure_captures(self, def_id: LocalDefId) -> &'tcx [&'tcx ty::CapturedPlace<'tcx>] {
+ if !self.is_closure(def_id.to_def_id()) {
+ return &[];
+ };
+ self.closure_typeinfo(def_id).captures
+ }
}
/// Return true if the `proj_possible_ancestor` represents an ancestor path
@@ -434,5 +458,5 @@ impl BorrowKind {
}
pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { symbols_for_closure_captures, ..*providers }
+ *providers = ty::query::Providers { closure_typeinfo, ..*providers }
}
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 8cc8286c1..3ce80e06a 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -157,6 +157,14 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AllocId {
}
}
+impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::ParamEnv<'tcx> {
+ fn encode(&self, e: &mut E) {
+ self.caller_bounds().encode(e);
+ self.reveal().encode(e);
+ self.constness().encode(e);
+ }
+}
+
#[inline]
fn decode_arena_allocable<
'tcx,
@@ -199,7 +207,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Ty<'tcx> {
})
} else {
let tcx = decoder.interner();
- tcx.mk_ty(rustc_type_ir::TyKind::decode(decoder))
+ tcx.mk_ty_from_kind(rustc_type_ir::TyKind::decode(decoder))
}
}
}
@@ -236,7 +244,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for SubstsRef<'tcx> {
fn decode(decoder: &mut D) -> Self {
let len = decoder.read_usize();
let tcx = decoder.interner();
- tcx.mk_substs(
+ tcx.mk_substs_from_iter(
(0..len).map::<ty::subst::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)),
)
}
@@ -246,7 +254,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for mir::Place<'tcx> {
fn decode(decoder: &mut D) -> Self {
let local: mir::Local = Decodable::decode(decoder);
let len = decoder.read_usize();
- let projection = decoder.interner().mk_place_elems(
+ let projection = decoder.interner().mk_place_elems_from_iter(
(0..len).map::<mir::PlaceElem<'tcx>, _>(|_| Decodable::decode(decoder)),
);
mir::Place { local, projection }
@@ -255,16 +263,16 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for mir::Place<'tcx> {
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Region<'tcx> {
fn decode(decoder: &mut D) -> Self {
- decoder.interner().mk_region(Decodable::decode(decoder))
+ decoder.interner().mk_region_from_kind(Decodable::decode(decoder))
}
}
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for CanonicalVarInfos<'tcx> {
fn decode(decoder: &mut D) -> Self {
let len = decoder.read_usize();
- let interned: Vec<CanonicalVarInfo<'tcx>> =
- (0..len).map(|_| Decodable::decode(decoder)).collect();
- decoder.interner().intern_canonical_var_infos(interned.as_slice())
+ decoder.interner().mk_canonical_var_infos_from_iter(
+ (0..len).map::<CanonicalVarInfo<'tcx>, _>(|_| Decodable::decode(decoder)),
+ )
}
}
@@ -280,8 +288,17 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::SymbolName<'tcx>
}
}
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::ParamEnv<'tcx> {
+ fn decode(d: &mut D) -> Self {
+ let caller_bounds = Decodable::decode(d);
+ let reveal = Decodable::decode(d);
+ let constness = Decodable::decode(d);
+ ty::ParamEnv::new(caller_bounds, reveal, constness)
+ }
+}
+
macro_rules! impl_decodable_via_ref {
- ($($t:ty),+) => {
+ ($($t:ty,)+) => {
$(impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for $t {
fn decode(decoder: &mut D) -> Self {
RefDecodable::decode(decoder)
@@ -293,7 +310,9 @@ macro_rules! impl_decodable_via_ref {
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> {
fn decode(decoder: &mut D) -> &'tcx Self {
let len = decoder.read_usize();
- decoder.interner().mk_type_list((0..len).map::<Ty<'tcx>, _>(|_| Decodable::decode(decoder)))
+ decoder
+ .interner()
+ .mk_type_list_from_iter((0..len).map::<Ty<'tcx>, _>(|_| Decodable::decode(decoder)))
}
}
@@ -302,7 +321,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
{
fn decode(decoder: &mut D) -> &'tcx Self {
let len = decoder.read_usize();
- decoder.interner().mk_poly_existential_predicates(
+ decoder.interner().mk_poly_existential_predicates_from_iter(
(0..len).map::<ty::Binder<'tcx, _>, _>(|_| Decodable::decode(decoder)),
)
}
@@ -325,13 +344,13 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [ty::ValTre
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ConstAllocation<'tcx> {
fn decode(decoder: &mut D) -> Self {
- decoder.interner().intern_const_alloc(Decodable::decode(decoder))
+ decoder.interner().mk_const_alloc(Decodable::decode(decoder))
}
}
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AdtDef<'tcx> {
fn decode(decoder: &mut D) -> Self {
- decoder.interner().intern_adt_def(Decodable::decode(decoder))
+ decoder.interner().mk_adt_def_from_data(Decodable::decode(decoder))
}
}
@@ -358,7 +377,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
{
fn decode(decoder: &mut D) -> &'tcx Self {
let len = decoder.read_usize();
- decoder.interner().mk_bound_variable_kinds(
+ decoder.interner().mk_bound_variable_kinds_from_iter(
(0..len).map::<ty::BoundVariableKind, _>(|_| Decodable::decode(decoder)),
)
}
@@ -367,9 +386,18 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Const<'tcx>> {
fn decode(decoder: &mut D) -> &'tcx Self {
let len = decoder.read_usize();
- decoder
- .interner()
- .mk_const_list((0..len).map::<ty::Const<'tcx>, _>(|_| Decodable::decode(decoder)))
+ decoder.interner().mk_const_list_from_iter(
+ (0..len).map::<ty::Const<'tcx>, _>(|_| Decodable::decode(decoder)),
+ )
+ }
+}
+
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Predicate<'tcx>> {
+ fn decode(decoder: &mut D) -> &'tcx Self {
+ let len = decoder.read_usize();
+ decoder.interner().mk_predicates_from_iter(
+ (0..len).map::<ty::Predicate<'tcx>, _>(|_| Decodable::decode(decoder)),
+ )
}
}
@@ -382,7 +410,8 @@ impl_decodable_via_ref! {
&'tcx mir::UnsafetyCheckResult,
&'tcx mir::BorrowCheckResult<'tcx>,
&'tcx mir::coverage::CodeRegion,
- &'tcx ty::List<ty::BoundVariableKind>
+ &'tcx ty::List<ty::BoundVariableKind>,
+ &'tcx ty::List<ty::Predicate<'tcx>>,
}
#[macro_export]
@@ -519,6 +548,8 @@ macro_rules! impl_binder_encode_decode {
impl_binder_encode_decode! {
&'tcx ty::List<Ty<'tcx>>,
ty::FnSig<'tcx>,
+ ty::Predicate<'tcx>,
+ ty::TraitPredicate<'tcx>,
ty::ExistentialPredicate<'tcx>,
ty::TraitRef<'tcx>,
Vec<ty::GeneratorInteriorTypeCause<'tcx>>,
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 65cbac3e8..527ec9f6e 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,7 +1,9 @@
+use crate::middle::resolve_bound_vars as rbv;
use crate::mir::interpret::LitToConstInput;
use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_data_structures::intern::Interned;
use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_macros::HashStable;
use std::fmt;
@@ -14,7 +16,7 @@ pub use int::*;
pub use kind::*;
pub use valtree::*;
-/// Use this rather than `ConstData, 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(super) Interned<'tcx, ConstData<'tcx>>);
@@ -71,7 +73,10 @@ impl<'tcx> Const<'tcx> {
let expr = &tcx.hir().body(body_id).value;
debug!(?expr);
- let ty = tcx.type_of(def.def_id_for_type_of());
+ let ty = tcx
+ .type_of(def.def_id_for_type_of())
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic");
match Self::try_eval_lit_or_param(tcx, ty, expr) {
Some(v) => v,
@@ -125,16 +130,30 @@ impl<'tcx> Const<'tcx> {
}
}
- use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
match expr.kind {
- ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
- // Find the name and index of the const parameter by indexing the generics of
- // the parent item and construct a `ParamConst`.
- let item_def_id = tcx.parent(def_id);
- let generics = tcx.generics_of(item_def_id);
- let index = generics.param_def_id_to_index[&def_id];
- let name = tcx.item_name(def_id);
- Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+ hir::ExprKind::Path(hir::QPath::Resolved(
+ _,
+ &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
+ )) => {
+ match tcx.named_bound_var(expr.hir_id) {
+ Some(rbv::ResolvedArg::EarlyBound(_)) => {
+ // Find the name and index of the const parameter by indexing the generics of
+ // the parent item and construct a `ParamConst`.
+ let item_def_id = tcx.parent(def_id);
+ let generics = tcx.generics_of(item_def_id);
+ let index = generics.param_def_id_to_index[&def_id];
+ let name = tcx.item_name(def_id);
+ Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+ }
+ Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
+ ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
+ ty,
+ )),
+ Some(rbv::ResolvedArg::Error(guar)) => {
+ Some(tcx.const_error_with_guaranteed(ty, guar))
+ }
+ arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
+ }
}
_ => None,
}
@@ -175,7 +194,7 @@ impl<'tcx> Const<'tcx> {
#[inline]
/// Creates an interned usize constant.
- pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
+ pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
}
@@ -201,8 +220,12 @@ impl<'tcx> Const<'tcx> {
}
#[inline]
- pub fn try_eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u64> {
- self.kind().eval(tcx, param_env).try_to_machine_usize(tcx)
+ pub fn try_eval_target_usize(
+ self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ) -> Option<u64> {
+ self.kind().eval(tcx, param_env).try_to_target_usize(tcx)
}
#[inline]
@@ -229,8 +252,8 @@ impl<'tcx> Const<'tcx> {
#[inline]
/// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
- pub fn eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 {
- self.try_eval_usize(tcx, param_env)
+ pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 {
+ self.try_eval_target_usize(tcx, param_env)
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
}
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 48958e0d9..eecd78ab6 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -232,7 +232,7 @@ impl ScalarInt {
}
#[inline]
- pub fn try_to_machine_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
+ pub fn try_to_target_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 d9721863a..560caa041 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -4,7 +4,7 @@ use crate::mir::interpret::{AllocId, ConstValue, Scalar};
use crate::ty::abstract_const::CastKind;
use crate::ty::subst::{InternalSubsts, SubstsRef};
use crate::ty::ParamEnv;
-use crate::ty::{self, List, Ty, TyCtxt, TypeVisitable};
+use crate::ty::{self, List, Ty, TyCtxt, TypeVisitableExt};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
@@ -125,8 +125,8 @@ impl<'tcx> ConstKind<'tcx> {
}
#[inline]
- pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
- self.try_to_value()?.try_to_machine_usize(tcx)
+ pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
+ self.try_to_value()?.try_to_target_usize(tcx)
}
}
@@ -217,23 +217,21 @@ impl<'tcx> ConstKind<'tcx> {
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
// so that we don't try to invoke this query with
// any region variables.
- let param_env_and = tcx
- .erase_regions(param_env)
- .with_reveal_all_normalized(tcx)
- .and(tcx.erase_regions(unevaluated));
// HACK(eddyb) when the query key would contain inference variables,
// attempt using identity substs and `ParamEnv` instead, that will succeed
// when the expression doesn't depend on any parameters.
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
// we can call `infcx.const_eval_resolve` which handles inference variables.
- let param_env_and = if param_env_and.needs_infer() {
+ let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst {
def: unevaluated.def,
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
})
} else {
- param_env_and
+ tcx.erase_regions(param_env)
+ .with_reveal_all_normalized(tcx)
+ .and(tcx.erase_regions(unevaluated))
};
// FIXME(eddyb) maybe the `const_eval_*` methods should take
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index a803fca0d..5ed4af2e9 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -78,8 +78,8 @@ impl<'tcx> ValTree<'tcx> {
}
}
- pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
- self.try_to_scalar_int().map(|s| s.try_to_machine_usize(tcx).ok()).flatten()
+ pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
+ self.try_to_scalar_int().map(|s| s.try_to_target_usize(tcx).ok()).flatten()
}
/// Get the values inside the ValTree as a slice of bytes. This only works for
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index ce04d8d21..d9af2fd74 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2,12 +2,14 @@
#![allow(rustc::usage_of_ty_tykind)]
+pub mod tls;
+
use crate::arena::Arena;
use crate::dep_graph::{DepGraph, DepKindStruct};
-use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
+use crate::infer::canonical::CanonicalVarInfo;
use crate::lint::struct_lint_level;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::resolve_lifetime;
+use crate::middle::resolve_bound_vars;
use crate::middle::stability;
use crate::mir::interpret::{self, Allocation, ConstAllocation};
use crate::mir::{
@@ -15,6 +17,7 @@ use crate::mir::{
};
use crate::thir::Thir;
use crate::traits;
+use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
use crate::ty::query::{self, TyCtxtAt};
use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar,
@@ -33,7 +36,7 @@ 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, WorkerLocal};
+use rustc_data_structures::sync::{self, Lock, Lrc, MappedReadGuard, ReadGuard, WorkerLocal};
use rustc_errors::{
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
};
@@ -64,7 +67,7 @@ use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi;
use rustc_type_ir::sty::TyKind::*;
use rustc_type_ir::WithCachedTypeInfo;
-use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags};
+use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags};
use std::any::Any;
use std::borrow::Borrow;
@@ -75,6 +78,8 @@ use std::iter;
use std::mem;
use std::ops::{Bound, Deref};
+const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
+
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
@@ -95,9 +100,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type AdtDef = ty::AdtDef<'tcx>;
type SubstsRef = ty::SubstsRef<'tcx>;
type DefId = DefId;
+ type Binder<T> = Binder<'tcx, T>;
type Ty = Ty<'tcx>;
type Const = ty::Const<'tcx>;
type Region = Region<'tcx>;
+ type Predicate = Predicate<'tcx>;
type TypeAndMut = TypeAndMut<'tcx>;
type Mutability = hir::Mutability;
type Movability = hir::Movability;
@@ -142,8 +149,9 @@ pub struct CtxtInterners<'tcx> {
const_: InternedSet<'tcx, ConstData<'tcx>>,
const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
- layout: InternedSet<'tcx, LayoutS<VariantIdx>>,
+ layout: InternedSet<'tcx, LayoutS>,
adt_def: InternedSet<'tcx, AdtDefData>,
+ external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
}
impl<'tcx> CtxtInterners<'tcx> {
@@ -165,10 +173,11 @@ impl<'tcx> CtxtInterners<'tcx> {
bound_variable_kinds: Default::default(),
layout: Default::default(),
adt_def: Default::default(),
+ external_constraints: Default::default(),
}
}
- /// Interns a type.
+ /// Interns a type. (Use `mk_*` functions instead, where possible.)
#[allow(rustc::usage_of_ty_tykind)]
#[inline(never)]
fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> {
@@ -208,6 +217,7 @@ impl<'tcx> CtxtInterners<'tcx> {
}
}
+ /// Interns a predicate. (Use `mk_predicate` instead, where possible.)
#[inline(never)]
fn intern_predicate(
&self,
@@ -234,6 +244,20 @@ impl<'tcx> CtxtInterners<'tcx> {
}
}
+// For these preinterned values, an alternative would be to have
+// variable-length vectors that grow as needed. But that turned out to be
+// slightly more complex and no faster.
+
+const NUM_PREINTERNED_TY_VARS: u32 = 100;
+const NUM_PREINTERNED_FRESH_TYS: u32 = 20;
+const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3;
+const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3;
+
+// This number may seem high, but it is reached in all but the smallest crates.
+const NUM_PREINTERNED_RE_VARS: u32 = 500;
+const NUM_PREINTERNED_RE_LATE_BOUNDS_I: u32 = 2;
+const NUM_PREINTERNED_RE_LATE_BOUNDS_V: u32 = 20;
+
pub struct CommonTypes<'tcx> {
pub unit: Ty<'tcx>,
pub bool: Ty<'tcx>,
@@ -259,7 +283,20 @@ pub struct CommonTypes<'tcx> {
/// Dummy type used for the `Self` of a `TraitRef` created for converting
/// a trait object, and which gets removed in `ExistentialTraitRef`.
/// This type must not appear anywhere in other converted types.
+ /// `Infer(ty::FreshTy(0))` does the job.
pub trait_object_dummy_self: Ty<'tcx>,
+
+ /// Pre-interned `Infer(ty::TyVar(n))` for small values of `n`.
+ pub ty_vars: Vec<Ty<'tcx>>,
+
+ /// Pre-interned `Infer(ty::FreshTy(n))` for small values of `n`.
+ pub fresh_tys: Vec<Ty<'tcx>>,
+
+ /// Pre-interned `Infer(ty::FreshIntTy(n))` for small values of `n`.
+ pub fresh_int_tys: Vec<Ty<'tcx>>,
+
+ /// Pre-interned `Infer(ty::FreshFloatTy(n))` for small values of `n`.
+ pub fresh_float_tys: Vec<Ty<'tcx>>,
}
pub struct CommonLifetimes<'tcx> {
@@ -268,6 +305,14 @@ pub struct CommonLifetimes<'tcx> {
/// Erased region, used outside of type inference.
pub re_erased: Region<'tcx>,
+
+ /// Pre-interned `ReVar(ty::RegionVar(n))` for small values of `n`.
+ pub re_vars: Vec<Region<'tcx>>,
+
+ /// Pre-interned values of the form:
+ /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })`
+ /// for small values of `i` and `v`.
+ pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
}
pub struct CommonConsts<'tcx> {
@@ -282,6 +327,15 @@ impl<'tcx> CommonTypes<'tcx> {
) -> CommonTypes<'tcx> {
let mk = |ty| interners.intern_ty(ty, sess, untracked);
+ let ty_vars =
+ (0..NUM_PREINTERNED_TY_VARS).map(|n| mk(Infer(ty::TyVar(TyVid::from(n))))).collect();
+ let fresh_tys: Vec<_> =
+ (0..NUM_PREINTERNED_FRESH_TYS).map(|n| mk(Infer(ty::FreshTy(n)))).collect();
+ let fresh_int_tys: Vec<_> =
+ (0..NUM_PREINTERNED_FRESH_INT_TYS).map(|n| mk(Infer(ty::FreshIntTy(n)))).collect();
+ let fresh_float_tys: Vec<_> =
+ (0..NUM_PREINTERNED_FRESH_FLOAT_TYS).map(|n| mk(Infer(ty::FreshFloatTy(n)))).collect();
+
CommonTypes {
unit: mk(Tuple(List::empty())),
bool: mk(Bool),
@@ -304,7 +358,12 @@ impl<'tcx> CommonTypes<'tcx> {
str_: mk(Str),
self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })),
- trait_object_dummy_self: mk(Infer(ty::FreshTy(0))),
+ trait_object_dummy_self: fresh_tys[0],
+
+ ty_vars,
+ fresh_tys,
+ fresh_int_tys,
+ fresh_float_tys,
}
}
}
@@ -317,7 +376,31 @@ impl<'tcx> CommonLifetimes<'tcx> {
))
};
- CommonLifetimes { re_static: mk(ty::ReStatic), re_erased: mk(ty::ReErased) }
+ let re_vars =
+ (0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect();
+
+ let re_late_bounds = (0..NUM_PREINTERNED_RE_LATE_BOUNDS_I)
+ .map(|i| {
+ (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V)
+ .map(|v| {
+ mk(ty::ReLateBound(
+ ty::DebruijnIndex::from(i),
+ ty::BoundRegion {
+ var: ty::BoundVar::from(v),
+ kind: ty::BrAnon(v, None),
+ },
+ ))
+ })
+ .collect()
+ })
+ .collect();
+
+ CommonLifetimes {
+ re_static: mk(ty::ReStatic),
+ re_erased: mk(ty::ReErased),
+ re_vars,
+ re_late_bounds,
+ }
}
}
@@ -438,7 +521,7 @@ pub struct GlobalCtxt<'tcx> {
pub on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
pub queries: &'tcx dyn query::QueryEngine<'tcx>,
- pub query_caches: query::QueryCaches<'tcx>,
+ pub query_system: query::QuerySystem<'tcx>,
pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
// Internal caches for metadata decoding. No need to track deps on this.
@@ -461,6 +544,18 @@ pub struct GlobalCtxt<'tcx> {
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
}
+impl<'tcx> GlobalCtxt<'tcx> {
+ /// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of
+ /// `f`.
+ pub fn enter<'a: 'tcx, F, R>(&'a self, f: F) -> R
+ where
+ F: FnOnce(TyCtxt<'tcx>) -> R,
+ {
+ let icx = tls::ImplicitCtxt::new(self);
+ tls::enter_context(&icx, || f(icx.tcx))
+ }
+}
+
impl<'tcx> TyCtxt<'tcx> {
/// Expects a body and returns its codegen attributes.
///
@@ -521,21 +616,21 @@ impl<'tcx> TyCtxt<'tcx> {
self.arena.alloc(Steal::new(promoted))
}
- pub fn alloc_adt_def(
+ pub fn mk_adt_def(
self,
did: DefId,
kind: AdtKind,
variants: IndexVec<VariantIdx, ty::VariantDef>,
repr: ReprOptions,
) -> ty::AdtDef<'tcx> {
- self.intern_adt_def(ty::AdtDefData::new(self, did, kind, variants, repr))
+ self.mk_adt_def_from_data(ty::AdtDefData::new(self, did, kind, variants, repr))
}
/// Allocates a read-only byte or string literal for `mir::interpret`.
pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
// Create an allocation that just contains these bytes.
let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes);
- let alloc = self.intern_const_alloc(alloc);
+ let alloc = self.mk_const_alloc(alloc);
self.create_memory_alloc(alloc)
}
@@ -611,7 +706,7 @@ impl<'tcx> TyCtxt<'tcx> {
untracked,
on_disk_cache,
queries,
- query_caches: query::QueryCaches::default(),
+ query_system: Default::default(),
query_kinds,
ty_rcache: Default::default(),
pred_rcache: Default::default(),
@@ -624,13 +719,13 @@ impl<'tcx> TyCtxt<'tcx> {
/// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
#[track_caller]
- pub fn ty_error_with_guaranteed(self, reported: ErrorGuaranteed) -> Ty<'tcx> {
- self.mk_ty(Error(reported))
+ pub fn ty_error(self, reported: ErrorGuaranteed) -> Ty<'tcx> {
+ self.mk_ty_from_kind(Error(reported))
}
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
#[track_caller]
- pub fn ty_error(self) -> Ty<'tcx> {
+ pub fn ty_error_misc(self) -> Ty<'tcx> {
self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported")
}
@@ -639,7 +734,31 @@ impl<'tcx> TyCtxt<'tcx> {
#[track_caller]
pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
let reported = self.sess.delay_span_bug(span, msg);
- self.mk_ty(Error(reported))
+ self.mk_ty_from_kind(Error(reported))
+ }
+
+ /// Constructs a `RegionKind::ReError` lifetime.
+ #[track_caller]
+ pub fn mk_re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> {
+ self.intern_region(ty::ReError(reported))
+ }
+
+ /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` to ensure it
+ /// gets used.
+ #[track_caller]
+ pub fn mk_re_error_misc(self) -> Region<'tcx> {
+ self.mk_re_error_with_message(
+ DUMMY_SP,
+ "RegionKind::ReError constructed but no error reported",
+ )
+ }
+
+ /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
+ /// `msg` to ensure it gets used.
+ #[track_caller]
+ pub fn mk_re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
+ let reported = self.sess.delay_span_bug(span, msg);
+ self.mk_re_error(reported)
}
/// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
@@ -675,8 +794,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
- let cname = self.crate_name(LOCAL_CRATE);
- self.sess.consider_optimizing(cname.as_str(), msg)
+ self.sess.consider_optimizing(|| self.crate_name(LOCAL_CRATE), msg)
}
/// Obtain all lang items of this crate and all dependencies (recursively)
@@ -718,7 +836,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(id) = id.as_local() {
self.definitions_untracked().def_key(id)
} else {
- self.untracked.cstore.def_key(id)
+ self.cstore_untracked().def_key(id)
}
}
@@ -732,7 +850,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(id) = id.as_local() {
self.definitions_untracked().def_path(id)
} else {
- self.untracked.cstore.def_path(id)
+ self.cstore_untracked().def_path(id)
}
}
@@ -742,7 +860,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.cstore.def_path_hash(def_id)
+ self.cstore_untracked().def_path_hash(def_id)
}
}
@@ -751,7 +869,7 @@ impl<'tcx> TyCtxt<'tcx> {
if crate_num == LOCAL_CRATE {
self.sess.local_stable_crate_id()
} else {
- self.untracked.cstore.stable_crate_id(crate_num)
+ self.cstore_untracked().stable_crate_id(crate_num)
}
}
@@ -762,7 +880,7 @@ impl<'tcx> TyCtxt<'tcx> {
if stable_crate_id == self.sess.local_stable_crate_id() {
LOCAL_CRATE
} else {
- self.untracked.cstore.stable_crate_id_to_crate_num(stable_crate_id)
+ self.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id)
}
}
@@ -781,7 +899,7 @@ impl<'tcx> TyCtxt<'tcx> {
} else {
// If this is a DefPathHash from an upstream crate, let the CrateStore map
// it to a DefId.
- let cstore = &*self.untracked.cstore;
+ let cstore = &*self.cstore_untracked();
let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
cstore.def_path_hash_to_def_id(cnum, hash)
}
@@ -795,7 +913,7 @@ impl<'tcx> TyCtxt<'tcx> {
let (crate_name, stable_crate_id) = if def_id.is_local() {
(self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id())
} else {
- let cstore = &*self.untracked.cstore;
+ let cstore = &*self.cstore_untracked();
(cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
};
@@ -893,10 +1011,15 @@ impl<'tcx> TyCtxt<'tcx> {
/// 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.cstore
+ #[inline]
+ pub fn cstore_untracked(self) -> MappedReadGuard<'tcx, CrateStoreDyn> {
+ ReadGuard::map(self.untracked.cstore.read(), |c| &**c)
}
+ /// Give out access to the untracked data without any sanity checks.
+ pub fn untracked(self) -> &'tcx Untracked {
+ &self.untracked
+ }
/// Note that this is *untracked* and should only be used within the query
/// system if the result is otherwise tracked through queries
#[inline]
@@ -908,7 +1031,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// system if the result is otherwise tracked through queries
#[inline]
pub fn source_span_untracked(self, def_id: LocalDefId) -> Span {
- self.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP)
+ self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP)
}
#[inline(always)]
@@ -997,6 +1120,30 @@ impl<'tcx> TyCtxt<'tcx> {
v.0
}
+ /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type and associated alias span when type alias is used
+ pub fn return_type_impl_or_dyn_traits_with_type_alias(
+ self,
+ scope_def_id: LocalDefId,
+ ) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span)> {
+ let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
+ let mut v = TraitObjectVisitor(vec![], self.hir());
+ // when the return type is a type alias
+ if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id)
+ && let hir::TyKind::Path(hir::QPath::Resolved(
+ None,
+ hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind
+ && let Some(local_id) = def_id.as_local()
+ && let Some(alias_ty) = self.hir().get_by_def_id(local_id).alias_ty() // it is type alias
+ && let Some(alias_generics) = self.hir().get_by_def_id(local_id).generics()
+ {
+ v.visit_ty(alias_ty);
+ if !v.0.is_empty() {
+ return Some((v.0, alias_generics.span));
+ }
+ }
+ return None;
+ }
+
pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
// `type_of()` will fail on these (#55796, #86483), so only allow `fn`s or closures.
match self.hir().get_by_def_id(scope_def_id) {
@@ -1007,18 +1154,16 @@ impl<'tcx> TyCtxt<'tcx> {
_ => return None,
}
- let ret_ty = self.type_of(scope_def_id);
+ let ret_ty = self.type_of(scope_def_id).subst_identity();
match ret_ty.kind() {
ty::FnDef(_, _) => {
let sig = ret_ty.fn_sig(self);
let output = self.erase_late_bound_regions(sig.output());
- if output.is_impl_trait() {
+ output.is_impl_trait().then(|| {
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
- Some((output, fn_decl.output.span()))
- } else {
- None
- }
+ (output, fn_decl.output.span())
+ })
}
_ => None,
}
@@ -1049,20 +1194,15 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn caller_location_ty(self) -> Ty<'tcx> {
self.mk_imm_ref(
self.lifetimes.re_static,
- self.bound_type_of(self.require_lang_item(LangItem::PanicLocation, None))
- .subst(self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
+ self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
+ .subst(self, self.mk_substs(&[self.lifetimes.re_static.into()])),
)
}
/// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
pub fn article_and_description(self, def_id: DefId) -> (&'static str, &'static str) {
- match self.def_kind(def_id) {
- DefKind::Generator => match self.generator_kind(def_id).unwrap() {
- rustc_hir::GeneratorKind::Async(..) => ("an", "async closure"),
- rustc_hir::GeneratorKind::Gen => ("a", "generator"),
- },
- def_kind => (def_kind.article(), def_kind.descr(def_id)),
- }
+ let kind = self.def_kind(def_id);
+ (self.def_kind_descr_article(kind, def_id), self.def_kind_descr(kind, def_id))
}
pub fn type_length_limit(self) -> Limit {
@@ -1078,7 +1218,11 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn const_eval_limit(self) -> Limit {
- self.limits(()).const_eval_limit
+ if self.sess.opts.unstable_opts.tiny_const_eval_limit {
+ TINY_CONST_EVAL_LIMIT
+ } else {
+ self.limits(()).const_eval_limit
+ }
}
pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
@@ -1120,13 +1264,12 @@ macro_rules! nop_lift {
impl<'a, 'tcx> Lift<'tcx> for $ty {
type Lifted = $lifted;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
- if tcx.interners.$set.contains_pointer_to(&InternedInSet(&*self.0.0)) {
+ tcx.interners
+ .$set
+ .contains_pointer_to(&InternedInSet(&*self.0.0))
// SAFETY: `self` is interned and therefore valid
// for the entire lifetime of the `TyCtxt`.
- Some(unsafe { mem::transmute(self) })
- } else {
- None
- }
+ .then(|| unsafe { mem::transmute(self) })
}
}
};
@@ -1134,20 +1277,20 @@ macro_rules! nop_lift {
// Can't use the macros as we have reuse the `substs` here.
//
-// See `intern_type_list` for more info.
+// See `mk_type_list` for more info.
impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
type Lifted = &'tcx List<Ty<'tcx>>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
if self.is_empty() {
return Some(List::empty());
}
- if tcx.interners.substs.contains_pointer_to(&InternedInSet(self.as_substs())) {
+
+ tcx.interners
+ .substs
+ .contains_pointer_to(&InternedInSet(self.as_substs()))
// SAFETY: `self` is interned and therefore valid
// for the entire lifetime of the `TyCtxt`.
- Some(unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
- } else {
- None
- }
+ .then(|| unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
}
}
@@ -1159,11 +1302,10 @@ macro_rules! nop_list_lift {
if self.is_empty() {
return Some(List::empty());
}
- if tcx.interners.$set.contains_pointer_to(&InternedInSet(self)) {
- Some(unsafe { mem::transmute(self) })
- } else {
- None
- }
+ tcx.interners
+ .$set
+ .contains_pointer_to(&InternedInSet(self))
+ .then(|| unsafe { mem::transmute(self) })
}
}
};
@@ -1188,178 +1330,6 @@ CloneLiftImpls! { for<'tcx> {
Constness, traits::WellFormedLoc, ImplPolarity, crate::mir::ReturnConstraint,
} }
-pub mod tls {
- use super::{ptr_eq, GlobalCtxt, TyCtxt};
-
- use crate::dep_graph::TaskDepsRef;
- use crate::ty::query;
- use rustc_data_structures::sync::{self, Lock};
- use rustc_errors::Diagnostic;
- use std::mem;
- use thin_vec::ThinVec;
-
- #[cfg(not(parallel_compiler))]
- use std::cell::Cell;
-
- #[cfg(parallel_compiler)]
- use rustc_rayon_core as rayon_core;
-
- /// This is the implicit state of rustc. It contains the current
- /// `TyCtxt` and query. It is updated when creating a local interner or
- /// executing a new query. Whenever there's a `TyCtxt` value available
- /// you should also have access to an `ImplicitCtxt` through the functions
- /// in this module.
- #[derive(Clone)]
- pub struct ImplicitCtxt<'a, 'tcx> {
- /// The current `TyCtxt`.
- pub tcx: TyCtxt<'tcx>,
-
- /// The current query job, if any. This is updated by `JobOwner::start` in
- /// `ty::query::plumbing` when executing a query.
- pub query: Option<query::QueryJobId>,
-
- /// Where to store diagnostics for the current query job, if any.
- /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
- pub diagnostics: Option<&'a Lock<ThinVec<Diagnostic>>>,
-
- /// Used to prevent queries from calling too deeply.
- pub query_depth: usize,
-
- /// The current dep graph task. This is used to add dependencies to queries
- /// when executing them.
- pub task_deps: TaskDepsRef<'a>,
- }
-
- impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
- pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
- let tcx = TyCtxt { gcx };
- ImplicitCtxt {
- tcx,
- query: None,
- diagnostics: None,
- query_depth: 0,
- task_deps: TaskDepsRef::Ignore,
- }
- }
- }
-
- /// Sets Rayon's thread-local variable, which is preserved for Rayon jobs
- /// to `value` during the call to `f`. It is restored to its previous value after.
- /// This is used to set the pointer to the new `ImplicitCtxt`.
- #[cfg(parallel_compiler)]
- #[inline]
- fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
- rayon_core::tlv::with(value, f)
- }
-
- /// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
- /// This is used to get the pointer to the current `ImplicitCtxt`.
- #[cfg(parallel_compiler)]
- #[inline]
- pub fn get_tlv() -> usize {
- rayon_core::tlv::get()
- }
-
- #[cfg(not(parallel_compiler))]
- thread_local! {
- /// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
- static TLV: Cell<usize> = const { Cell::new(0) };
- }
-
- /// Sets TLV to `value` during the call to `f`.
- /// It is restored to its previous value after.
- /// This is used to set the pointer to the new `ImplicitCtxt`.
- #[cfg(not(parallel_compiler))]
- #[inline]
- fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
- let old = get_tlv();
- let _reset = rustc_data_structures::OnDrop(move || TLV.with(|tlv| tlv.set(old)));
- TLV.with(|tlv| tlv.set(value));
- f()
- }
-
- /// Gets the pointer to the current `ImplicitCtxt`.
- #[cfg(not(parallel_compiler))]
- #[inline]
- fn get_tlv() -> usize {
- TLV.with(|tlv| tlv.get())
- }
-
- /// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
- #[inline]
- pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R
- where
- F: FnOnce(&ImplicitCtxt<'a, 'tcx>) -> R,
- {
- set_tlv(context as *const _ as usize, || f(&context))
- }
-
- /// Allows access to the current `ImplicitCtxt` in a closure if one is available.
- #[inline]
- pub fn with_context_opt<F, R>(f: F) -> R
- where
- F: for<'a, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'tcx>>) -> R,
- {
- let context = get_tlv();
- if context == 0 {
- f(None)
- } else {
- // We could get an `ImplicitCtxt` pointer from another thread.
- // Ensure that `ImplicitCtxt` is `Sync`.
- sync::assert_sync::<ImplicitCtxt<'_, '_>>();
-
- unsafe { f(Some(&*(context as *const ImplicitCtxt<'_, '_>))) }
- }
- }
-
- /// Allows access to the current `ImplicitCtxt`.
- /// Panics if there is no `ImplicitCtxt` available.
- #[inline]
- pub fn with_context<F, R>(f: F) -> R
- where
- F: for<'a, 'tcx> FnOnce(&ImplicitCtxt<'a, 'tcx>) -> R,
- {
- with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls")))
- }
-
- /// Allows access to the current `ImplicitCtxt` whose tcx field is the same as the tcx argument
- /// passed in. This means the closure is given an `ImplicitCtxt` with the same `'tcx` lifetime
- /// as the `TyCtxt` passed in.
- /// This will panic if you pass it a `TyCtxt` which is different from the current
- /// `ImplicitCtxt`'s `tcx` field.
- #[inline]
- pub fn with_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R
- where
- F: FnOnce(&ImplicitCtxt<'_, 'tcx>) -> R,
- {
- with_context(|context| unsafe {
- assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
- let context: &ImplicitCtxt<'_, '_> = mem::transmute(context);
- f(context)
- })
- }
-
- /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
- /// Panics if there is no `ImplicitCtxt` available.
- #[inline]
- pub fn with<F, R>(f: F) -> R
- where
- F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
- {
- with_context(|context| f(context.tcx))
- }
-
- /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
- /// The closure is passed None if there is no `ImplicitCtxt` available.
- #[inline]
- pub fn with_opt<F, R>(f: F) -> R
- where
- F: for<'tcx> FnOnce(Option<TyCtxt<'tcx>>) -> R,
- {
- with_context_opt(|opt_context| f(opt_context.map(|context| context.tcx)))
- }
-}
-
macro_rules! sty_debug_print {
($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
// Curious inner module to allow variant names to be used as
@@ -1452,6 +1422,7 @@ impl<'tcx> TyCtxt<'tcx> {
Placeholder,
Generator,
GeneratorWitness,
+ GeneratorWitnessMIR,
Dynamic,
Closure,
Tuple,
@@ -1547,7 +1518,7 @@ impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, List<T>> {
}
macro_rules! direct_interners {
- ($($name:ident: $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => {
+ ($($name:ident: $vis:vis $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => {
$(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> {
fn borrow<'a>(&'a self) -> &'a $ty {
&self.0
@@ -1573,7 +1544,7 @@ macro_rules! direct_interners {
}
impl<'tcx> TyCtxt<'tcx> {
- pub fn $method(self, v: $ty) -> $ret_ty {
+ $vis fn $method(self, v: $ty) -> $ret_ty {
$ret_ctor(Interned::new_unchecked(self.interners.$name.intern(v, |v| {
InternedInSet(self.interners.arena.alloc(v))
}).0))
@@ -1582,36 +1553,47 @@ macro_rules! direct_interners {
}
}
+// Functions with a `mk_` prefix are intended for use outside this file and
+// crate. Functions with an `intern_` prefix are intended for use within this
+// file only, and have a corresponding `mk_` function.
direct_interners! {
- region: mk_region(RegionKind<'tcx>): Region -> Region<'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>,
+ region: intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
+ const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>,
+ const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
+ layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>,
+ adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
+ external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>):
+ ExternalConstraints -> ExternalConstraints<'tcx>,
}
macro_rules! slice_interners {
- ($($field:ident: $method:ident($ty:ty)),+ $(,)?) => (
+ ($($field:ident: $vis:vis $method:ident($ty:ty)),+ $(,)?) => (
impl<'tcx> TyCtxt<'tcx> {
- $(pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
- self.interners.$field.intern_ref(v, || {
- InternedInSet(List::from_arena(&*self.arena, v))
- }).0
+ $($vis fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
+ if v.is_empty() {
+ List::empty()
+ } else {
+ self.interners.$field.intern_ref(v, || {
+ InternedInSet(List::from_arena(&*self.arena, v))
+ }).0
+ }
})+
}
);
}
+// These functions intern slices. They all have a corresponding
+// `mk_foo_from_iter` function that interns an iterator. The slice version
+// should be used when possible, because it's faster.
slice_interners!(
- const_lists: _intern_const_list(Const<'tcx>),
- substs: _intern_substs(GenericArg<'tcx>),
- canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>),
- poly_existential_predicates:
- _intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
- predicates: _intern_predicates(Predicate<'tcx>),
- projs: _intern_projs(ProjectionKind),
- place_elems: _intern_place_elems(PlaceElem<'tcx>),
- bound_variable_kinds: _intern_bound_variable_kinds(ty::BoundVariableKind),
+ const_lists: pub mk_const_list(Const<'tcx>),
+ substs: pub mk_substs(GenericArg<'tcx>),
+ canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
+ poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
+ predicates: intern_predicates(Predicate<'tcx>),
+ projs: pub mk_projs(ProjectionKind),
+ place_elems: pub mk_place_elems(PlaceElem<'tcx>),
+ bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
);
impl<'tcx> TyCtxt<'tcx> {
@@ -1688,24 +1670,18 @@ impl<'tcx> TyCtxt<'tcx> {
unsafety: hir::Unsafety,
) -> PolyFnSig<'tcx> {
sig.map_bound(|s| {
- let params_iter = match s.inputs()[0].kind() {
- ty::Tuple(params) => params.into_iter(),
+ let params = match s.inputs()[0].kind() {
+ ty::Tuple(params) => *params,
_ => bug!(),
};
- self.mk_fn_sig(params_iter, s.output(), s.c_variadic, unsafety, abi::Abi::Rust)
+ self.mk_fn_sig(params, s.output(), s.c_variadic, unsafety, abi::Abi::Rust)
})
}
- /// Same a `self.mk_region(kind)`, but avoids accessing the interners if
- /// `*r == kind`.
- #[inline]
- pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
- if *r == kind { r } else { self.mk_region(kind) }
- }
-
+ // Avoid this in favour of more specific `mk_*` methods, where possible.
#[allow(rustc::usage_of_ty_tykind)]
#[inline]
- pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> {
+ pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> {
self.interners.intern_ty(
st,
self.sess,
@@ -1770,12 +1746,12 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_adt(self, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
// Take a copy of substs so that we own the vectors inside.
- self.mk_ty(Adt(def, substs))
+ self.mk_ty_from_kind(Adt(def, substs))
}
#[inline]
pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> {
- self.mk_ty(Foreign(def_id))
+ self.mk_ty_from_kind(Foreign(def_id))
}
fn mk_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
@@ -1788,11 +1764,11 @@ impl<'tcx> TyCtxt<'tcx> {
ty_param.into()
} else {
assert!(has_default);
- self.bound_type_of(param.def_id).subst(self, substs).into()
+ self.type_of(param.def_id).subst(self, substs).into()
}
}
});
- self.mk_ty(Adt(adt_def, substs))
+ self.mk_ty_from_kind(Adt(adt_def, substs))
}
#[inline]
@@ -1821,12 +1797,12 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
- self.mk_ty(RawPtr(tm))
+ self.mk_ty_from_kind(RawPtr(tm))
}
#[inline]
pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
- self.mk_ty(Ref(r, tm.ty, tm.mutbl))
+ self.mk_ty_from_kind(Ref(r, tm.ty, tm.mutbl))
}
#[inline]
@@ -1851,21 +1827,34 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
- self.mk_ty(Array(ty, ty::Const::from_usize(self, n)))
+ self.mk_ty_from_kind(Array(ty, ty::Const::from_target_usize(self, n)))
+ }
+
+ #[inline]
+ pub fn mk_array_with_const_len(self, ty: Ty<'tcx>, ct: Const<'tcx>) -> Ty<'tcx> {
+ self.mk_ty_from_kind(Array(ty, ct))
}
#[inline]
pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ty(Slice(ty))
+ self.mk_ty_from_kind(Slice(ty))
}
#[inline]
- pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
- self.mk_ty(Tuple(self.intern_type_list(&ts)))
+ pub fn mk_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
+ if ts.is_empty() {
+ self.types.unit
+ } else {
+ self.mk_ty_from_kind(Tuple(self.mk_type_list(&ts)))
+ }
}
- pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
- iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(&ts))))
+ pub fn mk_tup_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>,
+ {
+ T::collect_and_apply(iter, |ts| self.mk_tup(ts))
}
#[inline]
@@ -1882,17 +1871,17 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn mk_fn_def(
self,
def_id: DefId,
- substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> Ty<'tcx> {
- let substs = self.check_substs(def_id, substs);
- self.mk_ty(FnDef(def_id, substs))
+ let substs = self.check_and_mk_substs(def_id, substs);
+ self.mk_ty_from_kind(FnDef(def_id, substs))
}
#[inline(always)]
- fn check_substs(
+ fn check_and_mk_substs(
self,
_def_id: DefId,
- substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> SubstsRef<'tcx> {
let substs = substs.into_iter().map(Into::into);
#[cfg(debug_assertions)]
@@ -1905,12 +1894,12 @@ impl<'tcx> TyCtxt<'tcx> {
substs.collect::<Vec<_>>(),
);
}
- self.mk_substs(substs)
+ self.mk_substs_from_iter(substs)
}
#[inline]
pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
- self.mk_ty(FnPtr(fty))
+ self.mk_ty_from_kind(FnPtr(fty))
}
#[inline]
@@ -1920,21 +1909,21 @@ impl<'tcx> TyCtxt<'tcx> {
reg: ty::Region<'tcx>,
repr: DynKind,
) -> Ty<'tcx> {
- self.mk_ty(Dynamic(obj, reg, repr))
+ self.mk_ty_from_kind(Dynamic(obj, reg, repr))
}
#[inline]
pub fn mk_projection(
self,
item_def_id: DefId,
- substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> Ty<'tcx> {
- self.mk_ty(Alias(ty::Projection, self.mk_alias_ty(item_def_id, substs)))
+ self.mk_alias(ty::Projection, self.mk_alias_ty(item_def_id, substs))
}
#[inline]
pub fn mk_closure(self, closure_id: DefId, closure_substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- self.mk_ty(Closure(closure_id, closure_substs))
+ self.mk_ty_from_kind(Closure(closure_id, closure_substs))
}
#[inline]
@@ -1944,71 +1933,183 @@ impl<'tcx> TyCtxt<'tcx> {
generator_substs: SubstsRef<'tcx>,
movability: hir::Movability,
) -> Ty<'tcx> {
- self.mk_ty(Generator(id, generator_substs, movability))
+ self.mk_ty_from_kind(Generator(id, generator_substs, movability))
}
#[inline]
pub fn mk_generator_witness(self, types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>) -> Ty<'tcx> {
- self.mk_ty(GeneratorWitness(types))
+ self.mk_ty_from_kind(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_substs = self.mk_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))
+ pub fn mk_generator_witness_mir(self, id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
+ self.mk_ty_from_kind(GeneratorWitnessMIR(id, substs))
}
#[inline]
pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> {
- self.mk_const_internal(ty::ConstData { kind: kind.into(), ty })
+ self.intern_const(ty::ConstData { kind: kind.into(), ty })
+ }
+
+ #[inline]
+ pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ self.types
+ .ty_vars
+ .get(v.as_usize())
+ .copied()
+ .unwrap_or_else(|| self.mk_ty_from_kind(Infer(TyVar(v))))
}
#[inline]
pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> {
- self.mk_ty_infer(IntVar(v))
+ self.mk_ty_from_kind(Infer(IntVar(v)))
}
#[inline]
pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> {
- self.mk_ty_infer(FloatVar(v))
+ self.mk_ty_from_kind(Infer(FloatVar(v)))
+ }
+
+ #[inline]
+ pub fn mk_fresh_ty(self, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ self.types
+ .fresh_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshTy(n))))
}
#[inline]
- pub fn mk_ty_infer(self, it: InferTy) -> Ty<'tcx> {
- self.mk_ty(Infer(it))
+ pub fn mk_fresh_int_ty(self, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ self.types
+ .fresh_int_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshIntTy(n))))
+ }
+
+ #[inline]
+ pub fn mk_fresh_float_ty(self, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ self.types
+ .fresh_float_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshFloatTy(n))))
}
#[inline]
pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> {
- self.mk_ty(Param(ParamTy { index, name }))
+ self.mk_ty_from_kind(Param(ParamTy { index, name }))
}
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
match param.kind {
GenericParamDefKind::Lifetime => {
- self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
+ self.mk_re_early_bound(param.to_early_bound_region_data()).into()
}
GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
GenericParamDefKind::Const { .. } => self
.mk_const(
ParamConst { index: param.index, name: param.name },
- self.type_of(param.def_id),
+ self.type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
)
.into(),
}
}
#[inline]
+ pub fn mk_bound(self, index: ty::DebruijnIndex, bound_ty: ty::BoundTy) -> Ty<'tcx> {
+ self.mk_ty_from_kind(Bound(index, bound_ty))
+ }
+
+ #[inline]
+ pub fn mk_placeholder(self, placeholder: ty::PlaceholderType) -> Ty<'tcx> {
+ self.mk_ty_from_kind(Placeholder(placeholder))
+ }
+
+ #[inline]
+ pub fn mk_alias(self, kind: ty::AliasKind, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> {
+ self.mk_ty_from_kind(Alias(kind, alias_ty))
+ }
+
+ #[inline]
pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- self.mk_ty(Alias(ty::Opaque, self.mk_alias_ty(def_id, substs)))
+ self.mk_alias(ty::Opaque, self.mk_alias_ty(def_id, substs))
+ }
+
+ #[inline]
+ pub fn mk_re_early_bound(self, early_bound_region: ty::EarlyBoundRegion) -> Region<'tcx> {
+ self.intern_region(ty::ReEarlyBound(early_bound_region))
+ }
+
+ #[inline]
+ pub fn mk_re_late_bound(
+ self,
+ debruijn: ty::DebruijnIndex,
+ bound_region: ty::BoundRegion,
+ ) -> Region<'tcx> {
+ // Use a pre-interned one when possible.
+ if let ty::BoundRegion { var, kind: ty::BrAnon(v, None) } = bound_region
+ && var.as_u32() == v
+ && let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
+ && let Some(re) = inner.get(v as usize).copied()
+ {
+ re
+ } else {
+ self.intern_region(ty::ReLateBound(debruijn, bound_region))
+ }
+ }
+
+ #[inline]
+ pub fn mk_re_free(self, scope: DefId, bound_region: ty::BoundRegionKind) -> Region<'tcx> {
+ self.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
+ }
+
+ #[inline]
+ pub fn mk_re_var(self, v: ty::RegionVid) -> Region<'tcx> {
+ // Use a pre-interned one when possible.
+ self.lifetimes
+ .re_vars
+ .get(v.as_usize())
+ .copied()
+ .unwrap_or_else(|| self.intern_region(ty::ReVar(v)))
+ }
+
+ #[inline]
+ pub fn mk_re_placeholder(self, placeholder: ty::PlaceholderRegion) -> Region<'tcx> {
+ self.intern_region(ty::RePlaceholder(placeholder))
+ }
+
+ // Avoid this in favour of more specific `mk_re_*` methods, where possible,
+ // to avoid the cost of the `match`.
+ pub fn mk_region_from_kind(self, kind: ty::RegionKind<'tcx>) -> Region<'tcx> {
+ match kind {
+ ty::ReEarlyBound(region) => self.mk_re_early_bound(region),
+ ty::ReLateBound(debruijn, region) => self.mk_re_late_bound(debruijn, region),
+ ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
+ self.mk_re_free(scope, bound_region)
+ }
+ ty::ReStatic => self.lifetimes.re_static,
+ ty::ReVar(vid) => self.mk_re_var(vid),
+ ty::RePlaceholder(region) => self.mk_re_placeholder(region),
+ ty::ReErased => self.lifetimes.re_erased,
+ ty::ReError(reported) => self.mk_re_error(reported),
+ }
}
pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
@@ -2050,10 +2151,10 @@ impl<'tcx> TyCtxt<'tcx> {
let mut projection = place.projection.to_vec();
projection.push(elem);
- Place { local: place.local, projection: self.intern_place_elems(&projection) }
+ Place { local: place.local, projection: self.mk_place_elems(&projection) }
}
- pub fn intern_poly_existential_predicates(
+ pub fn mk_poly_existential_predicates(
self,
eps: &[PolyExistentialPredicate<'tcx>],
) -> &'tcx List<PolyExistentialPredicate<'tcx>> {
@@ -2063,125 +2164,109 @@ impl<'tcx> TyCtxt<'tcx> {
.all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
!= Ordering::Greater)
);
- self._intern_poly_existential_predicates(eps)
+ self.intern_poly_existential_predicates(eps)
}
- pub fn intern_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
+ pub fn mk_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
// FIXME consider asking the input slice to be sorted to avoid
// re-interning permutations, in which case that would be asserted
// here.
- if preds.is_empty() {
- // The macro-generated method below asserts we don't intern an empty slice.
- List::empty()
- } else {
- self._intern_predicates(preds)
- }
- }
-
- pub fn mk_const_list<I: InternAs<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>>(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_const_list(xs))
- }
-
- pub fn intern_const_list(self, cs: &[ty::Const<'tcx>]) -> &'tcx List<ty::Const<'tcx>> {
- if cs.is_empty() { List::empty() } else { self._intern_const_list(cs) }
- }
-
- pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
- if ts.is_empty() {
- List::empty()
- } else {
- // Actually intern type lists as lists of `GenericArg`s.
- //
- // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
- // as explained in ty_slice_as_generic_arg`. With this,
- // we guarantee that even when transmuting between `List<Ty<'tcx>>`
- // and `List<GenericArg<'tcx>>`, the uniqueness requirement for
- // lists is upheld.
- let substs = self._intern_substs(ty::subst::ty_slice_as_generic_args(ts));
- substs.try_as_type_list().unwrap()
- }
- }
-
- pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List<GenericArg<'tcx>> {
- if ts.is_empty() { List::empty() } else { self._intern_substs(ts) }
+ self.intern_predicates(preds)
}
- pub fn intern_projs(self, ps: &[ProjectionKind]) -> &'tcx List<ProjectionKind> {
- if ps.is_empty() { List::empty() } else { self._intern_projs(ps) }
- }
-
- pub fn intern_place_elems(self, ts: &[PlaceElem<'tcx>]) -> &'tcx List<PlaceElem<'tcx>> {
- if ts.is_empty() { List::empty() } else { self._intern_place_elems(ts) }
- }
-
- pub fn intern_canonical_var_infos(
- self,
- ts: &[CanonicalVarInfo<'tcx>],
- ) -> CanonicalVarInfos<'tcx> {
- if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) }
- }
-
- pub fn intern_bound_variable_kinds(
- self,
- ts: &[ty::BoundVariableKind],
- ) -> &'tcx List<ty::BoundVariableKind> {
- if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) }
+ pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_const_list(xs))
}
- pub fn mk_fn_sig<I>(
+ pub fn mk_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
+ // Actually intern type lists as lists of `GenericArg`s.
+ //
+ // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
+ // as explained in `ty_slice_as_generic_arg`. With this,
+ // we guarantee that even when transmuting between `List<Ty<'tcx>>`
+ // and `List<GenericArg<'tcx>>`, the uniqueness requirement for
+ // lists is upheld.
+ let substs = self.mk_substs(ty::subst::ty_slice_as_generic_args(ts));
+ substs.try_as_type_list().unwrap()
+ }
+
+ // Unlike various other `mk_*_from_iter` functions, this one uses `I:
+ // IntoIterator` instead of `I: Iterator`, and it doesn't have a slice
+ // variant, because of the need to combine `inputs` and `output`. This
+ // explains the lack of `_from_iter` suffix.
+ pub fn mk_fn_sig<I, T>(
self,
inputs: I,
output: I::Item,
c_variadic: bool,
unsafety: hir::Unsafety,
abi: abi::Abi,
- ) -> <I::Item as InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>::Output
+ ) -> T::Output
where
- I: Iterator<Item: InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>,
+ I: IntoIterator<Item = T>,
+ T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
{
- inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig {
- inputs_and_output: self.intern_type_list(xs),
+ T::collect_and_apply(inputs.into_iter().chain(iter::once(output)), |xs| ty::FnSig {
+ inputs_and_output: self.mk_type_list(xs),
c_variadic,
unsafety,
abi,
})
}
- pub fn mk_poly_existential_predicates<
- I: InternAs<PolyExistentialPredicate<'tcx>, &'tcx List<PolyExistentialPredicate<'tcx>>>,
- >(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_poly_existential_predicates(xs))
+ pub fn mk_poly_existential_predicates_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<
+ PolyExistentialPredicate<'tcx>,
+ &'tcx List<PolyExistentialPredicate<'tcx>>,
+ >,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs))
}
- pub fn mk_predicates<I: InternAs<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>>(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_predicates(xs))
+ pub fn mk_predicates_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_predicates(xs))
}
- pub fn mk_type_list<I: InternAs<Ty<'tcx>, &'tcx List<Ty<'tcx>>>>(self, iter: I) -> I::Output {
- iter.intern_with(|xs| self.intern_type_list(xs))
+ pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<Ty<'tcx>, &'tcx List<Ty<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_type_list(xs))
}
- pub fn mk_substs<I: InternAs<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>>(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_substs(xs))
+ pub fn mk_substs_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_substs(xs))
}
- pub fn mk_place_elems<I: InternAs<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>>(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_place_elems(xs))
+ pub fn mk_canonical_var_infos_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<CanonicalVarInfo<'tcx>, &'tcx List<CanonicalVarInfo<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_canonical_var_infos(xs))
+ }
+
+ pub fn mk_place_elems_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_place_elems(xs))
}
pub fn mk_substs_trait(
@@ -2189,34 +2274,33 @@ impl<'tcx> TyCtxt<'tcx> {
self_ty: Ty<'tcx>,
rest: impl IntoIterator<Item = GenericArg<'tcx>>,
) -> SubstsRef<'tcx> {
- self.mk_substs(iter::once(self_ty.into()).chain(rest))
+ self.mk_substs_from_iter(iter::once(self_ty.into()).chain(rest))
}
pub fn mk_trait_ref(
self,
trait_def_id: DefId,
- substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> ty::TraitRef<'tcx> {
- let substs = self.check_substs(trait_def_id, substs);
+ let substs = self.check_and_mk_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>>>,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> ty::AliasTy<'tcx> {
- let substs = self.check_substs(def_id, substs);
+ let substs = self.check_and_mk_substs(def_id, substs);
ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
}
- pub fn mk_bound_variable_kinds<
- I: InternAs<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
- >(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_bound_variable_kinds(xs))
+ pub fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
}
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
@@ -2291,26 +2375,23 @@ impl<'tcx> TyCtxt<'tcx> {
Some(&*candidates)
}
- pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> {
+ pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
debug!(?id, "named_region");
- self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
+ self.named_variable_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
}
pub fn is_late_bound(self, id: HirId) -> bool {
- self.is_late_bound_map(id.owner.def_id).map_or(false, |set| {
- let def_id = self.hir().local_def_id(id);
- set.contains(&def_id)
- })
+ self.is_late_bound_map(id.owner).map_or(false, |set| set.contains(&id.local_id))
}
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
self.mk_bound_variable_kinds(
- self.late_bound_vars_map(id.owner)
+ &self
+ .late_bound_vars_map(id.owner)
.and_then(|map| map.get(&id.local_id).cloned())
.unwrap_or_else(|| {
- bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id)
- })
- .iter(),
+ bug!("No bound vars found for {}", self.hir().node_to_string(id))
+ }),
)
}
@@ -2351,16 +2432,24 @@ impl<'tcx> TyCtxt<'tcx> {
})
)
}
+
+ pub fn local_def_id_to_hir_id(self, local_def_id: LocalDefId) -> HirId {
+ self.opt_local_def_id_to_hir_id(local_def_id).unwrap()
+ }
+
+ pub fn trait_solver_next(self) -> bool {
+ self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
+ }
}
impl<'tcx> TyCtxtAt<'tcx> {
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
#[track_caller]
- pub fn ty_error(self) -> Ty<'tcx> {
+ pub fn ty_error_misc(self) -> Ty<'tcx> {
self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported")
}
- /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
+ /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
/// ensure it gets used.
#[track_caller]
pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
@@ -2370,7 +2459,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
pub fn mk_trait_ref(
self,
trait_lang_item: LangItem,
- substs: impl IntoIterator<Item = impl Into<ty::GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
) -> ty::TraitRef<'tcx> {
let trait_def_id = self.require_lang_item(trait_lang_item, Some(self.span));
self.tcx.mk_trait_ref(trait_def_id, substs)
@@ -2392,19 +2481,11 @@ pub struct DeducedParamAttrs {
pub read_only: bool,
}
-// We are comparing types with different invariant lifetimes, so `ptr::eq`
-// won't work for us.
-fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
- t as *const () == u as *const ()
-}
-
pub fn provide(providers: &mut ty::query::Providers) {
providers.module_reexports =
|tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]);
providers.maybe_unused_trait_imports =
|tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
- providers.maybe_unused_extern_crates =
- |tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..];
providers.names_imported_by_glob_use = |tcx, id| {
tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
};
@@ -2424,6 +2505,5 @@ 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);
+ providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
}
diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs
new file mode 100644
index 000000000..5426ac8d7
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/context/tls.rs
@@ -0,0 +1,186 @@
+use super::{GlobalCtxt, TyCtxt};
+
+use crate::dep_graph::TaskDepsRef;
+use crate::ty::query;
+use rustc_data_structures::sync::{self, Lock};
+use rustc_errors::Diagnostic;
+use std::mem;
+use std::ptr;
+use thin_vec::ThinVec;
+
+/// This is the implicit state of rustc. It contains the current
+/// `TyCtxt` and query. It is updated when creating a local interner or
+/// executing a new query. Whenever there's a `TyCtxt` value available
+/// you should also have access to an `ImplicitCtxt` through the functions
+/// in this module.
+#[derive(Clone)]
+pub struct ImplicitCtxt<'a, 'tcx> {
+ /// The current `TyCtxt`.
+ pub tcx: TyCtxt<'tcx>,
+
+ /// The current query job, if any. This is updated by `JobOwner::start` in
+ /// `ty::query::plumbing` when executing a query.
+ pub query: Option<query::QueryJobId>,
+
+ /// Where to store diagnostics for the current query job, if any.
+ /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
+ pub diagnostics: Option<&'a Lock<ThinVec<Diagnostic>>>,
+
+ /// Used to prevent queries from calling too deeply.
+ pub query_depth: usize,
+
+ /// The current dep graph task. This is used to add dependencies to queries
+ /// when executing them.
+ pub task_deps: TaskDepsRef<'a>,
+}
+
+impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
+ pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
+ let tcx = TyCtxt { gcx };
+ ImplicitCtxt {
+ tcx,
+ query: None,
+ diagnostics: None,
+ query_depth: 0,
+ task_deps: TaskDepsRef::Ignore,
+ }
+ }
+}
+
+#[cfg(parallel_compiler)]
+mod tlv {
+ use rustc_rayon_core as rayon_core;
+ use std::ptr;
+
+ /// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
+ /// This is used to get the pointer to the current `ImplicitCtxt`.
+ #[inline]
+ pub(super) fn get_tlv() -> *const () {
+ ptr::from_exposed_addr(rayon_core::tlv::get())
+ }
+
+ /// Sets Rayon's thread-local variable, which is preserved for Rayon jobs
+ /// to `value` during the call to `f`. It is restored to its previous value after.
+ /// This is used to set the pointer to the new `ImplicitCtxt`.
+ #[inline]
+ pub(super) fn with_tlv<F: FnOnce() -> R, R>(value: *const (), f: F) -> R {
+ rayon_core::tlv::with(value.expose_addr(), f)
+ }
+}
+
+#[cfg(not(parallel_compiler))]
+mod tlv {
+ use std::cell::Cell;
+ use std::ptr;
+
+ thread_local! {
+ /// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
+ static TLV: Cell<*const ()> = const { Cell::new(ptr::null()) };
+ }
+
+ /// Gets the pointer to the current `ImplicitCtxt`.
+ #[inline]
+ pub(super) fn get_tlv() -> *const () {
+ TLV.with(|tlv| tlv.get())
+ }
+
+ /// Sets TLV to `value` during the call to `f`.
+ /// It is restored to its previous value after.
+ /// This is used to set the pointer to the new `ImplicitCtxt`.
+ #[inline]
+ pub(super) fn with_tlv<F: FnOnce() -> R, R>(value: *const (), f: F) -> R {
+ let old = TLV.replace(value);
+ let _reset = rustc_data_structures::OnDrop(move || TLV.set(old));
+ f()
+ }
+}
+
+#[inline]
+fn erase(context: &ImplicitCtxt<'_, '_>) -> *const () {
+ context as *const _ as *const ()
+}
+
+#[inline]
+unsafe fn downcast<'a, 'tcx>(context: *const ()) -> &'a ImplicitCtxt<'a, 'tcx> {
+ &*(context as *const ImplicitCtxt<'a, 'tcx>)
+}
+
+/// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
+#[inline]
+pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R
+where
+ F: FnOnce() -> R,
+{
+ tlv::with_tlv(erase(context), f)
+}
+
+/// Allows access to the current `ImplicitCtxt` in a closure if one is available.
+#[inline]
+pub fn with_context_opt<F, R>(f: F) -> R
+where
+ F: for<'a, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'tcx>>) -> R,
+{
+ let context = tlv::get_tlv();
+ if context.is_null() {
+ f(None)
+ } else {
+ // We could get an `ImplicitCtxt` pointer from another thread.
+ // Ensure that `ImplicitCtxt` is `Sync`.
+ sync::assert_sync::<ImplicitCtxt<'_, '_>>();
+
+ unsafe { f(Some(downcast(context))) }
+ }
+}
+
+/// Allows access to the current `ImplicitCtxt`.
+/// Panics if there is no `ImplicitCtxt` available.
+#[inline]
+pub fn with_context<F, R>(f: F) -> R
+where
+ F: for<'a, 'tcx> FnOnce(&ImplicitCtxt<'a, 'tcx>) -> R,
+{
+ with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls")))
+}
+
+/// Allows access to the current `ImplicitCtxt` whose tcx field is the same as the tcx argument
+/// passed in. This means the closure is given an `ImplicitCtxt` with the same `'tcx` lifetime
+/// as the `TyCtxt` passed in.
+/// This will panic if you pass it a `TyCtxt` which is different from the current
+/// `ImplicitCtxt`'s `tcx` field.
+#[inline]
+pub fn with_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R
+where
+ F: FnOnce(&ImplicitCtxt<'_, 'tcx>) -> R,
+{
+ with_context(|context| {
+ // The two gcx have different invariant lifetimes, so we need to erase them for the comparison.
+ assert!(ptr::eq(
+ context.tcx.gcx as *const _ as *const (),
+ tcx.gcx as *const _ as *const ()
+ ));
+
+ let context: &ImplicitCtxt<'_, '_> = unsafe { mem::transmute(context) };
+
+ f(context)
+ })
+}
+
+/// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
+/// Panics if there is no `ImplicitCtxt` available.
+#[inline]
+pub fn with<F, R>(f: F) -> R
+where
+ F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
+{
+ with_context(|context| f(context.tcx))
+}
+
+/// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
+/// The closure is passed None if there is no `ImplicitCtxt` available.
+#[inline]
+pub fn with_opt<F, R>(f: F) -> R
+where
+ F: for<'tcx> FnOnce(Option<TyCtxt<'tcx>>) -> R,
+{
+ with_context_opt(|opt_context| f(opt_context.map(|context| context.tcx)))
+}
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 4b4518f61..e894e1aaf 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -3,8 +3,9 @@
use std::ops::ControlFlow;
use crate::ty::{
- visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque,
- PolyTraitPredicate, Projection, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
+ AliasTy, Const, ConstKind, DefIdTree, FallibleTypeFolder, InferConst, InferTy, Opaque,
+ PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
+ TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use rustc_data_structures::fx::FxHashMap;
@@ -76,7 +77,7 @@ impl<'tcx> Ty<'tcx> {
}
}
-pub trait IsSuggestable<'tcx> {
+pub trait IsSuggestable<'tcx>: Sized {
/// Whether this makes sense to suggest in a diagnostic.
///
/// We filter out certain types and constants since they don't provide
@@ -87,15 +88,21 @@ pub trait IsSuggestable<'tcx> {
/// Only if `infer_suggestable` is true, we consider type and const
/// inference variables to be suggestable.
fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool;
+
+ fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option<Self>;
}
impl<'tcx, T> IsSuggestable<'tcx> for T
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>> + TypeFoldable<TyCtxt<'tcx>>,
{
fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool {
self.visit_with(&mut IsSuggestableVisitor { tcx, infer_suggestable }).is_continue()
}
+
+ fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option<T> {
+ self.try_fold_with(&mut MakeSuggestableFolder { tcx, infer_suggestable }).ok()
+ }
}
pub fn suggest_arbitrary_trait_bound<'tcx>(
@@ -186,6 +193,9 @@ fn suggest_removing_unsized_bound(
}
/// Suggest restricting a type param with a new bound.
+///
+/// If `span_to_replace` is provided, then that span will be replaced with the
+/// `constraint`. If one wasn't provided, then the full bound will be suggested.
pub fn suggest_constraining_type_param(
tcx: TyCtxt<'_>,
generics: &hir::Generics<'_>,
@@ -193,12 +203,14 @@ pub fn suggest_constraining_type_param(
param_name: &str,
constraint: &str,
def_id: Option<DefId>,
+ span_to_replace: Option<Span>,
) -> bool {
suggest_constraining_type_params(
tcx,
generics,
err,
[(param_name, constraint, def_id)].into_iter(),
+ span_to_replace,
)
}
@@ -208,6 +220,7 @@ pub fn suggest_constraining_type_params<'a>(
generics: &hir::Generics<'_>,
err: &mut Diagnostic,
param_names_and_constraints: impl Iterator<Item = (&'a str, &'a str, Option<DefId>)>,
+ span_to_replace: Option<Span>,
) -> bool {
let mut grouped = FxHashMap::default();
param_names_and_constraints.for_each(|(param_name, constraint, def_id)| {
@@ -246,7 +259,9 @@ pub fn suggest_constraining_type_params<'a>(
let mut suggest_restrict = |span, bound_list_non_empty| {
suggestions.push((
span,
- if bound_list_non_empty {
+ if span_to_replace.is_some() {
+ constraint.clone()
+ } else if bound_list_non_empty {
format!(" + {}", constraint)
} else {
format!(" {}", constraint)
@@ -255,6 +270,11 @@ pub fn suggest_constraining_type_params<'a>(
))
};
+ if let Some(span) = span_to_replace {
+ suggest_restrict(span, true);
+ continue;
+ }
+
// When the type parameter has been provided bounds
//
// Message:
@@ -440,7 +460,7 @@ pub struct IsSuggestableVisitor<'tcx> {
infer_suggestable: bool,
}
-impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -460,8 +480,9 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
Alias(Opaque, AliasTy { def_id, .. }) => {
let parent = self.tcx.parent(def_id);
+ let parent_ty = self.tcx.type_of(parent).subst_identity();
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()
+ && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind()
&& parent_opaque_def_id == def_id
{
// Okay
@@ -509,3 +530,92 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
c.super_visit_with(self)
}
}
+
+pub struct MakeSuggestableFolder<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ infer_suggestable: bool,
+}
+
+impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> {
+ type Error = ();
+
+ fn interner(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+ let t = match *t.kind() {
+ Infer(InferTy::TyVar(_)) if self.infer_suggestable => t,
+
+ FnDef(def_id, substs) => {
+ self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
+ }
+
+ // FIXME(compiler-errors): We could replace these with infer, I guess.
+ Closure(..)
+ | Infer(..)
+ | Generator(..)
+ | GeneratorWitness(..)
+ | Bound(_, _)
+ | Placeholder(_)
+ | Error(_) => {
+ return Err(());
+ }
+
+ Alias(Opaque, AliasTy { def_id, .. }) => {
+ let parent = self.tcx.parent(def_id);
+ let parent_ty = self.tcx.type_of(parent).subst_identity();
+ if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
+ && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind()
+ && parent_opaque_def_id == def_id
+ {
+ t
+ } else {
+ return Err(());
+ }
+ }
+
+ Param(param) => {
+ // FIXME: It would be nice to make this not use string manipulation,
+ // but it's pretty hard to do this, since `ty::ParamTy` is missing
+ // sufficient info to determine if it is synthetic, and we don't
+ // always have a convenient way of getting `ty::Generics` at the call
+ // sites we invoke `IsSuggestable::is_suggestable`.
+ if param.name.as_str().starts_with("impl ") {
+ return Err(());
+ }
+
+ t
+ }
+
+ _ => t,
+ };
+
+ t.try_super_fold_with(self)
+ }
+
+ fn try_fold_const(&mut self, c: Const<'tcx>) -> Result<Const<'tcx>, ()> {
+ let c = match c.kind() {
+ ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => c,
+
+ ConstKind::Infer(..)
+ | ConstKind::Bound(..)
+ | ConstKind::Placeholder(..)
+ | ConstKind::Error(..) => {
+ return Err(());
+ }
+
+ _ => c,
+ };
+
+ c.try_super_fold_with(self)
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(middle_const_not_used_in_type_alias)]
+pub(super) struct ConstNotUsedTraitAlias {
+ pub ct: String,
+ #[primary_span]
+ pub span: Span,
+}
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index 9e4f90caa..383773248 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -1,6 +1,5 @@
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use crate::ty::visit::TypeVisitable;
-use crate::ty::{self, Ty, TyCtxt, TypeFlags};
+use crate::ty::{self, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
pub(super) fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers { erase_regions_ty, ..*providers };
@@ -18,7 +17,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// subtyping, but they are anonymized and normalized as well)..
pub fn erase_regions<T>(self, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
// If there's nothing to erase avoid performing the query at all
if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
@@ -35,8 +34,8 @@ struct RegionEraserVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
}
-impl<'tcx> TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
@@ -46,7 +45,7 @@ impl<'tcx> TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let u = self.tcx.anonymize_bound_vars(t);
u.super_fold_with(self)
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 5d394f71f..9c171a69d 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -1,24 +1,16 @@
-use crate::traits::{ObligationCause, ObligationCauseCode};
-use crate::ty::diagnostics::suggest_constraining_type_param;
-use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer};
+use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, PrettyPrinter};
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
-use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
-use rustc_errors::{pluralize, Diagnostic, MultiSpan};
+use rustc_errors::pluralize;
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};
+use rustc_span::symbol::Symbol;
use rustc_target::spec::abi;
-
use std::borrow::Cow;
use std::collections::hash_map::DefaultHasher;
-use std::fmt;
use std::hash::{Hash, Hasher};
use std::path::PathBuf;
-use super::print::PrettyPrinter;
-
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable, Lift)]
pub struct ExpectedFound<T> {
pub expected: T,
@@ -36,7 +28,7 @@ impl<T> ExpectedFound<T> {
}
// Data structures used in type unification
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, PartialEq, Eq)]
#[rustc_pass_by_value]
pub enum TypeError<'tcx> {
Mismatch,
@@ -93,20 +85,16 @@ impl TypeError<'_> {
/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
/// afterwards to present additional details, particularly when it comes to lifetime-related
/// errors.
-impl<'tcx> fmt::Display for TypeError<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl<'tcx> TypeError<'tcx> {
+ pub fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
use self::TypeError::*;
- fn report_maybe_different(
- f: &mut fmt::Formatter<'_>,
- expected: &str,
- found: &str,
- ) -> fmt::Result {
+ fn report_maybe_different(expected: &str, found: &str) -> String {
// A naive approach to making sure that we're not reporting silly errors such as:
// (expected closure, found closure).
if expected == found {
- write!(f, "expected {}, found a different {}", expected, found)
+ format!("expected {}, found a different {}", expected, found)
} else {
- write!(f, "expected {}, found {}", expected, found)
+ format!("expected {}, found {}", expected, found)
}
}
@@ -115,64 +103,63 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
_ => String::new(),
};
- match *self {
- CyclicTy(_) => write!(f, "cyclic type of infinite size"),
- CyclicConst(_) => write!(f, "encountered a self-referencing constant"),
- Mismatch => write!(f, "types differ"),
+ match self {
+ CyclicTy(_) => "cyclic type of infinite size".into(),
+ CyclicConst(_) => "encountered a self-referencing constant".into(),
+ Mismatch => "types differ".into(),
ConstnessMismatch(values) => {
- write!(f, "expected {} bound, found {} bound", values.expected, values.found)
+ format!("expected {} bound, found {} bound", values.expected, values.found).into()
}
PolarityMismatch(values) => {
- write!(f, "expected {} polarity, found {} polarity", values.expected, values.found)
+ format!("expected {} polarity, found {} polarity", values.expected, values.found)
+ .into()
}
UnsafetyMismatch(values) => {
- write!(f, "expected {} fn, found {} fn", values.expected, values.found)
+ format!("expected {} fn, found {} fn", values.expected, values.found).into()
}
AbiMismatch(values) => {
- write!(f, "expected {} fn, found {} fn", values.expected, values.found)
+ format!("expected {} fn, found {} fn", values.expected, values.found).into()
}
- ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"),
- TupleSize(values) => write!(
- f,
+ ArgumentMutability(_) | Mutability => "types differ in mutability".into(),
+ TupleSize(values) => format!(
"expected a tuple with {} element{}, found one with {} element{}",
values.expected,
pluralize!(values.expected),
values.found,
pluralize!(values.found)
- ),
- FixedArraySize(values) => write!(
- f,
+ )
+ .into(),
+ FixedArraySize(values) => format!(
"expected an array with a fixed size of {} element{}, found one with {} element{}",
values.expected,
pluralize!(values.expected),
values.found,
pluralize!(values.found)
- ),
- ArgCount => write!(f, "incorrect number of function parameters"),
- FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field),
- RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
+ )
+ .into(),
+ ArgCount => "incorrect number of function parameters".into(),
+ FieldMisMatch(adt, field) => format!("field type mismatch: {}.{}", adt, field).into(),
+ RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
// Actually naming the region here is a bit confusing because context is lacking
RegionsInsufficientlyPolymorphic(..) => {
- write!(f, "one type is more general than the other")
+ "one type is more general than the other".into()
}
- RegionsOverlyPolymorphic(br, _) => write!(
- f,
+ RegionsOverlyPolymorphic(br, _) => format!(
"expected concrete lifetime, found bound lifetime parameter{}",
br_string(br)
- ),
- RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
- ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| {
- let (mut expected, mut found) = with_forced_trimmed_paths!((
- values.expected.sort_string(tcx),
- values.found.sort_string(tcx),
- ));
+ )
+ .into(),
+ RegionsPlaceholderMismatch => "one type is more general than the other".into(),
+ ArgumentSorts(values, _) | Sorts(values) => {
+ let mut expected = values.expected.sort_string(tcx);
+ let mut found = values.found.sort_string(tcx);
if expected == found {
expected = values.expected.sort_string(tcx);
found = values.found.sort_string(tcx);
}
- report_maybe_different(f, &expected, &found)
- }),
- Traits(values) => ty::tls::with(|tcx| {
+ report_maybe_different(&expected, &found).into()
+ }
+ Traits(values) => {
let (mut expected, mut found) = with_forced_trimmed_paths!((
tcx.def_path_str(values.expected),
tcx.def_path_str(values.found),
@@ -181,12 +168,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
expected = tcx.def_path_str(values.expected);
found = tcx.def_path_str(values.found);
}
- report_maybe_different(
- f,
- &format!("trait `{expected}`"),
- &format!("trait `{found}`"),
- )
- }),
+ report_maybe_different(&format!("trait `{expected}`"), &format!("trait `{found}`"))
+ .into()
+ }
IntMismatch(ref values) => {
let expected = match values.expected {
ty::IntVarValue::IntType(ty) => ty.name_str(),
@@ -196,43 +180,38 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
ty::IntVarValue::IntType(ty) => ty.name_str(),
ty::IntVarValue::UintType(ty) => ty.name_str(),
};
- write!(f, "expected `{}`, found `{}`", expected, found)
+ format!("expected `{}`, found `{}`", expected, found).into()
}
- FloatMismatch(ref values) => {
- write!(
- f,
- "expected `{}`, found `{}`",
- values.expected.name_str(),
- values.found.name_str()
- )
- }
- VariadicMismatch(ref values) => write!(
- f,
+ FloatMismatch(ref values) => format!(
+ "expected `{}`, found `{}`",
+ values.expected.name_str(),
+ values.found.name_str()
+ )
+ .into(),
+ VariadicMismatch(ref values) => format!(
"expected {} fn, found {} function",
if values.expected { "variadic" } else { "non-variadic" },
if values.found { "variadic" } else { "non-variadic" }
- ),
- ProjectionMismatched(ref values) => ty::tls::with(|tcx| {
- write!(
- f,
- "expected {}, found {}",
- tcx.def_path_str(values.expected),
- tcx.def_path_str(values.found)
- )
- }),
+ )
+ .into(),
+ ProjectionMismatched(ref values) => format!(
+ "expected `{}`, found `{}`",
+ tcx.def_path_str(values.expected),
+ tcx.def_path_str(values.found)
+ )
+ .into(),
ExistentialMismatch(ref values) => report_maybe_different(
- f,
&format!("trait `{}`", values.expected),
&format!("trait `{}`", values.found),
- ),
+ )
+ .into(),
ConstMismatch(ref values) => {
- write!(f, "expected `{}`, found `{}`", values.expected, values.found)
+ format!("expected `{}`, found `{}`", values.expected, values.found).into()
+ }
+ IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
+ TargetFeatureCast(_) => {
+ "cannot coerce functions with `#[target_feature]` to safe function pointers".into()
}
- IntrinsicCast => write!(f, "cannot coerce intrinsics to function pointers"),
- TargetFeatureCast(_) => write!(
- f,
- "cannot coerce functions with `#[target_feature]` to safe function pointers"
- ),
}
}
}
@@ -265,60 +244,9 @@ impl<'tcx> TypeError<'tcx> {
}
impl<'tcx> Ty<'tcx> {
- pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
+ pub fn sort_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
match *self.kind() {
- ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
- format!("`{}`", self).into()
- }
- ty::Tuple(ref tys) if tys.is_empty() => format!("`{}`", self).into(),
-
- ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did())).into(),
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
- ty::Array(t, n) => {
- if t.is_simple_ty() {
- return format!("array `{}`", self).into();
- }
-
- let n = tcx.lift(n).unwrap();
- if let ty::ConstKind::Value(v) = n.kind() {
- if let Some(n) = v.try_to_machine_usize(tcx) {
- return format!("array of {} element{}", n, pluralize!(n)).into();
- }
- }
- "array".into()
- }
- ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(),
- ty::Slice(_) => "slice".into(),
- ty::RawPtr(tymut) => {
- let tymut_string = match tymut.mutbl {
- hir::Mutability::Mut => tymut.to_string(),
- hir::Mutability::Not => format!("const {}", tymut.ty),
- };
-
- if tymut_string != "_" && (tymut.ty.is_simple_text() || tymut_string.len() < "const raw pointer".len()) {
- format!("`*{}`", tymut_string).into()
- } else {
- // Unknown type name, it's long or has type arguments
- "raw pointer".into()
- }
- },
- ty::Ref(_, ty, mutbl) => {
- let tymut = ty::TypeAndMut { ty, mutbl };
- let tymut_string = tymut.to_string();
-
- if tymut_string != "_"
- && (ty.is_simple_text() || tymut_string.len() < "mutable reference".len())
- {
- format!("`&{}`", tymut_string).into()
- } else {
- // Unknown type name, it's long or has type arguments
- match mutbl {
- hir::Mutability::Mut => "mutable reference",
- _ => "reference",
- }
- .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(),
@@ -326,13 +254,13 @@ impl<'tcx> Ty<'tcx> {
},
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()
+ format!("`dyn {}`", tcx.def_path_str(principal.def_id())).into()
}
ty::Dynamic(..) => "trait object".into(),
ty::Closure(..) => "closure".into(),
ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
- ty::GeneratorWitness(..) => "generator witness".into(),
- ty::Tuple(..) => "tuple".into(),
+ ty::GeneratorWitness(..) |
+ ty::GeneratorWitnessMIR(..) => "generator witness".into(),
ty::Infer(ty::TyVar(_)) => "inferred type".into(),
ty::Infer(ty::IntVar(_)) => "integer".into(),
ty::Infer(ty::FloatVar(_)) => "floating-point number".into(),
@@ -342,9 +270,14 @@ impl<'tcx> Ty<'tcx> {
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
ty::Alias(ty::Projection, _) => "associated type".into(),
- ty::Param(p) => format!("type parameter `{}`", p).into(),
- ty::Alias(ty::Opaque, ..) => "opaque type".into(),
+ ty::Param(p) => format!("type parameter `{p}`").into(),
+ ty::Alias(ty::Opaque, ..) => if tcx.ty_is_opaque_future(self) { "future".into() } else { "opaque type".into() },
ty::Error(_) => "type error".into(),
+ _ => {
+ let width = tcx.sess.diagnostic_width();
+ let length_limit = std::cmp::max(width / 4, 15);
+ format!("`{}`", tcx.ty_string_with_limit(self, length_limit)).into()
+ }
}
}
@@ -379,7 +312,7 @@ impl<'tcx> Ty<'tcx> {
ty::Dynamic(..) => "trait object".into(),
ty::Closure(..) => "closure".into(),
ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
- ty::GeneratorWitness(..) => "generator witness".into(),
+ ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => "generator witness".into(),
ty::Tuple(..) => "tuple".into(),
ty::Placeholder(..) => "higher-ranked type".into(),
ty::Bound(..) => "bound type variable".into(),
@@ -391,630 +324,14 @@ impl<'tcx> Ty<'tcx> {
}
impl<'tcx> TyCtxt<'tcx> {
- pub fn note_and_explain_type_err(
- self,
- diag: &mut Diagnostic,
- err: TypeError<'tcx>,
- cause: &ObligationCause<'tcx>,
- sp: Span,
- body_owner_def_id: DefId,
- ) {
- use self::TypeError::*;
- debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
- match err {
- ArgumentSorts(values, _) | Sorts(values) => {
- match (values.expected.kind(), values.found.kind()) {
- (ty::Closure(..), ty::Closure(..)) => {
- 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::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => {
- // Issue #63167
- diag.note("distinct uses of `impl Trait` result in different opaque types");
- }
- (ty::Float(_), ty::Infer(ty::IntVar(_)))
- if let Ok(
- // Issue #53280
- snippet,
- ) = self.sess.source_map().span_to_snippet(sp) =>
- {
- if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') {
- diag.span_suggestion(
- sp,
- "use a float literal",
- format!("{}.0", snippet),
- MachineApplicable,
- );
- }
- }
- (ty::Param(expected), ty::Param(found)) => {
- let generics = self.generics_of(body_owner_def_id);
- let e_span = self.def_span(generics.type_param(expected, self).def_id);
- if !sp.contains(e_span) {
- diag.span_label(e_span, "expected type parameter");
- }
- let f_span = self.def_span(generics.type_param(found, self).def_id);
- if !sp.contains(f_span) {
- diag.span_label(f_span, "found type parameter");
- }
- diag.note(
- "a type parameter was expected, but a different one was found; \
- you might be missing a type parameter or trait bound",
- );
- diag.note(
- "for more information, visit \
- https://doc.rust-lang.org/book/ch10-02-traits.html\
- #traits-as-parameters",
- );
- }
- (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::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);
- if !sp.contains(p_span) {
- diag.span_label(p_span, "this type parameter");
- }
- let hir = self.hir();
- let mut note = true;
- if let Some(generics) = generics
- .type_param(p, self)
- .def_id
- .as_local()
- .map(|id| hir.local_def_id_to_hir_id(id))
- .and_then(|id| self.hir().find_parent(id))
- .as_ref()
- .and_then(|node| node.generics())
- {
- // Synthesize the associated type restriction `Add<Output = Expected>`.
- // FIXME: extract this logic for use in other diagnostics.
- 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.def_id);
- let item_args = self.format_generic_args(assoc_substs);
-
- let path = if path.ends_with('>') {
- format!(
- "{}, {}{} = {}>",
- &path[..path.len() - 1],
- item_name,
- item_args,
- p
- )
- } else {
- format!("{}<{}{} = {}>", path, item_name, item_args, p)
- };
- note = !suggest_constraining_type_param(
- self,
- generics,
- diag,
- &format!("{}", proj.self_ty()),
- &path,
- None,
- );
- }
- if note {
- diag.note("you might be missing a type parameter or trait bound");
- }
- }
- (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) {
- diag.span_label(p_span, "this type parameter");
- }
- diag.help("type parameters must be constrained to match other types");
- if self.sess.teach(&diag.get_code().unwrap()) {
- diag.help(
- "given a type parameter `T` and a method `foo`:
-```
-trait Trait<T> { fn foo(&self) -> T; }
-```
-the only ways to implement method `foo` are:
-- constrain `T` with an explicit type:
-```
-impl Trait<String> for X {
- fn foo(&self) -> String { String::new() }
-}
-```
-- add a trait bound to `T` and call a method on that trait that returns `Self`:
-```
-impl<T: std::default::Default> Trait<T> for X {
- fn foo(&self) -> T { <T as std::default::Default>::default() }
-}
-```
-- change `foo` to return an argument of type `T`:
-```
-impl<T> Trait<T> for X {
- fn foo(&self, x: T) -> T { x }
-}
-```",
- );
- }
- diag.note(
- "for more information, visit \
- https://doc.rust-lang.org/book/ch10-02-traits.html\
- #traits-as-parameters",
- );
- }
- (ty::Param(p), ty::Closure(..) | ty::Generator(..)) => {
- 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) {
- diag.span_label(p_span, "this type parameter");
- }
- diag.help(&format!(
- "every closure has a distinct type and so could not always match the \
- caller-chosen type of parameter `{}`",
- p
- ));
- }
- (ty::Param(p), _) | (_, 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) {
- diag.span_label(p_span, "this type parameter");
- }
- }
- (ty::Alias(ty::Projection, proj_ty), _) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
- self.expected_projection(
- diag,
- proj_ty,
- values,
- body_owner_def_id,
- cause.code(),
- );
- }
- (_, 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,
- );
- if !(self.suggest_constraining_opaque_associated_type(
- diag,
- &msg,
- proj_ty,
- values.expected,
- ) || self.suggest_constraint(
- diag,
- &msg,
- body_owner_def_id,
- proj_ty,
- values.expected,
- )) {
- diag.help(&msg);
- diag.note(
- "for more information, visit \
- https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
- );
- }
- }
- _ => {}
- }
- debug!(
- "note_and_explain_type_err expected={:?} ({:?}) found={:?} ({:?})",
- values.expected,
- values.expected.kind(),
- values.found,
- values.found.kind(),
- );
- }
- CyclicTy(ty) => {
- // Watch out for various cases of cyclic types and try to explain.
- if ty.is_closure() || ty.is_generator() {
- diag.note(
- "closures cannot capture themselves or take themselves as argument;\n\
- this error may be the result of a recent compiler bug-fix,\n\
- see issue #46062 <https://github.com/rust-lang/rust/issues/46062>\n\
- for more information",
- );
- }
- }
- TargetFeatureCast(def_id) => {
- let target_spans =
- self.get_attrs(def_id, sym::target_feature).map(|attr| attr.span);
- diag.note(
- "functions with `#[target_feature]` can only be coerced to `unsafe` function pointers"
- );
- diag.span_labels(target_spans, "`#[target_feature]` added here");
- }
- _ => {}
- }
- }
-
- fn suggest_constraint(
- self,
- diag: &mut Diagnostic,
- msg: &str,
- body_owner_def_id: DefId,
- proj_ty: &ty::AliasTy<'tcx>,
- ty: Ty<'tcx>,
- ) -> bool {
- 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() {
- // Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
- // This will also work for `impl Trait`.
- let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
- let generics = self.generics_of(body_owner_def_id);
- generics.type_param(param_ty, self).def_id
- } else {
- return false;
- };
- let Some(def_id) = def_id.as_local() else {
- return false;
- };
-
- // First look in the `where` clause, as this might be
- // `fn foo<T>(x: T) where T: Trait`.
- for pred in hir_generics.bounds_for_param(def_id) {
- if self.constrain_generic_bound_associated_type_structured_suggestion(
- diag,
- &trait_ref,
- pred.bounds,
- &assoc,
- assoc_substs,
- ty,
- msg,
- false,
- ) {
- return true;
- }
- }
- }
- }
- false
- }
-
- /// An associated type was expected and a different type was found.
- ///
- /// We perform a few different checks to see what we can suggest:
- ///
- /// - In the current item, look for associated functions that return the expected type and
- /// suggest calling them. (Not a structured suggestion.)
- /// - If any of the item's generic bounds can be constrained, we suggest constraining the
- /// associated type to the found type.
- /// - If the associated type has a default type and was expected inside of a `trait`, we
- /// mention that this is disallowed.
- /// - If all other things fail, and the error is not because of a mismatch between the `trait`
- /// and the `impl`, we provide a generic `help` to constrain the assoc type or call an assoc
- /// fn that returns the type.
- fn expected_projection(
- self,
- diag: &mut Diagnostic,
- proj_ty: &ty::AliasTy<'tcx>,
- values: ExpectedFound<Ty<'tcx>>,
- body_owner_def_id: DefId,
- cause_code: &ObligationCauseCode<'_>,
- ) {
- let msg = format!(
- "consider constraining the associated type `{}` to `{}`",
- values.expected, values.found
- );
- let body_owner = self.hir().get_if_local(body_owner_def_id);
- let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name);
-
- // We don't want to suggest calling an assoc fn in a scope where that isn't feasible.
- let callable_scope = matches!(
- body_owner,
- Some(
- hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })
- | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. })
- | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }),
- )
- );
- let impl_comparison =
- matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
- 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
- // scope is outside of a `Body`.
- } else {
- // If we find a suitable associated function that returns the expected type, we don't
- // want the more general suggestion later in this method about "consider constraining
- // the associated type or calling a method that returns the associated type".
- let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type(
- diag,
- assoc.container_id(self),
- current_method_ident,
- proj_ty.def_id,
- values.expected,
- );
- // Possibly suggest constraining the associated type to conform to the
- // found type.
- if self.suggest_constraint(diag, &msg, body_owner_def_id, proj_ty, values.found)
- || point_at_assoc_fn
- {
- return;
- }
- }
-
- self.suggest_constraining_opaque_associated_type(diag, &msg, proj_ty, values.found);
-
- if self.point_at_associated_type(diag, body_owner_def_id, values.found) {
- return;
- }
-
- if !impl_comparison {
- // Generic suggestion when we can't be more specific.
- if callable_scope {
- diag.help(&format!(
- "{} or calling a method that returns `{}`",
- msg, values.expected
- ));
- } else {
- diag.help(&msg);
- }
- diag.note(
- "for more information, visit \
- https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
- );
- }
- if self.sess.teach(&diag.get_code().unwrap()) {
- diag.help(
- "given an associated type `T` and a method `foo`:
-```
-trait Trait {
-type T;
-fn foo(&self) -> Self::T;
-}
-```
-the only way of implementing method `foo` is to constrain `T` with an explicit associated type:
-```
-impl Trait for X {
-type T = String;
-fn foo(&self) -> Self::T { String::new() }
-}
-```",
- );
- }
- }
-
- /// When the expected `impl Trait` is not defined in the current item, it will come from
- /// a return type. This can occur when dealing with `TryStream` (#71035).
- fn suggest_constraining_opaque_associated_type(
- self,
- diag: &mut Diagnostic,
- msg: &str,
- proj_ty: &ty::AliasTy<'tcx>,
- ty: Ty<'tcx>,
- ) -> bool {
- 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 {
- hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
- _ => bug!("The HirId comes from a `ty::Opaque`"),
- }
- } else {
- return false;
- };
-
- let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
-
- self.constrain_generic_bound_associated_type_structured_suggestion(
- diag,
- &trait_ref,
- opaque_hir_ty.bounds,
- assoc,
- assoc_substs,
- ty,
- msg,
- true,
- )
- } else {
- false
- }
- }
-
- fn point_at_methods_that_satisfy_associated_type(
- self,
- diag: &mut Diagnostic,
- assoc_container_id: DefId,
- current_method_ident: Option<Symbol>,
- proj_ty_item_def_id: DefId,
- expected: Ty<'tcx>,
- ) -> bool {
- let items = self.associated_items(assoc_container_id);
- // Find all the methods in the trait that could be called to construct the
- // expected associated type.
- // FIXME: consider suggesting the use of associated `const`s.
- let methods: Vec<(Span, String)> = items
- .items
- .iter()
- .filter(|(name, item)| {
- ty::AssocKind::Fn == item.kind && Some(**name) != current_method_ident
- })
- .filter_map(|(_, item)| {
- let method = self.fn_sig(item.def_id);
- match *method.output().skip_binder().kind() {
- ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. })
- if item_def_id == proj_ty_item_def_id =>
- {
- Some((
- self.def_span(item.def_id),
- format!("consider calling `{}`", self.def_path_str(item.def_id)),
- ))
- }
- _ => None,
- }
- })
- .collect();
- if !methods.is_empty() {
- // Use a single `help:` to show all the methods in the trait that can
- // be used to construct the expected associated type.
- let mut span: MultiSpan =
- methods.iter().map(|(sp, _)| *sp).collect::<Vec<Span>>().into();
- let msg = format!(
- "{some} method{s} {are} available that return{r} `{ty}`",
- some = if methods.len() == 1 { "a" } else { "some" },
- s = pluralize!(methods.len()),
- are = pluralize!("is", methods.len()),
- r = if methods.len() == 1 { "s" } else { "" },
- ty = expected
- );
- for (sp, label) in methods.into_iter() {
- span.push_span_label(sp, label);
- }
- diag.span_help(span, &msg);
- return true;
- }
- false
- }
-
- fn point_at_associated_type(
- self,
- diag: &mut Diagnostic,
- body_owner_def_id: DefId,
- found: Ty<'tcx>,
- ) -> bool {
- let Some(hir_id) = body_owner_def_id.as_local() else {
- return false;
- };
- let hir_id = self.hir().local_def_id_to_hir_id(hir_id);
- // When `body_owner` is an `impl` or `trait` item, look in its associated types for
- // `expected` and point at it.
- let parent_id = self.hir().get_parent_item(hir_id);
- let item = self.hir().find_by_def_id(parent_id.def_id);
- debug!("expected_projection parent item {:?}", item);
- match item {
- Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => {
- // FIXME: account for `#![feature(specialization)]`
- for item in &items[..] {
- match item.kind {
- hir::AssocItemKind::Type => {
- // FIXME: account for returning some type in a trait fn impl that has
- // an assoc type as a return type (#72076).
- if let hir::Defaultness::Default { has_value: true } =
- self.impl_defaultness(item.id.owner_id)
- {
- if self.type_of(item.id.owner_id) == found {
- diag.span_label(
- item.span,
- "associated type defaults can't be assumed inside the \
- trait defining them",
- );
- return true;
- }
- }
- }
- _ => {}
- }
- }
- }
- Some(hir::Node::Item(hir::Item {
- kind: hir::ItemKind::Impl(hir::Impl { items, .. }),
- ..
- })) => {
- for item in &items[..] {
- if let hir::AssocItemKind::Type = item.kind {
- if self.type_of(item.id.owner_id) == found {
- diag.span_label(item.span, "expected this associated type");
- return true;
- }
- }
- }
- }
- _ => {}
- }
- false
- }
-
- /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
- /// requirement, provide a structured suggestion to constrain it to a given type `ty`.
- ///
- /// `is_bound_surely_present` indicates whether we know the bound we're looking for is
- /// inside `bounds`. If that's the case then we can consider `bounds` containing only one
- /// trait bound as the one we're looking for. This can help in cases where the associated
- /// type is defined on a supertrait of the one present in the bounds.
- fn constrain_generic_bound_associated_type_structured_suggestion(
- self,
- diag: &mut Diagnostic,
- trait_ref: &ty::TraitRef<'tcx>,
- bounds: hir::GenericBounds<'_>,
- assoc: &ty::AssocItem,
- assoc_substs: &[ty::GenericArg<'tcx>],
- ty: Ty<'tcx>,
- msg: &str,
- is_bound_surely_present: bool,
- ) -> bool {
- // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
-
- let trait_bounds = bounds.iter().filter_map(|bound| match bound {
- hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => Some(ptr),
- _ => None,
- });
-
- let matching_trait_bounds = trait_bounds
- .clone()
- .filter(|ptr| ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id))
- .collect::<Vec<_>>();
-
- let span = match &matching_trait_bounds[..] {
- &[ptr] => ptr.span,
- &[] if is_bound_surely_present => match &trait_bounds.collect::<Vec<_>>()[..] {
- &[ptr] => ptr.span,
- _ => return false,
- },
- _ => return false,
- };
-
- self.constrain_associated_type_structured_suggestion(
- diag,
- span,
- assoc,
- assoc_substs,
- ty,
- msg,
- )
- }
-
- /// Given a span corresponding to a bound, provide a structured suggestion to set an
- /// associated type to a given type `ty`.
- fn constrain_associated_type_structured_suggestion(
- self,
- diag: &mut Diagnostic,
- span: Span,
- assoc: &ty::AssocItem,
- assoc_substs: &[ty::GenericArg<'tcx>],
- ty: Ty<'tcx>,
- msg: &str,
- ) -> bool {
- if let Ok(has_params) =
- self.sess.source_map().span_to_snippet(span).map(|snippet| snippet.ends_with('>'))
- {
- let (span, sugg) = if has_params {
- let pos = span.hi() - BytePos(1);
- let span = Span::new(pos, pos, span.ctxt(), span.parent());
- (span, format!(", {} = {}", assoc.ident(self), ty))
- } else {
- let item_args = self.format_generic_args(assoc_substs);
- (span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(self), item_args, ty))
- };
- diag.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect);
- return true;
- }
- false
- }
-
- pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
- let width = self.sess.diagnostic_width();
- let length_limit = width.saturating_sub(30);
+ pub fn ty_string_with_limit(self, ty: Ty<'tcx>, length_limit: usize) -> String {
let mut type_limit = 50;
let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
.pretty_print_type(ty)
.expect("could not write to `String`")
.into_buffer();
- if regular.len() <= width {
- return (regular, None);
+ if regular.len() <= length_limit {
+ return regular;
}
let mut short;
loop {
@@ -1034,6 +351,20 @@ fn foo(&self) -> Self::T { String::new() }
}
type_limit -= 1;
}
+ short
+ }
+
+ pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
+ let width = self.sess.diagnostic_width();
+ let length_limit = width.saturating_sub(30);
+ let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
+ .pretty_print_type(ty)
+ .expect("could not write to `String`")
+ .into_buffer();
+ if regular.len() <= width {
+ return (regular, None);
+ }
+ let short = self.ty_string_with_limit(ty, length_limit);
if regular == short {
return (regular, None);
}
@@ -1047,11 +378,4 @@ fn foo(&self) -> Self::T { String::new() }
Err(_) => (regular, None),
}
}
-
- fn format_generic_args(self, args: &[ty::GenericArg<'tcx>]) -> String {
- FmtPrinter::new(self, hir::def::Namespace::TypeNS)
- .path_generic_args(Ok, args)
- .expect("could not write to `String`.")
- .into_buffer()
- }
}
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index f785fb5c4..59deade0a 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -1,6 +1,6 @@
use crate::mir::Mutability;
use crate::ty::subst::GenericArgKind;
-use crate::ty::{self, Ty, TyCtxt, TypeVisitable};
+use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_hir::def_id::DefId;
use std::fmt::Debug;
use std::hash::Hash;
@@ -32,6 +32,7 @@ pub enum SimplifiedType {
ClosureSimplifiedType(DefId),
GeneratorSimplifiedType(DefId),
GeneratorWitnessSimplifiedType(usize),
+ GeneratorWitnessMIRSimplifiedType(DefId),
FunctionSimplifiedType(usize),
PlaceholderSimplifiedType,
}
@@ -108,6 +109,7 @@ pub fn simplify_type<'tcx>(
ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)),
ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)),
ty::GeneratorWitness(tys) => Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len())),
+ ty::GeneratorWitnessMIR(def_id, _) => Some(GeneratorWitnessMIRSimplifiedType(def_id)),
ty::Never => Some(NeverSimplifiedType),
ty::Tuple(tys) => Some(TupleSimplifiedType(tys.len())),
ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
@@ -139,7 +141,8 @@ impl SimplifiedType {
| ForeignSimplifiedType(d)
| TraitSimplifiedType(d)
| ClosureSimplifiedType(d)
- | GeneratorSimplifiedType(d) => Some(d),
+ | GeneratorSimplifiedType(d)
+ | GeneratorWitnessMIRSimplifiedType(d) => Some(d),
_ => None,
}
}
@@ -208,6 +211,7 @@ impl DeepRejectCtxt {
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Placeholder(..)
| ty::Bound(..)
| ty::Infer(_) => bug!("unexpected impl_ty: {impl_ty}"),
@@ -286,7 +290,7 @@ impl DeepRejectCtxt {
// Impls cannot contain these types as these cannot be named directly.
ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
- ty::Placeholder(..) => false,
+ ty::Placeholder(..) | ty::Bound(..) => false,
// Depending on the value of `treat_obligation_params`, we either
// treat generic parameters like placeholders or like inference variables.
@@ -306,7 +310,7 @@ impl DeepRejectCtxt {
ty::Error(_) => true,
- ty::GeneratorWitness(..) | ty::Bound(..) => {
+ ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => {
bug!("unexpected obligation type: {:?}", obligation_ty)
}
}
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index b7eafc4b4..91241ff40 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -125,6 +125,16 @@ impl FlagComputation {
self.bound_computation(ts, |flags, ts| flags.add_tys(ts));
}
+ ty::GeneratorWitnessMIR(_, substs) => {
+ let should_remove_further_specializable =
+ !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
+ self.add_substs(substs);
+ if should_remove_further_specializable {
+ self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
+ }
+ self.add_flags(TypeFlags::HAS_TY_GENERATOR);
+ }
+
&ty::Closure(_, substs) => {
let substs = substs.as_closure();
let should_remove_further_specializable =
@@ -241,6 +251,10 @@ impl FlagComputation {
self.add_ty(ty);
self.add_region(region);
}
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ self.add_const(ct);
+ self.add_ty(ty);
+ }
ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
self.add_ty(a);
self.add_ty(b);
@@ -254,10 +268,7 @@ impl FlagComputation {
term,
})) => {
self.add_projection_ty(projection_ty);
- match term.unpack() {
- ty::TermKind::Ty(ty) => self.add_ty(ty),
- ty::TermKind::Const(c) => self.add_const(c),
- }
+ self.add_term(term);
}
ty::PredicateKind::WellFormed(arg) => {
self.add_substs(slice::from_ref(&arg));
@@ -277,6 +288,10 @@ impl FlagComputation {
self.add_ty(ty);
}
ty::PredicateKind::Ambiguous => {}
+ ty::PredicateKind::AliasEq(t1, t2) => {
+ self.add_term(t1);
+ self.add_term(t2);
+ }
}
}
@@ -370,4 +385,11 @@ impl FlagComputation {
}
}
}
+
+ fn add_term(&mut self, term: ty::Term<'_>) {
+ match term.unpack() {
+ ty::TermKind::Ty(ty) => self.add_ty(ty),
+ ty::TermKind::Const(ct) => self.add_const(ct),
+ }
+ }
}
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 6b9a37d84..d66f436f9 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -1,210 +1,10 @@
-//! A folding traversal mechanism for complex data structures that contain type
-//! information.
-//!
-//! This is a modifying traversal. It consumes the data structure, producing a
-//! (possibly) modified version of it. Both fallible and infallible versions are
-//! available. The name is potentially confusing, because this traversal is more
-//! like `Iterator::map` than `Iterator::fold`.
-//!
-//! This traversal has limited flexibility. Only a small number of "types of
-//! interest" within the complex data structures can receive custom
-//! modification. These are the ones containing the most important type-related
-//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
-//!
-//! There are three groups of traits involved in each traversal.
-//! - `TypeFoldable`. This is implemented once for many types, including:
-//! - Types of interest, for which the methods delegate to the folder.
-//! - All other types, including generic containers like `Vec` and `Option`.
-//! It defines a "skeleton" of how they should be folded.
-//! - `TypeSuperFoldable`. This is implemented only for each type of interest,
-//! and defines the folding "skeleton" for these types.
-//! - `TypeFolder`/`FallibleTypeFolder. One of these is implemented for each
-//! folder. This defines how types of interest are folded.
-//!
-//! This means each fold is a mixture of (a) generic folding operations, and (b)
-//! custom fold operations that are specific to the folder.
-//! - The `TypeFoldable` impls handle most of the traversal, and call into
-//! `TypeFolder`/`FallibleTypeFolder` when they encounter a type of interest.
-//! - A `TypeFolder`/`FallibleTypeFolder` may call into another `TypeFoldable`
-//! impl, because some of the types of interest are recursive and can contain
-//! other types of interest.
-//! - A `TypeFolder`/`FallibleTypeFolder` may also call into a `TypeSuperFoldable`
-//! impl, because each folder might provide custom handling only for some types
-//! of interest, or only for some variants of each type of interest, and then
-//! use default traversal for the remaining cases.
-//!
-//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U:
-//! TypeFoldable`, and an instance `s = S(ty, u)`, it would be folded like so:
-//! ```text
-//! s.fold_with(folder) calls
-//! - ty.fold_with(folder) calls
-//! - folder.fold_ty(ty) may call
-//! - ty.super_fold_with(folder)
-//! - u.fold_with(folder)
-//! ```
-use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitable};
+use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::def_id::DefId;
use std::collections::BTreeMap;
-/// This trait is implemented for every type that can be folded,
-/// providing the skeleton of the traversal.
-///
-/// To implement this conveniently, use the derive macro located in
-/// `rustc_macros`.
-pub trait TypeFoldable<'tcx>: TypeVisitable<'tcx> {
- /// The entry point for folding. To fold a value `t` with a folder `f`
- /// call: `t.try_fold_with(f)`.
- ///
- /// For most types, this just traverses the value, calling `try_fold_with`
- /// on each field/element.
- ///
- /// For types of interest (such as `Ty`), the implementation of method
- /// calls a folder method specifically for that type (such as
- /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable`
- /// to `TypeFolder`.
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error>;
-
- /// A convenient alternative to `try_fold_with` for use with infallible
- /// folders. Do not override this method, to ensure coherence with
- /// `try_fold_with`.
- fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
- self.try_fold_with(folder).into_ok()
- }
-}
-
-// This trait is implemented for types of interest.
-pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> {
- /// Provides a default fold for a type of interest. This should only be
- /// called within `TypeFolder` methods, when a non-custom traversal is
- /// desired for the value of the type of interest passed to that method.
- /// For example, in `MyFolder::try_fold_ty(ty)`, it is valid to call
- /// `ty.try_super_fold_with(self)`, but any other folding should be done
- /// with `xyz.try_fold_with(self)`.
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error>;
-
- /// A convenient alternative to `try_super_fold_with` for use with
- /// infallible folders. Do not override this method, to ensure coherence
- /// with `try_super_fold_with`.
- fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
- self.try_super_fold_with(folder).into_ok()
- }
-}
-
-/// This trait is implemented for every infallible folding traversal. There is
-/// a fold method defined for every type of interest. Each such method has a
-/// default that does an "identity" fold. Implementations of these methods
-/// often fall back to a `super_fold_with` method if the primary argument
-/// doesn't satisfy a particular condition.
-///
-/// A blanket implementation of [`FallibleTypeFolder`] will defer to
-/// the infallible methods of this trait to ensure that the two APIs
-/// are coherent.
-pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> {
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
-
- fn fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T>
- where
- T: TypeFoldable<'tcx>,
- {
- t.super_fold_with(self)
- }
-
- fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- t.super_fold_with(self)
- }
-
- fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
- r.super_fold_with(self)
- }
-
- fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
- c.super_fold_with(self)
- }
-
- fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
- p.super_fold_with(self)
- }
-}
-
-/// This trait is implemented for every folding traversal. There is a fold
-/// method defined for every type of interest. Each such method has a default
-/// that does an "identity" fold.
-///
-/// A blanket implementation of this trait (that defers to the relevant
-/// method of [`TypeFolder`]) is provided for all infallible folders in
-/// order to ensure the two APIs are coherent.
-pub trait FallibleTypeFolder<'tcx>: Sized {
- type Error;
-
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
-
- fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
- where
- T: TypeFoldable<'tcx>,
- {
- t.try_super_fold_with(self)
- }
-
- fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
- t.try_super_fold_with(self)
- }
-
- fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
- r.try_super_fold_with(self)
- }
-
- fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
- c.try_super_fold_with(self)
- }
-
- fn try_fold_predicate(
- &mut self,
- p: ty::Predicate<'tcx>,
- ) -> Result<ty::Predicate<'tcx>, Self::Error> {
- p.try_super_fold_with(self)
- }
-}
-
-// This blanket implementation of the fallible trait for infallible folders
-// delegates to infallible methods to ensure coherence.
-impl<'tcx, F> FallibleTypeFolder<'tcx> for F
-where
- F: TypeFolder<'tcx>,
-{
- type Error = !;
-
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
- TypeFolder::tcx(self)
- }
-
- fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, !>
- where
- T: TypeFoldable<'tcx>,
- {
- Ok(self.fold_binder(t))
- }
-
- fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, !> {
- Ok(self.fold_ty(t))
- }
-
- fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, !> {
- Ok(self.fold_region(r))
- }
-
- fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, !> {
- Ok(self.fold_const(c))
- }
-
- fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {
- Ok(self.fold_predicate(p))
- }
-}
+pub use rustc_type_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
///////////////////////////////////////////////////////////////////////////
// Some sample folders
@@ -221,13 +21,13 @@ where
pub ct_op: H,
}
-impl<'tcx, F, G, H> TypeFolder<'tcx> for BottomUpFolder<'tcx, F, G, H>
+impl<'tcx, F, G, H> TypeFolder<TyCtxt<'tcx>> for BottomUpFolder<'tcx, F, G, H>
where
F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
H: FnMut(ty::Const<'tcx>) -> ty::Const<'tcx>,
{
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
@@ -260,7 +60,7 @@ impl<'tcx> TyCtxt<'tcx> {
mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
value.fold_with(&mut RegionFolder::new(self, &mut f))
}
@@ -271,7 +71,7 @@ impl<'tcx> TyCtxt<'tcx> {
mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
) -> T
where
- T: TypeSuperFoldable<'tcx>,
+ T: TypeSuperFoldable<TyCtxt<'tcx>>,
{
value.super_fold_with(&mut RegionFolder::new(self, &mut f))
}
@@ -311,12 +111,12 @@ impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
}
}
-impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -385,15 +185,15 @@ impl<'tcx, D: BoundVarReplacerDelegate<'tcx>> BoundVarReplacer<'tcx, D> {
}
}
-impl<'tcx, D> TypeFolder<'tcx> for BoundVarReplacer<'tcx, D>
+impl<'tcx, D> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'tcx, D>
where
D: BoundVarReplacerDelegate<'tcx>,
{
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -425,7 +225,7 @@ where
// debruijn index. Then we adjust it to the
// correct depth.
assert_eq!(debruijn1, ty::INNERMOST);
- self.tcx.reuse_or_mk_region(region, ty::ReLateBound(debruijn, br))
+ self.tcx.mk_re_late_bound(debruijn, br)
} else {
region
}
@@ -471,7 +271,7 @@ impl<'tcx> TyCtxt<'tcx> {
) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
where
F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let mut region_map = BTreeMap::new();
let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
@@ -486,7 +286,7 @@ impl<'tcx> TyCtxt<'tcx> {
) -> T
where
F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let value = value.skip_binder();
if !value.has_escaping_bound_vars() {
@@ -505,7 +305,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Replaces all escaping bound vars. The `fld_r` closure replaces escaping
/// bound regions; the `fld_t` closure replaces escaping bound types and the `fld_c`
/// closure replaces escaping bound consts.
- pub fn replace_escaping_bound_vars_uncached<T: TypeFoldable<'tcx>>(
+ pub fn replace_escaping_bound_vars_uncached<T: TypeFoldable<TyCtxt<'tcx>>>(
self,
value: T,
delegate: impl BoundVarReplacerDelegate<'tcx>,
@@ -521,7 +321,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Replaces all types or regions bound by the given `Binder`. The `fld_r`
/// closure replaces bound regions, the `fld_t` closure replaces bound
/// types, and `fld_c` replaces bound constants.
- pub fn replace_bound_vars_uncached<T: TypeFoldable<'tcx>>(
+ pub fn replace_bound_vars_uncached<T: TypeFoldable<TyCtxt<'tcx>>>(
self,
value: Binder<'tcx, T>,
delegate: impl BoundVarReplacerDelegate<'tcx>,
@@ -537,35 +337,29 @@ impl<'tcx> TyCtxt<'tcx> {
value: ty::Binder<'tcx, T>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
self.replace_late_bound_regions_uncached(value, |br| {
- self.mk_region(ty::ReFree(ty::FreeRegion {
- scope: all_outlive_scope,
- bound_region: br.kind,
- }))
+ self.mk_re_free(all_outlive_scope, br.kind)
})
}
pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let shift_bv = |bv: ty::BoundVar| ty::BoundVar::from_usize(bv.as_usize() + bound_vars);
self.replace_escaping_bound_vars_uncached(
value,
FnMutDelegate {
regions: &mut |r: ty::BoundRegion| {
- self.mk_region(ty::ReLateBound(
+ self.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
- ))
+ )
},
types: &mut |t: ty::BoundTy| {
- self.mk_ty(ty::Bound(
- ty::INNERMOST,
- ty::BoundTy { var: shift_bv(t.var), kind: t.kind },
- ))
+ self.mk_bound(ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind })
},
consts: &mut |c, ty: Ty<'tcx>| {
self.mk_const(ty::ConstKind::Bound(ty::INNERMOST, shift_bv(c)), ty)
@@ -578,7 +372,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// method lookup and a few other places where precise region relationships are not required.
pub fn erase_late_bound_regions<T>(self, value: Binder<'tcx, T>) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
}
@@ -586,7 +380,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// 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
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
struct Anonymize<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
@@ -603,16 +397,18 @@ impl<'tcx> TyCtxt<'tcx> {
})
.expect_region();
let br = ty::BoundRegion { var, kind };
- self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
+ self.tcx.mk_re_late_bound(ty::INNERMOST, br)
}
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
let entry = self.map.entry(bt.var);
let index = entry.index();
let var = ty::BoundVar::from_usize(index);
let kind = entry
- .or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon))
+ .or_insert_with(|| {
+ ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon(index as u32))
+ })
.expect_ty();
- self.tcx.mk_ty(ty::Bound(ty::INNERMOST, BoundTy { var, kind }))
+ self.tcx.mk_bound(ty::INNERMOST, BoundTy { var, kind })
}
fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> {
let entry = self.map.entry(bv);
@@ -626,7 +422,7 @@ impl<'tcx> TyCtxt<'tcx> {
let mut map = Default::default();
let delegate = Anonymize { tcx: self, map: &mut map };
let inner = self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate);
- let bound_vars = self.mk_bound_variable_kinds(map.into_values());
+ let bound_vars = self.mk_bound_variable_kinds_from_iter(map.into_values());
Binder::bind_with_vars(inner, bound_vars)
}
}
@@ -652,12 +448,12 @@ impl<'tcx> Shifter<'tcx> {
}
}
-impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -671,8 +467,7 @@ impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> {
match *r {
ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
let debruijn = debruijn.shifted_in(self.amount);
- let shifted = ty::ReLateBound(debruijn, br);
- self.tcx.mk_region(shifted)
+ self.tcx.mk_re_late_bound(debruijn, br)
}
_ => r,
}
@@ -682,7 +477,7 @@ impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> {
match *ty.kind() {
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
let debruijn = debruijn.shifted_in(self.amount);
- self.tcx.mk_ty(ty::Bound(debruijn, bound_ty))
+ self.tcx.mk_bound(debruijn, bound_ty)
}
_ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self),
@@ -713,7 +508,7 @@ pub fn shift_region<'tcx>(
) -> ty::Region<'tcx> {
match *region {
ty::ReLateBound(debruijn, br) if amount > 0 => {
- tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br))
+ tcx.mk_re_late_bound(debruijn.shifted_in(amount), br)
}
_ => region,
}
@@ -721,7 +516,7 @@ pub fn shift_region<'tcx>(
pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!("shift_vars(value={:?}, amount={})", value, amount);
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 801ca6004..baef4ffed 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -85,7 +85,7 @@ impl GenericParamDef {
) -> Option<EarlyBinder<ty::GenericArg<'tcx>>> {
match self.kind {
GenericParamDefKind::Type { has_default, .. } if has_default => {
- Some(tcx.bound_type_of(self.def_id).map_bound(|t| t.into()))
+ Some(tcx.type_of(self.def_id).map_bound(|t| t.into()))
}
GenericParamDefKind::Const { has_default } if has_default => {
Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into()))
@@ -100,10 +100,10 @@ impl GenericParamDef {
preceding_substs: &[ty::GenericArg<'tcx>],
) -> ty::GenericArg<'tcx> {
match &self.kind {
- ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
- ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(),
+ ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
+ ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(),
ty::GenericParamDefKind::Const { .. } => {
- tcx.const_error(tcx.bound_type_of(self.def_id).subst(tcx, preceding_substs)).into()
+ tcx.const_error(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
}
}
}
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index 3e59c0b96..4c7822acd 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -79,7 +79,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArgKin
// WARNING: We dedup cache the `HashStable` results for `List`
// while ignoring types and freely transmute
// between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
- // See `fn intern_type_list` for more details.
+ // See `fn mk_type_list` for more details.
//
// We therefore hash types without adding a hash for their discriminant.
//
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index 33f727297..e268553f8 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -57,7 +57,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
match self {
Self::False => Ok(false),
Self::True => Ok(true),
- Self::ConstIsZero(const_) => match const_.try_eval_usize(tcx, param_env) {
+ Self::ConstIsZero(const_) => match const_.try_eval_target_usize(tcx, param_env) {
None | Some(0) => Ok(true),
Some(1..) => Ok(false),
},
@@ -159,7 +159,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
match self {
Self::ConstIsZero(c) => {
let c = ty::EarlyBinder(c).subst(tcx, substs);
- let pred = match c.kind().try_to_machine_usize(tcx) {
+ let pred = match c.kind().try_to_target_usize(tcx) {
Some(0) => Self::True,
Some(1..) => Self::False,
None => Self::ConstIsZero(c),
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 5d5089cec..92a040068 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -87,7 +87,7 @@ impl<'tcx> VariantDef {
InhabitedPredicate::all(
tcx,
self.fields.iter().map(|field| {
- let pred = tcx.type_of(field.did).inhabited_predicate(tcx);
+ let pred = tcx.type_of(field.did).subst_identity().inhabited_predicate(tcx);
if adt.is_enum() {
return pred;
}
@@ -105,7 +105,7 @@ impl<'tcx> VariantDef {
impl<'tcx> Ty<'tcx> {
pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> {
match self.kind() {
- // For now, union`s are always considered inhabited
+ // For now, unions are always considered inhabited
Adt(adt, _) if adt.is_union() => InhabitedPredicate::True,
// Non-exhaustive ADTs from other crates are always considered inhabited
Adt(adt, _) if adt.is_variant_list_non_exhaustive() && !adt.did().is_local() => {
@@ -191,7 +191,7 @@ fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedP
// If we can evaluate the array length before having a `ParamEnv`, then
// we can simplify the predicate. This is an optimization.
- Array(ty, len) => match len.kind().try_to_machine_usize(tcx) {
+ Array(ty, len) => match len.kind().try_to_target_usize(tcx) {
Some(0) => InhabitedPredicate::True,
Some(1..) => ty.inhabited_predicate(tcx),
None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)),
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 6ac00d16c..f4028a5a9 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -1,7 +1,7 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::print::{FmtPrinter, Printer};
-use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable};
-use crate::ty::{EarlyBinder, InternalSubsts, SubstsRef};
+use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
+use crate::ty::{EarlyBinder, InternalSubsts, SubstsRef, TypeVisitableExt};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId};
@@ -103,7 +103,7 @@ impl<'tcx> Instance<'tcx> {
/// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization.
pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
let ty = tcx.type_of(self.def.def_id());
- tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty)
+ tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty.skip_binder())
}
/// Finds a crate that contains a monomorphization of this instance that
@@ -459,7 +459,7 @@ impl<'tcx> Instance<'tcx> {
substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> {
debug!("resolve_for_vtable(def_id={:?}, substs={:?})", def_id, substs);
- let fn_sig = tcx.fn_sig(def_id);
+ let fn_sig = tcx.fn_sig(def_id).subst_identity();
let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty()
&& fn_sig.input(0).skip_binder().is_param(0)
&& tcx.generics_of(def_id).has_self;
@@ -540,7 +540,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()]);
+ let substs = tcx.mk_substs(&[ty.into()]);
Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
}
@@ -584,12 +584,12 @@ impl<'tcx> Instance<'tcx> {
/// this function returns `None`, then the MIR body does not require substitution during
/// codegen.
fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> {
- if self.def.has_polymorphic_mir_body() { Some(self.substs) } else { None }
+ self.def.has_polymorphic_mir_body().then_some(self.substs)
}
pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: &T) -> T
where
- T: TypeFoldable<'tcx> + Copy,
+ T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
if let Some(substs) = self.substs_for_mir_body() {
EarlyBinder(*v).subst(tcx, substs)
@@ -606,7 +606,7 @@ impl<'tcx> Instance<'tcx> {
v: T,
) -> T
where
- T: TypeFoldable<'tcx> + Clone,
+ T: TypeFoldable<TyCtxt<'tcx>> + Clone,
{
if let Some(substs) = self.substs_for_mir_body() {
tcx.subst_and_normalize_erasing_regions(substs, param_env, v)
@@ -623,7 +623,7 @@ impl<'tcx> Instance<'tcx> {
v: T,
) -> Result<T, NormalizationError<'tcx>>
where
- T: TypeFoldable<'tcx> + Clone,
+ T: TypeFoldable<TyCtxt<'tcx>> + Clone,
{
if let Some(substs) = self.substs_for_mir_body() {
tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v)
@@ -662,7 +662,7 @@ fn polymorphize<'tcx>(
let def_id = instance.def_id();
let upvars_ty = if tcx.is_closure(def_id) {
Some(substs.as_closure().tupled_upvars_ty())
- } else if tcx.type_of(def_id).is_generator() {
+ } else if tcx.type_of(def_id).skip_binder().is_generator() {
Some(substs.as_generator().tupled_upvars_ty())
} else {
None
@@ -674,8 +674,8 @@ fn polymorphize<'tcx>(
tcx: TyCtxt<'tcx>,
}
- impl<'tcx> ty::TypeFolder<'tcx> for PolymorphizationFolder<'tcx> {
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+ impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for PolymorphizationFolder<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index dfd016569..254ffc33c 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,11 +1,13 @@
+use crate::fluent_generated as fluent;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::normalize_erasing_regions::NormalizationError;
-use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitable};
+use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_index::vec::Idx;
use rustc_session::config::OptLevel;
+use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::*;
@@ -91,7 +93,7 @@ impl IntegerExt for Integer {
if discr < fit {
bug!(
"Integer::repr_discr: `#[repr]` hint too small for \
- discriminant range of enum `{}",
+ discriminant range of enum `{}`",
ty
)
}
@@ -128,7 +130,8 @@ impl PrimitiveExt for Primitive {
Int(i, signed) => i.to_ty(tcx, signed),
F32 => tcx.types.f32,
F64 => tcx.types.f64,
- Pointer => tcx.mk_mut_ptr(tcx.mk_unit()),
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ Pointer(_) => tcx.mk_mut_ptr(tcx.mk_unit()),
}
}
@@ -138,7 +141,11 @@ impl PrimitiveExt for Primitive {
fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match *self {
Int(i, signed) => i.to_ty(tcx, signed),
- Pointer => tcx.types.usize,
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ Pointer(_) => {
+ let signed = false;
+ tcx.data_layout().ptr_sized_integer().to_ty(tcx, signed)
+ }
F32 | F64 => bug!("floats do not have an int type"),
}
}
@@ -163,6 +170,41 @@ pub const FAT_PTR_EXTRA: usize = 1;
/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
+/// Used in `check_validity_requirement` to indicate the kind of initialization
+/// that is checked to be valid
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+pub enum ValidityRequirement {
+ Inhabited,
+ Zero,
+ /// The return value of mem::uninitialized, 0x01
+ /// (unless -Zstrict-init-checks is on, in which case it's the same as Uninit).
+ UninitMitigated0x01Fill,
+ /// True uninitialized memory.
+ Uninit,
+}
+
+impl ValidityRequirement {
+ pub fn from_intrinsic(intrinsic: Symbol) -> Option<Self> {
+ match intrinsic {
+ sym::assert_inhabited => Some(Self::Inhabited),
+ sym::assert_zero_valid => Some(Self::Zero),
+ sym::assert_mem_uninitialized_valid => Some(Self::UninitMitigated0x01Fill),
+ _ => None,
+ }
+ }
+}
+
+impl fmt::Display for ValidityRequirement {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Inhabited => f.write_str("is inhabited"),
+ Self::Zero => f.write_str("allows being left zeroed"),
+ Self::UninitMitigated0x01Fill => f.write_str("allows being filled with 0x01"),
+ Self::Uninit => f.write_str("allows being left uninitialized"),
+ }
+ }
+}
+
#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
pub enum LayoutError<'tcx> {
Unknown(Ty<'tcx>),
@@ -177,16 +219,16 @@ impl IntoDiagnostic<'_, !> for LayoutError<'_> {
match self {
LayoutError::Unknown(ty) => {
diag.set_arg("ty", ty);
- diag.set_primary_message(rustc_errors::fluent::middle_unknown_layout);
+ diag.set_primary_message(fluent::middle_unknown_layout);
}
LayoutError::SizeOverflow(ty) => {
diag.set_arg("ty", ty);
- diag.set_primary_message(rustc_errors::fluent::middle_values_too_big);
+ diag.set_primary_message(fluent::middle_values_too_big);
}
LayoutError::NormalizationFailure(ty, e) => {
diag.set_arg("ty", ty);
diag.set_arg("failure_ty", e.get_type_for_failure());
- diag.set_primary_message(rustc_errors::fluent::middle_cannot_be_normalized);
+ diag.set_primary_message(fluent::middle_cannot_be_normalized);
}
}
diag
@@ -590,7 +632,7 @@ where
ty::Adt(def, _) => def.variant(variant_index).fields.len(),
_ => bug!(),
};
- tcx.intern_layout(LayoutS {
+ tcx.mk_layout(LayoutS {
variants: Variants::Single { index: variant_index },
fields: match NonZeroUsize::new(fields) {
Some(fields) => FieldsShape::Union(fields),
@@ -603,7 +645,7 @@ where
})
}
- Variants::Multiple { ref variants, .. } => cx.tcx().intern_layout(variants[variant_index].clone()),
+ Variants::Multiple { ref variants, .. } => cx.tcx().mk_layout(variants[variant_index].clone()),
};
assert_eq!(*layout.variants(), Variants::Single { index: variant_index });
@@ -625,7 +667,7 @@ where
let tcx = cx.tcx();
let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> {
TyAndLayout {
- layout: tcx.intern_layout(LayoutS::scalar(cx, tag)),
+ layout: tcx.mk_layout(LayoutS::scalar(cx, tag)),
ty: tag.primitive().to_ty(tcx),
}
};
@@ -640,6 +682,7 @@ where
| ty::Never
| ty::FnDef(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Foreign(..)
| ty::Dynamic(_, _, ty::Dyn) => {
bug!("TyAndLayout::field({:?}): not applicable", this)
@@ -764,7 +807,7 @@ where
ty::Dynamic(_, _, ty::DynStar) => {
if i == 0 {
- TyMaybeWithLayout::Ty(tcx.types.usize)
+ TyMaybeWithLayout::Ty(tcx.mk_mut_ptr(tcx.types.unit))
} else if i == 1 {
// FIXME(dyn-star) same FIXME as above applies here too
TyMaybeWithLayout::Ty(
@@ -812,17 +855,12 @@ where
let tcx = cx.tcx();
let param_env = cx.param_env();
- let addr_space_of_ty = |ty: Ty<'tcx>| {
- if ty.is_fn() { cx.data_layout().instruction_address_space } else { AddressSpace::DATA }
- };
-
let pointee_info = match *this.ty.kind() {
ty::RawPtr(mt) if offset.bytes() == 0 => {
tcx.layout_of(param_env.and(mt.ty)).ok().map(|layout| PointeeInfo {
size: layout.size,
align: layout.align.abi,
safe: None,
- address_space: addr_space_of_ty(mt.ty),
})
}
ty::FnPtr(fn_sig) if offset.bytes() == 0 => {
@@ -830,44 +868,26 @@ where
size: layout.size,
align: layout.align.abi,
safe: None,
- address_space: cx.data_layout().instruction_address_space,
})
}
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
- let address_space = addr_space_of_ty(ty);
- let kind = if tcx.sess.opts.optimize == OptLevel::No {
- // Use conservative pointer kind if not optimizing. This saves us the
- // Freeze/Unpin queries, and can save time in the codegen backend (noalias
- // attributes in LLVM have compile-time cost even in unoptimized builds).
- PointerKind::SharedMutable
- } else {
- match mt {
- hir::Mutability::Not => {
- if ty.is_freeze(tcx, cx.param_env()) {
- PointerKind::Frozen
- } else {
- PointerKind::SharedMutable
- }
- }
- hir::Mutability::Mut => {
- // References to self-referential structures should not be considered
- // noalias, as another pointer to the structure can be obtained, that
- // is not based-on the original reference. We consider all !Unpin
- // types to be potentially self-referential here.
- if ty.is_unpin(tcx, cx.param_env()) {
- PointerKind::UniqueBorrowed
- } else {
- PointerKind::UniqueBorrowedPinned
- }
- }
- }
+ // Use conservative pointer kind if not optimizing. This saves us the
+ // Freeze/Unpin queries, and can save time in the codegen backend (noalias
+ // attributes in LLVM have compile-time cost even in unoptimized builds).
+ let optimize = tcx.sess.opts.optimize != OptLevel::No;
+ let kind = match mt {
+ hir::Mutability::Not => PointerKind::SharedRef {
+ frozen: optimize && ty.is_freeze(tcx, cx.param_env()),
+ },
+ hir::Mutability::Mut => PointerKind::MutableRef {
+ unpin: optimize && ty.is_unpin(tcx, cx.param_env()),
+ },
};
tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo {
size: layout.size,
align: layout.align.abi,
safe: Some(kind),
- address_space,
})
}
@@ -904,7 +924,9 @@ where
let mut result = None;
if let Some(variant) = data_variant {
- let ptr_end = offset + Pointer.size(cx);
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ // (requires passing in the expected address space from the caller)
+ let ptr_end = offset + Pointer(AddressSpace::DATA).size(cx);
for i in 0..variant.fields.count() {
let field_start = variant.fields.offset(i);
if field_start <= offset {
@@ -930,7 +952,10 @@ where
if let Some(ref mut pointee) = result {
if let ty::Adt(def, _) = this.ty.kind() {
if def.is_box() && offset.bytes() == 0 {
- pointee.safe = Some(PointerKind::UniqueOwned);
+ let optimize = tcx.sess.opts.optimize != OptLevel::No;
+ pointee.safe = Some(PointerKind::Box {
+ unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()),
+ });
}
}
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 7dfcd1bb5..dce18a585 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -12,7 +12,7 @@
#![allow(rustc::usage_of_ty_tykind)]
pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
-pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
pub use self::AssocItemContainer::*;
pub use self::BorrowKind::*;
pub use self::IntVarValue::*;
@@ -31,23 +31,22 @@ pub use generics::*;
use rustc_ast as ast;
use rustc_ast::node_id::NodeMap;
use rustc_attr as attr;
-use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
+use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res};
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
use rustc_hir::Node;
use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
use rustc_serialize::{Decodable, Encodable};
-use rustc_session::cstore::Untracked;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{ExpnId, Span};
+use rustc_span::{ExpnId, ExpnKind, Span};
use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions};
use rustc_type_ir::WithCachedTypeInfo;
@@ -74,7 +73,7 @@ pub use self::binding::BindingMode;
pub use self::binding::BindingMode::*;
pub use self::closure::{
is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
- CapturedPlace, ClosureKind, MinCaptureInformationMap, MinCaptureList,
+ CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath,
CAPTURE_STRUCT_LOCAL,
};
@@ -154,7 +153,6 @@ pub type RegisteredTools = FxHashSet<Ident>;
pub struct ResolverOutputs {
pub global_ctxt: ResolverGlobalCtxt,
pub ast_lowering: ResolverAstLowering,
- pub untracked: Untracked,
}
#[derive(Debug)]
@@ -167,12 +165,8 @@ pub struct ResolverGlobalCtxt {
pub effective_visibilities: EffectiveVisibilities,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
- pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
pub reexport_map: FxHashMap<LocalDefId, Vec<ModChild>>,
pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
- /// Extern prelude entries. The value is `true` if the entry was introduced
- /// via `extern crate` item and not `--extern` option or compiler built-in.
- pub extern_prelude: FxHashMap<Symbol, bool>,
pub main_def: Option<MainDefinition>,
pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
/// A list of proc macro LocalDefIds, written out in the order in which
@@ -182,6 +176,9 @@ pub struct ResolverGlobalCtxt {
/// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
pub confused_type_with_std_module: FxHashMap<Span, Span>,
pub registered_tools: RegisteredTools,
+ pub doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>,
+ pub doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>,
+ pub all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
}
/// Resolutions that should only be used for lowering.
@@ -453,18 +450,6 @@ pub struct CReaderCacheKey {
#[rustc_pass_by_value]
pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
-impl<'tcx> TyCtxt<'tcx> {
- /// A "bool" type used in rustc_mir_transform unit tests when we
- /// have not spun up a TyCtxt.
- pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> =
- Ty(Interned::new_unchecked(&WithCachedTypeInfo {
- internee: ty::Bool,
- stable_hash: Fingerprint::ZERO,
- flags: TypeFlags::empty(),
- outer_exclusive_binder: DebruijnIndex::from_usize(0),
- }));
-}
-
impl ty::EarlyBoundRegion {
/// Does this early bound region have a name? Early bound regions normally
/// always have names except when using anonymous lifetimes (`'_`).
@@ -558,6 +543,8 @@ impl<'tcx> Predicate<'tcx> {
| PredicateKind::Clause(Clause::RegionOutlives(_))
| PredicateKind::Clause(Clause::TypeOutlives(_))
| PredicateKind::Clause(Clause::Projection(_))
+ | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ | PredicateKind::AliasEq(..)
| PredicateKind::ObjectSafe(_)
| PredicateKind::ClosureKind(_, _, _)
| PredicateKind::Subtype(_)
@@ -595,6 +582,10 @@ pub enum Clause<'tcx> {
/// `where <T as TraitRef>::Name == X`, approximately.
/// See the `ProjectionPredicate` struct for details.
Projection(ProjectionPredicate<'tcx>),
+
+ /// Ensures that a const generic argument to a parameter `const N: u8`
+ /// is of type `u8`.
+ ConstArgHasType(Const<'tcx>, Ty<'tcx>),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
@@ -645,6 +636,12 @@ pub enum PredicateKind<'tcx> {
/// A marker predicate that is always ambiguous.
/// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
Ambiguous,
+
+ /// Separate from `Clause::Projection` which is used for normalization in new solver.
+ /// This predicate requires two terms to be equal to eachother.
+ ///
+ /// Only used for new solver
+ AliasEq(Term<'tcx>, Term<'tcx>),
}
/// The crate outlives map is computed during typeck and contains the
@@ -713,7 +710,7 @@ impl<'tcx> Predicate<'tcx> {
// The substitution from the input trait-ref is therefore going to be
// `'a => 'x` (where `'x` has a DB index of 1).
// - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
- // early-bound parameter and `'b' is a late-bound parameter with a
+ // early-bound parameter and `'b` is a late-bound parameter with a
// DB index of 1.
// - If we replace `'a` with `'x` from the input, it too will have
// a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
@@ -756,7 +753,7 @@ impl<'tcx> Predicate<'tcx> {
let new = EarlyBinder(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
// 3) ['x] + ['b] -> ['x, 'b]
let bound_vars =
- tcx.mk_bound_variable_kinds(trait_bound_vars.iter().chain(pred_bound_vars));
+ tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars))
}
}
@@ -917,14 +914,17 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Term<'tcx> {
}
}
-impl<'tcx> TypeFoldable<'tcx> for Term<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(self.unpack().try_fold_with(folder)?.pack())
}
}
-impl<'tcx> TypeVisitable<'tcx> for Term<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.unpack().visit_with(visitor)
}
}
@@ -976,6 +976,33 @@ impl<'tcx> Term<'tcx> {
TermKind::Const(c) => c.into(),
}
}
+
+ /// This function returns `None` for `AliasKind::Opaque`.
+ ///
+ /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly
+ /// deal with constants.
+ pub fn to_alias_term_no_opaque(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
+ match self.unpack() {
+ TermKind::Ty(ty) => match ty.kind() {
+ ty::Alias(kind, alias_ty) => match kind {
+ AliasKind::Projection => Some(*alias_ty),
+ AliasKind::Opaque => None,
+ },
+ _ => None,
+ },
+ TermKind::Const(ct) => match ct.kind() {
+ ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def.did, uv.substs)),
+ _ => None,
+ },
+ }
+ }
+
+ pub fn is_infer(&self) -> bool {
+ match self.unpack() {
+ TermKind::Ty(ty) => ty.is_ty_or_numeric_infer(),
+ TermKind::Const(ct) => ct.is_ct_infer(),
+ }
+ }
}
const TAG_MASK: usize = 0b11;
@@ -1165,6 +1192,8 @@ impl<'tcx> Predicate<'tcx> {
match predicate.skip_binder() {
PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(Clause::Projection(..))
+ | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ | PredicateKind::AliasEq(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))
@@ -1184,6 +1213,8 @@ impl<'tcx> Predicate<'tcx> {
match predicate.skip_binder() {
PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(Clause::Trait(..))
+ | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ | PredicateKind::AliasEq(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))
@@ -1203,7 +1234,9 @@ impl<'tcx> Predicate<'tcx> {
match predicate.skip_binder() {
PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)),
PredicateKind::Clause(Clause::Trait(..))
+ | PredicateKind::Clause(Clause::ConstArgHasType(..))
| PredicateKind::Clause(Clause::Projection(..))
+ | PredicateKind::AliasEq(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))
@@ -1322,7 +1355,7 @@ pub struct OpaqueHiddenType<'tcx> {
}
impl<'tcx> OpaqueHiddenType<'tcx> {
- pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) {
+ pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed {
// Found different concrete types for the opaque type.
let sub_diag = if self.span == other.span {
TypeMismatchReason::ConflictType { span: self.span }
@@ -1334,7 +1367,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
other_ty: other.ty,
other_span: other.span,
sub: sub_diag,
- });
+ })
}
#[instrument(level = "debug", skip(tcx), ret)]
@@ -1382,7 +1415,7 @@ pub struct Placeholder<T> {
pub type PlaceholderRegion = Placeholder<BoundRegionKind>;
-pub type PlaceholderType = Placeholder<BoundVar>;
+pub type PlaceholderType = Placeholder<BoundTyKind>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
@@ -1589,8 +1622,8 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> {
}
}
-impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
- fn try_fold_with<F: ty::fold::FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
+ fn try_fold_with<F: ty::fold::FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
@@ -1602,8 +1635,8 @@ impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
}
}
-impl<'tcx> TypeVisitable<'tcx> for ParamEnv<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.caller_bounds().visit_with(visitor)?;
self.reveal().visit_with(visitor)
}
@@ -1728,7 +1761,7 @@ impl<'tcx> ParamEnv<'tcx> {
/// `where Box<u32>: Copy`, which are clearly never
/// satisfiable. We generally want to behave as if they were true,
/// although the surrounding function is never reachable.
- pub fn and<T: TypeVisitable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
+ pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
match self.reveal() {
Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
@@ -1986,7 +2019,7 @@ impl<'tcx> FieldDef {
/// Returns the type of this field. The resulting type is not normalized. The `subst` is
/// typically obtained via the second field of [`TyKind::Adt`].
pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
- tcx.bound_type_of(self.did).subst(tcx, subst)
+ tcx.type_of(self.did).subst(tcx, subst)
}
/// Computes the `Ident` of this variant by looking up the `Span`
@@ -2038,6 +2071,12 @@ pub enum ImplOverlapKind {
Issue33140,
}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
+pub enum ImplTraitInTraitData {
+ Trait { fn_def_id: DefId, opaque_def_id: DefId },
+ Impl { fn_def_id: DefId },
+}
+
impl<'tcx> TyCtxt<'tcx> {
pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
self.typeck(self.hir().body_owner_def_id(body))
@@ -2167,7 +2206,7 @@ impl<'tcx> TyCtxt<'tcx> {
Some(Ident::new(def, span))
}
- pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> {
+ pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
Some(self.associated_item(def_id))
} else {
@@ -2357,15 +2396,17 @@ impl<'tcx> TyCtxt<'tcx> {
self.trait_def(trait_def_id).has_auto_impl
}
+ /// Returns `true` if this is coinductive, either because it is
+ /// an auto trait or because it has the `#[rustc_coinductive]` attribute.
+ pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool {
+ self.trait_def(trait_def_id).is_coinductive
+ }
+
/// 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)
- }
-
/// Returns layout of a generator. Layout might be unavailable if the
/// generator is tainted by errors.
pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> {
@@ -2396,15 +2437,30 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
let parent = self.parent(def_id);
- if let DefKind::Impl = self.def_kind(parent) {
+ if let DefKind::Impl { .. } = self.def_kind(parent) {
return Some(parent);
}
}
None
}
- /// If the given `DefId` belongs to a trait that was automatically derived, returns `true`.
- pub fn is_builtin_derive(self, def_id: DefId) -> bool {
+ /// Check if the given `DefId` is `#\[automatically_derived\]`, *and*
+ /// whether it was produced by expanding a builtin derive macro.
+ pub fn is_builtin_derived(self, def_id: DefId) -> bool {
+ if self.is_automatically_derived(def_id)
+ && let Some(def_id) = def_id.as_local()
+ && let outer = self.def_span(def_id).ctxt().outer_expn_data()
+ && matches!(outer.kind, ExpnKind::Macro(MacroKind::Derive, _))
+ && self.has_attr(outer.macro_def_id.unwrap(), sym::rustc_builtin_macro)
+ {
+ true
+ } else {
+ false
+ }
+ }
+
+ /// Check if the given `DefId` is `#\[automatically_derived\]`.
+ pub fn is_automatically_derived(self, def_id: DefId) -> bool {
self.has_attr(def_id, sym::automatically_derived)
}
@@ -2437,6 +2493,7 @@ impl<'tcx> TyCtxt<'tcx> {
ident
}
+ // FIXME(vincenzoapalzzo): move the HirId to a LocalDefId
pub fn adjust_ident_and_get_scope(
self,
mut ident: Ident,
@@ -2470,10 +2527,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- pub fn is_object_safe(self, key: DefId) -> bool {
- self.object_safety_violations(key).is_empty()
- }
-
#[inline]
pub fn is_const_fn_raw(self, def_id: DefId) -> bool {
matches!(
@@ -2494,6 +2547,34 @@ impl<'tcx> TyCtxt<'tcx> {
}
def_id
}
+
+ pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
+ if self.def_kind(def_id) != DefKind::AssocFn {
+ return false;
+ }
+
+ let Some(item) = self.opt_associated_item(def_id) else { return false; };
+ if item.container != ty::AssocItemContainer::ImplContainer {
+ return false;
+ }
+
+ let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
+
+ // FIXME(RPITIT): This does a somewhat manual walk through the signature
+ // of the trait fn to look for any RPITITs, but that's kinda doing a lot
+ // of work. We can probably remove this when we refactor RPITITs to be
+ // associated types.
+ self.fn_sig(trait_item_def_id).subst_identity().skip_binder().output().walk().any(|arg| {
+ if let ty::GenericArgKind::Type(ty) = arg.unpack()
+ && let ty::Alias(ty::Projection, data) = ty.kind()
+ && self.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
+ {
+ true
+ } else {
+ false
+ }
+ })
+ }
}
/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition.
@@ -2619,7 +2700,7 @@ impl<'tcx> fmt::Debug for SymbolName<'tcx> {
}
#[derive(Debug, Default, Copy, Clone)]
-pub struct FoundRelationships {
+pub struct InferVarInfo {
/// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo`
/// obligation, where:
///
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index ee13920d5..7c59879a1 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -7,16 +7,14 @@
//! `normalize_generic_arg_after_erasing_regions` query for each type
//! or constant found within. (This underlying query is what is cached.)
-use crate::mir;
use crate::traits::query::NoSolution;
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
-use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt};
+use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
#[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
pub enum NormalizationError<'tcx> {
Type(Ty<'tcx>),
Const(ty::Const<'tcx>),
- ConstantKind(mir::ConstantKind<'tcx>),
}
impl<'tcx> NormalizationError<'tcx> {
@@ -24,7 +22,6 @@ impl<'tcx> NormalizationError<'tcx> {
match self {
NormalizationError::Type(t) => format!("{}", t),
NormalizationError::Const(c) => format!("{}", c),
- NormalizationError::ConstantKind(ck) => format!("{}", ck),
}
}
}
@@ -38,7 +35,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[tracing::instrument(level = "debug", skip(self, param_env))]
pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
@@ -70,7 +67,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: T,
) -> Result<T, NormalizationError<'tcx>>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
@@ -107,7 +104,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: ty::Binder<'tcx, T>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let value = self.erase_late_bound_regions(value);
self.normalize_erasing_regions(param_env, value)
@@ -127,7 +124,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: ty::Binder<'tcx, T>,
) -> Result<T, NormalizationError<'tcx>>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let value = self.erase_late_bound_regions(value);
self.try_normalize_erasing_regions(param_env, value)
@@ -145,7 +142,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: T,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"subst_and_normalize_erasing_regions(\
@@ -169,7 +166,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: T,
) -> Result<T, NormalizationError<'tcx>>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"subst_and_normalize_erasing_regions(\
@@ -196,14 +193,14 @@ impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
let arg = self.param_env.and(arg);
self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!(
- "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead",
- arg.value
- ))
+ "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead",
+ arg.value
+ ))
}
}
-impl<'tcx> TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for NormalizeAfterErasingRegionsFolder<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
@@ -238,10 +235,10 @@ impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> {
}
}
-impl<'tcx> FallibleTypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> {
+impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for TryNormalizeAfterErasingRegionsFolder<'tcx> {
type Error = NormalizationError<'tcx>;
- fn tcx(&self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 98cd92007..751f3066c 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -3,6 +3,7 @@ use crate::ty::fold::{TypeFolder, TypeSuperFoldable};
use crate::ty::subst::{GenericArg, GenericArgKind};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_data_structures::fx::FxHashMap;
+use rustc_span::def_id::DefId;
use rustc_span::Span;
/// Converts generic params of a TypeFoldable from one
@@ -47,10 +48,51 @@ impl<'tcx> ReverseMapper<'tcx> {
assert!(!self.do_not_error);
kind.fold_with(self)
}
+
+ fn fold_closure_substs(
+ &mut self,
+ def_id: DefId,
+ substs: ty::SubstsRef<'tcx>,
+ ) -> ty::SubstsRef<'tcx> {
+ // I am a horrible monster and I pray for death. When
+ // we encounter a closure here, it is always a closure
+ // from within the function that we are currently
+ // type-checking -- one that is now being encapsulated
+ // in an opaque type. Ideally, we would
+ // go through the types/lifetimes that it references
+ // and treat them just like we would any other type,
+ // which means we would error out if we find any
+ // reference to a type/region that is not in the
+ // "reverse map".
+ //
+ // **However,** in the case of closures, there is a
+ // somewhat subtle (read: hacky) consideration. The
+ // problem is that our closure types currently include
+ // all the lifetime parameters declared on the
+ // enclosing function, even if they are unused by the
+ // closure itself. We can't readily filter them out,
+ // so here we replace those values with `'empty`. This
+ // can't really make a difference to the rest of the
+ // compiler; those regions are ignored for the
+ // outlives relation, and hence don't affect trait
+ // selection or auto traits, and they are erased
+ // during codegen.
+
+ let generics = self.tcx.generics_of(def_id);
+ self.tcx.mk_substs_from_iter(substs.iter().enumerate().map(|(index, kind)| {
+ if index < generics.parent_count {
+ // Accommodate missing regions in the parent kinds...
+ self.fold_kind_no_missing_regions_error(kind)
+ } else {
+ // ...but not elsewhere.
+ self.fold_kind_normally(kind)
+ }
+ }))
+ }
}
-impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
@@ -67,6 +109,8 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
// them.
ty::ReErased => return r,
+ ty::ReError(_) => return r,
+
// The regions that we expect from borrow checking.
ty::ReEarlyBound(_) | ty::ReFree(_) => {}
@@ -83,20 +127,21 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
None if self.do_not_error => self.tcx.lifetimes.re_static,
None => {
- self.tcx
+ let e = self
+ .tcx
.sess
.struct_span_err(self.span, "non-defining opaque type use in defining scope")
.span_label(
self.span,
format!(
"lifetime `{}` is part of concrete type but not used in \
- parameter list of the `impl Trait` type alias",
+ parameter list of the `impl Trait` type alias",
r
),
)
.emit();
- self.tcx().lifetimes.re_static
+ self.interner().mk_re_error(e)
}
}
}
@@ -104,59 +149,20 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
match *ty.kind() {
ty::Closure(def_id, substs) => {
- // I am a horrible monster and I pray for death. When
- // we encounter a closure here, it is always a closure
- // from within the function that we are currently
- // type-checking -- one that is now being encapsulated
- // in an opaque type. Ideally, we would
- // go through the types/lifetimes that it references
- // and treat them just like we would any other type,
- // which means we would error out if we find any
- // reference to a type/region that is not in the
- // "reverse map".
- //
- // **However,** in the case of closures, there is a
- // somewhat subtle (read: hacky) consideration. The
- // problem is that our closure types currently include
- // all the lifetime parameters declared on the
- // enclosing function, even if they are unused by the
- // closure itself. We can't readily filter them out,
- // so here we replace those values with `'empty`. This
- // can't really make a difference to the rest of the
- // compiler; those regions are ignored for the
- // outlives relation, and hence don't affect trait
- // selection or auto traits, and they are erased
- // during codegen.
-
- let generics = self.tcx.generics_of(def_id);
- let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
- if index < generics.parent_count {
- // Accommodate missing regions in the parent kinds...
- self.fold_kind_no_missing_regions_error(kind)
- } else {
- // ...but not elsewhere.
- self.fold_kind_normally(kind)
- }
- }));
-
+ let substs = self.fold_closure_substs(def_id, substs);
self.tcx.mk_closure(def_id, substs)
}
ty::Generator(def_id, substs, movability) => {
- let generics = self.tcx.generics_of(def_id);
- let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
- if index < generics.parent_count {
- // Accommodate missing regions in the parent kinds...
- self.fold_kind_no_missing_regions_error(kind)
- } else {
- // ...but not elsewhere.
- self.fold_kind_normally(kind)
- }
- }));
-
+ let substs = self.fold_closure_substs(def_id, substs);
self.tcx.mk_generator(def_id, substs, movability)
}
+ ty::GeneratorWitnessMIR(def_id, substs) => {
+ let substs = self.fold_closure_substs(def_id, substs);
+ self.tcx.mk_generator_witness_mir(def_id, substs)
+ }
+
ty::Param(param) => {
// Look it up in the substitution list.
match self.map.get(&ty.into()).map(|k| k.unpack()) {
@@ -180,7 +186,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
.emit();
}
- self.tcx().ty_error()
+ self.interner().ty_error_misc()
}
}
}
@@ -208,7 +214,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
});
}
- self.tcx().const_error(ct.ty())
+ self.interner().const_error(ct.ty())
}
}
}
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 24f3d1acf..8849e7eab 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -57,7 +57,7 @@ trivially_parameterized_over_tcx! {
crate::metadata::ModChild,
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
crate::middle::exported_symbols::SymbolExportInfo,
- crate::middle::resolve_lifetime::ObjectLifetimeDefault,
+ crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
crate::mir::ConstQualifs,
ty::AssocItemContainer,
ty::DeducedParamAttrs,
@@ -81,6 +81,8 @@ trivially_parameterized_over_tcx! {
rustc_hir::IsAsync,
rustc_hir::LangItem,
rustc_hir::def::DefKind,
+ rustc_hir::def::DocLinkResMap,
+ rustc_hir::def_id::DefId,
rustc_hir::def_id::DefIndex,
rustc_hir::definitions::DefKey,
rustc_index::bit_set::BitSet<u32>,
@@ -117,6 +119,7 @@ macro_rules! parameterized_over_tcx {
parameterized_over_tcx! {
crate::middle::exported_symbols::ExportedSymbol,
crate::mir::Body,
+ crate::mir::GeneratorLayout,
ty::Ty,
ty::FnSig,
ty::GenericPredicates,
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index c302c4611..021c20b58 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -115,7 +115,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 self_ty = self.tcx().type_of(def_id);
let impl_trait_ref = self.tcx().impl_trait_ref(def_id);
let (self_ty, impl_trait_ref) = if substs.len() >= generics.count() {
(
@@ -265,6 +265,7 @@ fn characteristic_def_id_of_type_cached<'a>(
ty::FnDef(def_id, _)
| ty::Closure(def_id, _)
| ty::Generator(def_id, _, _)
+ | ty::GeneratorWitnessMIR(def_id, _)
| ty::Foreign(def_id) => Some(def_id),
ty::Bool
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index ae7c20fff..6a053c368 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,7 +1,7 @@
use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
use crate::ty::{
self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
- TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
+ TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
use crate::ty::{GenericArg, GenericArgKind};
use rustc_apfloat::ieee::{Double, Single};
@@ -22,7 +22,6 @@ use rustc_target::spec::abi::Abi;
use smallvec::SmallVec;
use std::cell::Cell;
-use std::char;
use std::collections::BTreeMap;
use std::fmt::{self, Write as _};
use std::iter;
@@ -183,7 +182,7 @@ impl<'tcx> RegionHighlightMode<'tcx> {
/// Convenience wrapper for `highlighting_region`.
pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) {
- self.highlighting_region(self.tcx.mk_region(ty::ReVar(vid)), number)
+ self.highlighting_region(self.tcx.mk_re_var(vid), number)
}
/// Returns `Some(n)` with the number to use for the given region, if any.
@@ -226,7 +225,7 @@ pub trait PrettyPrinter<'tcx>:
fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
value.as_ref().skip_binder().print(self)
}
@@ -237,7 +236,7 @@ pub trait PrettyPrinter<'tcx>:
f: F,
) -> Result<Self, Self::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
f(value.as_ref().skip_binder(), self)
}
@@ -675,8 +674,12 @@ pub trait PrettyPrinter<'tcx>:
p!(")")
}
ty::FnDef(def_id, substs) => {
- let sig = self.tcx().bound_fn_sig(def_id).subst(self.tcx(), substs);
- p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
+ if NO_QUERIES.with(|q| q.get()) {
+ p!(print_def_path(def_id, substs));
+ } else {
+ let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
+ p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
+ }
}
ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
ty::Infer(infer_ty) => {
@@ -698,8 +701,10 @@ pub trait PrettyPrinter<'tcx>:
ty::Error(_) => p!("[type error]"),
ty::Param(ref param_ty) => p!(print(param_ty)),
ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
- ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
- ty::BoundTyKind::Param(p) => p!(write("{}", p)),
+ ty::BoundTyKind::Anon(bv) => {
+ self.pretty_print_bound_var(debruijn, ty::BoundVar::from_u32(bv))?
+ }
+ ty::BoundTyKind::Param(_, s) => p!(write("{}", s)),
},
ty::Adt(def, substs) => {
p!(print_def_path(def.did(), substs));
@@ -730,15 +735,18 @@ pub trait PrettyPrinter<'tcx>:
p!(print(data))
}
}
- ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
+ ty::Placeholder(placeholder) => match placeholder.name {
+ ty::BoundTyKind::Anon(_) => p!(write("Placeholder({:?})", placeholder)),
+ ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
+ },
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
// only affect certain debug messages (e.g. messages printed
// from `rustc_middle::ty` during the computation of `tcx.predicates_of`),
// and should have no effect on any compiler output.
- if self.should_print_verbose() || NO_QUERIES.with(|q| q.get()) {
+ if self.should_print_verbose() {
+ // FIXME(eddyb) print this with `print_def_path`.
p!(write("Opaque({:?}, {:?})", def_id, substs));
return Ok(self);
}
@@ -746,8 +754,10 @@ pub trait PrettyPrinter<'tcx>:
let parent = self.tcx().parent(def_id);
match self.tcx().def_kind(parent) {
DefKind::TyAlias | DefKind::AssocTy => {
+ // NOTE: I know we should check for NO_QUERIES here, but it's alright.
+ // `type_of` on a type alias or assoc type should never cause a cycle.
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
- *self.tcx().type_of(parent).kind()
+ *self.tcx().type_of(parent).subst_identity().kind()
{
if d == def_id {
// If the type alias directly starts with the `impl` of the
@@ -760,7 +770,14 @@ pub trait PrettyPrinter<'tcx>:
p!(print_def_path(def_id, substs));
return Ok(self);
}
- _ => return self.pretty_print_opaque_impl_type(def_id, substs),
+ _ => {
+ if NO_QUERIES.with(|q| q.get()) {
+ p!(print_def_path(def_id, &[]));
+ return Ok(self);
+ } else {
+ return self.pretty_print_opaque_impl_type(def_id, substs);
+ }
+ }
}
}
ty::Str => p!("str"),
@@ -811,6 +828,28 @@ pub trait PrettyPrinter<'tcx>:
ty::GeneratorWitness(types) => {
p!(in_binder(&types));
}
+ ty::GeneratorWitnessMIR(did, substs) => {
+ p!(write("["));
+ if !self.tcx().sess.verbose() {
+ p!("generator witness");
+ // FIXME(eddyb) should use `def_span`.
+ if let Some(did) = did.as_local() {
+ let span = self.tcx().def_span(did);
+ 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)
+ ));
+ } else {
+ p!(write("@"), print_def_path(did, substs));
+ }
+ } else {
+ p!(print_def_path(did, substs));
+ }
+
+ p!("]")
+ }
ty::Closure(did, substs) => {
p!(write("["));
if !self.should_print_verbose() {
@@ -1062,9 +1101,11 @@ pub trait PrettyPrinter<'tcx>:
write!(self, "Sized")?;
}
- for re in lifetimes {
- write!(self, " + ")?;
- self = self.print_region(re)?;
+ if !FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ for re in lifetimes {
+ write!(self, " + ")?;
+ self = self.print_region(re)?;
+ }
}
Ok(self)
@@ -1171,7 +1212,7 @@ pub trait PrettyPrinter<'tcx>:
// in order to place the projections inside the `<...>`.
if !resugared {
// Use a type that can't appear in defaults of type parameters.
- let dummy_cx = cx.tcx().mk_ty_infer(ty::FreshTy(0));
+ let dummy_cx = cx.tcx().mk_fresh_ty(0);
let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
let args = cx
@@ -1992,7 +2033,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
self.pretty_in_binder(value)
}
@@ -2003,7 +2044,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
f: C,
) -> Result<Self, Self::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
self.pretty_wrap_binder(value, f)
}
@@ -2048,6 +2089,10 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
return true;
}
+ if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ return false;
+ }
+
let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
match *region {
@@ -2071,7 +2116,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
ty::ReVar(_) if identify_regions => true,
- ty::ReVar(_) | ty::ReErased => false,
+ ty::ReVar(_) | ty::ReErased | ty::ReError(_) => false,
ty::ReStatic => true,
}
@@ -2151,6 +2196,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
}
ty::ReVar(_) => {}
ty::ReErased => {}
+ ty::ReError(_) => {}
ty::ReStatic => {
p!("'static");
return Ok(self);
@@ -2178,12 +2224,12 @@ struct RegionFolder<'a, 'tcx> {
),
}
-impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -2228,7 +2274,7 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
};
if let ty::ReLateBound(debruijn1, br) = *region {
assert_eq!(debruijn1, ty::INNERMOST);
- self.tcx.mk_region(ty::ReLateBound(self.current_index, br))
+ self.tcx.mk_re_late_bound(self.current_index, br)
} else {
region
}
@@ -2243,7 +2289,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
value: &ty::Binder<'tcx, T>,
) -> Result<(Self, T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
fn name_by_region_index(
index: usize,
@@ -2324,6 +2370,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
} else {
let tcx = self.tcx;
+ let trim_path = FORCE_TRIMMED_PATH.with(|flag| flag.get());
// Closure used in `RegionFolder` to create names for anonymous late-bound
// regions. We use two `DebruijnIndex`es (one for the currently folded
// late-bound region and the other for the binder level) to determine
@@ -2339,10 +2386,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name);
- return tcx.mk_region(ty::ReLateBound(
+ return tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
- ));
+ );
}
}
@@ -2354,10 +2401,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = ty::BrNamed(def_id, name);
- return tcx.mk_region(ty::ReLateBound(
+ return tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
- ));
+ );
}
}
@@ -2367,10 +2414,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = br.kind;
- return tcx.mk_region(ty::ReLateBound(
+ return tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
- ));
+ );
}
}
@@ -2378,9 +2425,11 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
}
};
- start_or_continue(&mut self, "for<", ", ");
- do_continue(&mut self, name);
- tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
+ if !trim_path {
+ start_or_continue(&mut self, "for<", ", ");
+ do_continue(&mut self, name);
+ }
+ tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })
};
let mut folder = RegionFolder {
tcx,
@@ -2390,7 +2439,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
};
let new_value = value.clone().skip_binder().fold_with(&mut folder);
let region_map = folder.region_map;
- start_or_continue(&mut self, "", "> ");
+ if !trim_path {
+ start_or_continue(&mut self, "", "> ");
+ }
(new_value, region_map)
};
@@ -2401,7 +2452,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
pub fn pretty_in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, fmt::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
let old_region_index = self.region_index;
let (new, new_value, _) = self.name_all_regions(value)?;
@@ -2417,7 +2468,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
f: C,
) -> Result<Self, fmt::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
let old_region_index = self.region_index;
let (new, new_value, _) = self.name_all_regions(value)?;
@@ -2429,7 +2480,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
fn prepare_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
struct RegionNameCollector<'tcx> {
used_region_names: FxHashSet<Symbol>,
@@ -2445,7 +2496,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
}
}
- impl<'tcx> ty::visit::TypeVisitor<'tcx> for RegionNameCollector<'tcx> {
+ impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for RegionNameCollector<'tcx> {
type BreakTy = ();
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -2482,7 +2533,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T>
where
- T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
type Output = P;
type Error = P::Error;
@@ -2648,7 +2699,7 @@ define_print_and_forward_display! {
ty::ExistentialTraitRef<'tcx> {
// Use a type that can't appear in defaults of type parameters.
- let dummy_self = cx.tcx().mk_ty_infer(ty::FreshTy(0));
+ let dummy_self = cx.tcx().mk_fresh_ty(0);
let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
p!(print(trait_ref.print_only_trait_path()))
}
@@ -2774,15 +2825,18 @@ define_print_and_forward_display! {
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => p!(print(predicate)),
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(predicate)) => p!(print(predicate)),
ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => p!(print(predicate)),
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ p!("the constant `", print(ct), "` has type `", print(ty), "`")
+ },
ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"),
ty::PredicateKind::ObjectSafe(trait_def_id) => {
p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
}
- ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => {
- p!("the closure `",
+ ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => p!(
+ "the closure `",
print_value_path(closure_def_id, &[]),
- write("` implements the trait `{}`", kind))
- }
+ write("` implements the trait `{}`", kind)
+ ),
ty::PredicateKind::ConstEvaluatable(ct) => {
p!("the constant `", print(ct), "` can be evaluated")
}
@@ -2793,6 +2847,7 @@ define_print_and_forward_display! {
p!("the type `", print(ty), "` is found in the environment")
}
ty::PredicateKind::Ambiguous => p!("ambiguous"),
+ ty::PredicateKind::AliasEq(t1, t2) => p!(print(t1), " == ", print(t2)),
}
}
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index 9d4ee22a7..2bc51baf8 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -1,3 +1,5 @@
+#![allow(unused_parens)]
+
use crate::dep_graph;
use crate::infer::canonical::{self, Canonical};
use crate::lint::LintExpectation;
@@ -6,7 +8,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use crate::middle::lib_features::LibFeatures;
use crate::middle::privacy::EffectiveVisibilities;
-use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes};
+use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
use crate::middle::stability::{self, DeprecationEntry};
use crate::mir;
use crate::mir::interpret::GlobalId;
@@ -30,11 +32,12 @@ use crate::traits::specialization_graph;
use crate::traits::{self, ImplSource};
use crate::ty::context::TyCtxtFeed;
use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::layout::TyAndLayout;
+use crate::ty::layout::ValidityRequirement;
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::util::AlwaysRequiresDrop;
use crate::ty::GeneratorDiagnosticData;
use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams};
+use rustc_arena::TypedArena;
use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_attr as attr;
@@ -42,10 +45,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::WorkerLocal;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{DefKind, DocLinkResMap};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::hir_id::OwnerId;
use rustc_hir::lang_items::{LangItem, LanguageItems};
@@ -60,6 +64,7 @@ use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi;
use rustc_target::spec::PanicStrategy;
+use std::mem;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;
@@ -67,6 +72,12 @@ use std::sync::Arc;
pub(crate) use rustc_query_system::query::QueryJobId;
use rustc_query_system::query::*;
+#[derive(Default)]
+pub struct QuerySystem<'tcx> {
+ pub arenas: QueryArenas<'tcx>,
+ pub caches: QueryCaches<'tcx>,
+}
+
#[derive(Copy, Clone)]
pub struct TyCtxtAt<'tcx> {
pub tcx: TyCtxt<'tcx>,
@@ -106,30 +117,21 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
-/// Helper for `TyCtxtEnsure` to avoid a closure.
-#[inline(always)]
-fn noop<T>(_: &T) {}
-
-/// Helper to ensure that queries only return `Copy` types.
-#[inline(always)]
-fn copy<T: Copy>(x: &T) -> T {
- *x
-}
-
macro_rules! query_helper_param_ty {
(DefId) => { impl IntoQueryParam<DefId> };
+ (LocalDefId) => { impl IntoQueryParam<LocalDefId> };
($K:ty) => { $K };
}
-macro_rules! query_storage {
- ([][$K:ty, $V:ty]) => {
- <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache
+macro_rules! query_if_arena {
+ ([] $arena:tt $no_arena:tt) => {
+ $no_arena
};
- ([(arena_cache) $($rest:tt)*][$K:ty, $V:ty]) => {
- <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::ArenaCache
+ ([(arena_cache) $($rest:tt)*] $arena:tt $no_arena:tt) => {
+ $arena
};
- ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
- query_storage!([$($modifiers)*][$($args)*])
+ ([$other:tt $($modifiers:tt)*]$($args:tt)*) => {
+ query_if_arena!([$($modifiers)*]$($args)*)
};
}
@@ -141,7 +143,7 @@ macro_rules! separate_provide_extern_decl {
for<'tcx> fn(
TyCtxt<'tcx>,
query_keys::$name<'tcx>,
- ) -> query_values::$name<'tcx>
+ ) -> query_provided::$name<'tcx>
};
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
separate_provide_extern_decl!([$($modifiers)*][$($args)*])
@@ -199,17 +201,71 @@ macro_rules! define_callbacks {
$(pub type $name<'tcx> = $V;)*
}
+
+ /// This module specifies the type returned from query providers and the type used for
+ /// decoding. For regular queries this is the declared returned type `V`, but
+ /// `arena_cache` will use `<V as Deref>::Target` instead.
#[allow(nonstandard_style, unused_lifetimes)]
- pub mod query_storage {
+ pub mod query_provided {
use super::*;
- $(pub type $name<'tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
+ $(
+ pub type $name<'tcx> = query_if_arena!([$($modifiers)*] (<$V as Deref>::Target) ($V));
+ )*
}
+
+ /// This module has a function per query which takes a `query_provided` value and coverts
+ /// it to a regular `V` value by allocating it on an arena if the query has the
+ /// `arena_cache` modifier. This will happen when computing the query using a provider or
+ /// decoding a stored result.
#[allow(nonstandard_style, unused_lifetimes)]
- pub mod query_stored {
+ pub mod query_provided_to_value {
use super::*;
- $(pub type $name<'tcx> = <query_storage::$name<'tcx> as QueryStorage>::Stored;)*
+ $(
+ #[inline(always)]
+ pub fn $name<'tcx>(
+ _tcx: TyCtxt<'tcx>,
+ value: query_provided::$name<'tcx>,
+ ) -> query_values::$name<'tcx> {
+ query_if_arena!([$($modifiers)*]
+ {
+ if mem::needs_drop::<query_provided::$name<'tcx>>() {
+ &*_tcx.query_system.arenas.$name.alloc(value)
+ } else {
+ &*_tcx.arena.dropless.alloc(value)
+ }
+ }
+ (value)
+ )
+ }
+ )*
+ }
+ #[allow(nonstandard_style, unused_lifetimes)]
+ pub mod query_storage {
+ use super::*;
+
+ $(
+ pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache;
+ )*
+ }
+
+ pub struct QueryArenas<'tcx> {
+ $($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*]
+ (WorkerLocal<TypedArena<<$V as Deref>::Target>>)
+ ()
+ ),)*
+ }
+
+ impl Default for QueryArenas<'_> {
+ fn default() -> Self {
+ Self {
+ $($name: query_if_arena!([$($modifiers)*]
+ (WorkerLocal::new(|_| Default::default()))
+ ()
+ ),)*
+ }
+ }
}
#[derive(Default)]
@@ -224,14 +280,10 @@ macro_rules! define_callbacks {
let key = key.into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
- let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop);
-
- match cached {
- Ok(()) => return,
- Err(()) => (),
- }
-
- self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure);
+ match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
+ Some(_) => return,
+ None => self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure),
+ };
})*
}
@@ -239,7 +291,7 @@ macro_rules! define_callbacks {
$($(#[$attr])*
#[inline(always)]
#[must_use]
- pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
+ pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V
{
self.at(DUMMY_SP).$name(key)
})*
@@ -248,19 +300,15 @@ macro_rules! define_callbacks {
impl<'tcx> TyCtxtAt<'tcx> {
$($(#[$attr])*
#[inline(always)]
- pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
+ pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V
{
let key = key.into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
- let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, copy);
-
- match cached {
- Ok(value) => return value,
- Err(()) => (),
+ match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
+ Some(value) => value,
+ None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(),
}
-
- self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap()
})*
}
@@ -268,7 +316,7 @@ macro_rules! define_callbacks {
$(pub $name: for<'tcx> fn(
TyCtxt<'tcx>,
query_keys::$name<'tcx>,
- ) -> query_values::$name<'tcx>,)*
+ ) -> query_provided::$name<'tcx>,)*
}
pub struct ExternProviders {
@@ -281,8 +329,9 @@ macro_rules! define_callbacks {
Providers {
$($name: |_, key| bug!(
- "`tcx.{}({:?})` is not supported for {} crate;\n
- hint: Queries can be either made to the local crate, or the external crate. This error means you tried to use it for one that's not supported.\n
+ "`tcx.{}({:?})` is not supported for {} crate;\n\
+ hint: Queries can be either made to the local crate, or the external crate. \
+ This error means you tried to use it for one that's not supported.\n\
If that's not the case, {} was likely never assigned to a provider function.\n",
stringify!($name),
key,
@@ -323,7 +372,7 @@ macro_rules! define_callbacks {
span: Span,
key: query_keys::$name<'tcx>,
mode: QueryMode,
- ) -> Option<query_stored::$name<'tcx>>;)*
+ ) -> Option<$V>;)*
}
};
}
@@ -345,34 +394,34 @@ macro_rules! define_feedable {
$(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
$(#[$attr])*
#[inline(always)]
- pub fn $name(self, value: $V) -> query_stored::$name<'tcx> {
+ pub fn $name(self, value: query_provided::$name<'tcx>) -> $V {
let key = self.key().into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
let tcx = self.tcx;
- let cache = &tcx.query_caches.$name;
-
- let cached = try_get_cached(tcx, cache, &key, copy);
+ let value = query_provided_to_value::$name(tcx, value);
+ let cache = &tcx.query_system.caches.$name;
- match cached {
- Ok(old) => {
+ match try_get_cached(tcx, cache, &key) {
+ Some(old) => {
bug!(
"Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
stringify!($name),
+ )
+ }
+ None => {
+ let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
+ let dep_node_index = tcx.dep_graph.with_feed_task(
+ dep_node,
+ tcx,
+ key,
+ &value,
+ hash_result!([$($modifiers)*]),
);
+ cache.complete(key, value, dep_node_index);
+ value
}
- Err(()) => (),
}
-
- let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
- let dep_node_index = tcx.dep_graph.with_feed_task(
- dep_node,
- tcx,
- key,
- &value,
- hash_result!([$($modifiers)*]),
- );
- cache.complete(key, value, dep_node_index)
}
})*
}
@@ -418,6 +467,13 @@ mod sealed {
}
}
+ impl IntoQueryParam<LocalDefId> for OwnerId {
+ #[inline(always)]
+ fn into_query_param(self) -> LocalDefId {
+ self.def_id
+ }
+ }
+
impl IntoQueryParam<DefId> for LocalDefId {
#[inline(always)]
fn into_query_param(self) -> DefId {
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 65fd8d975..3fc5f5bed 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -9,7 +9,6 @@ use crate::ty::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldabl
use crate::ty::{GenericArg, GenericArgKind, SubstsRef};
use rustc_hir as ast;
use rustc_hir::def_id::DefId;
-use rustc_span::DUMMY_SP;
use rustc_target::spec::abi;
use std::iter;
@@ -106,7 +105,7 @@ pub trait TypeRelation<'tcx>: Sized {
T: Relate<'tcx>;
}
-pub trait Relate<'tcx>: TypeFoldable<'tcx> + PartialEq + Copy {
+pub trait Relate<'tcx>: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: Self,
@@ -145,7 +144,7 @@ pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>(
a_subst: SubstsRef<'tcx>,
b_subst: SubstsRef<'tcx>,
) -> RelateResult<'tcx, SubstsRef<'tcx>> {
- relation.tcx().mk_substs(iter::zip(a_subst, b_subst).map(|(a, b)| {
+ relation.tcx().mk_substs_from_iter(iter::zip(a_subst, b_subst).map(|(a, b)| {
relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)
}))
}
@@ -164,8 +163,7 @@ pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>(
let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
let variance = variances[i];
let variance_info = if variance == ty::Invariant && fetch_ty_for_diag {
- let ty =
- *cached_ty.get_or_insert_with(|| tcx.bound_type_of(ty_def_id).subst(tcx, a_subst));
+ let ty = *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
} else {
ty::VarianceDiagInfo::default()
@@ -173,7 +171,7 @@ pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>(
relation.relate_with_variance(variance, variance_info, a, b)
});
- tcx.mk_substs(params)
+ tcx.mk_substs_from_iter(params)
}
impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
@@ -224,7 +222,7 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
r => r,
});
Ok(ty::FnSig {
- inputs_and_output: tcx.mk_type_list(inputs_and_output)?,
+ inputs_and_output: tcx.mk_type_list_from_iter(inputs_and_output)?,
c_variadic: a.c_variadic,
unsafety,
abi,
@@ -354,7 +352,8 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
) -> RelateResult<'tcx, GeneratorWitness<'tcx>> {
assert_eq!(a.0.len(), b.0.len());
let tcx = relation.tcx();
- let types = tcx.mk_type_list(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?;
+ let types =
+ tcx.mk_type_list_from_iter(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?;
Ok(GeneratorWitness(types))
}
}
@@ -414,7 +413,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
bug!("bound types encountered in super_relate_tys")
}
- (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error_with_guaranteed(guar)),
+ (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)),
(&ty::Never, _)
| (&ty::Char, _)
@@ -443,12 +442,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
if a_repr == b_repr =>
{
let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| {
- relation.relate_with_variance(
- ty::Contravariant,
- ty::VarianceDiagInfo::default(),
- a_region,
- b_region,
- )
+ relation.relate(a_region, b_region)
})?;
Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr))
}
@@ -473,6 +467,16 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
Ok(tcx.mk_generator_witness(types))
}
+ (&ty::GeneratorWitnessMIR(a_id, a_substs), &ty::GeneratorWitnessMIR(b_id, b_substs))
+ if a_id == b_id =>
+ {
+ // All GeneratorWitness types with the same id represent
+ // the (anonymous) type of the same generator expression. So
+ // all of their regions should be equated.
+ let substs = relation.relate(a_substs, b_substs)?;
+ Ok(tcx.mk_generator_witness_mir(a_id, substs))
+ }
+
(&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => {
// All Closure types with the same id represent
// the (anonymous) type of the same closure expression. So
@@ -487,12 +491,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
}
(&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
- let r = relation.relate_with_variance(
- ty::Contravariant,
- ty::VarianceDiagInfo::default(),
- a_r,
- b_r,
- )?;
+ let r = relation.relate(a_r, b_r)?;
let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl };
let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl };
let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?;
@@ -502,7 +501,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
(&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => {
let t = relation.relate(a_t, b_t)?;
match relation.relate(sz_a, sz_b) {
- Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))),
+ Ok(sz) => Ok(tcx.mk_array_with_const_len(t, sz)),
Err(err) => {
// Check whether the lengths are both concrete/known values,
// but are unequal, for better diagnostics.
@@ -511,8 +510,8 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
// we however cannot end up with errors in `Relate` during both
// `type_of` and `predicates_of`. This means that evaluating the
// constants should not cause cycle errors here.
- let sz_a = sz_a.try_eval_usize(tcx, relation.param_env());
- let sz_b = sz_b.try_eval_usize(tcx, relation.param_env());
+ let sz_a = sz_a.try_eval_target_usize(tcx, relation.param_env());
+ let sz_b = sz_b.try_eval_target_usize(tcx, relation.param_env());
match (sz_a, sz_b) {
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err(
TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)),
@@ -530,7 +529,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
(&ty::Tuple(as_), &ty::Tuple(bs)) => {
if as_.len() == bs.len() {
- Ok(tcx.mk_tup(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?)
+ Ok(tcx.mk_tup_from_iter(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?)
} else if !(as_.is_empty() || bs.is_empty()) {
Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len())))
} else {
@@ -594,25 +593,6 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
let tcx = relation.tcx();
- let a_ty;
- let b_ty;
- if relation.tcx().features().adt_const_params {
- a_ty = tcx.normalize_erasing_regions(relation.param_env(), a.ty());
- b_ty = tcx.normalize_erasing_regions(relation.param_env(), b.ty());
- } else {
- a_ty = tcx.erase_regions(a.ty());
- b_ty = tcx.erase_regions(b.ty());
- }
- if a_ty != b_ty {
- relation.tcx().sess.delay_span_bug(
- DUMMY_SP,
- &format!(
- "cannot relate constants ({:?}, {:?}) of different types: {} != {}",
- a, b, a_ty, b_ty
- ),
- );
- }
-
// HACK(const_generics): We still need to eagerly evaluate consts when
// relating them because during `normalize_param_env_or_error`,
// we may relate an evaluated constant in a obligation against
@@ -629,6 +609,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
b = tcx.expand_abstract_consts(b);
}
+ debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
+
// Currently, the values that can be unified are primitive types,
// and those that derive both `PartialEq` and `Eq`, corresponding
// to structural-match types.
@@ -665,36 +647,34 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
// FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
// exprs? Should we care about that?
+ // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
+ // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
+ // of as being generic over the argument types, however this is implicit so these types don't get
+ // related when we relate the substs of the item this const arg is for.
let expr = match (ae, be) {
- (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br))
- if a_op == b_op && al.ty() == bl.ty() && ar.ty() == br.ty() =>
- {
+ (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => {
+ r.relate(al.ty(), bl.ty())?;
+ r.relate(ar.ty(), br.ty())?;
Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?)
}
- (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv))
- if a_op == b_op && av.ty() == bv.ty() =>
- {
+ (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => {
+ r.relate(av.ty(), bv.ty())?;
Expr::UnOp(a_op, r.consts(av, bv)?)
}
- (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt))
- if ak == bk && av.ty() == bv.ty() =>
- {
+ (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => {
+ r.relate(av.ty(), bv.ty())?;
Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?)
}
(Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba))
- if aa.len() == ba.len()
- && af.ty() == bf.ty()
- && aa
- .iter()
- .zip(ba.iter())
- .all(|(a_arg, b_arg)| a_arg.ty() == b_arg.ty()) =>
+ if aa.len() == ba.len() =>
{
+ r.relate(af.ty(), bf.ty())?;
let func = r.consts(af, bf)?;
let mut related_args = Vec::with_capacity(aa.len());
for (a_arg, b_arg) in aa.iter().zip(ba.iter()) {
related_args.push(r.consts(a_arg, b_arg)?);
}
- let related_args = tcx.mk_const_list(related_args.iter());
+ let related_args = tcx.mk_const_list(&related_args);
Expr::FunctionCall(func, related_args)
}
_ => return Err(TypeError::ConstMismatch(expected_found(r, a, b))),
@@ -741,7 +721,7 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
_ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))),
}
});
- tcx.mk_poly_existential_predicates(v)
+ tcx.mk_poly_existential_predicates_from_iter(v)
}
}
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 7d4d35b7f..ef643531b 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -1,6 +1,7 @@
-//! This module contains implements of the `Lift` and `TypeFoldable`
-//! traits for various types in the Rust compiler. Most are written by
-//! hand, though we've recently added some macros and proc-macros to help with the tedium.
+//! This module contains implementations of the `Lift`, `TypeFoldable` and
+//! `TypeVisitable` traits for various types in the Rust compiler. Most are
+//! written by hand, though we've recently added some macros and proc-macros
+//! to help with the tedium.
use crate::mir::interpret;
use crate::mir::{Field, ProjectionKind};
@@ -8,12 +9,11 @@ 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, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
-use rustc_data_structures::functor::IdFunctor;
use rustc_hir::def::Namespace;
use rustc_index::vec::{Idx, IndexVec};
+use rustc_target::abi::TyAndLayout;
use std::fmt;
-use std::mem::ManuallyDrop;
use std::ops::ControlFlow;
use std::rc::Rc;
use std::sync::Arc;
@@ -147,6 +147,7 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
impl<'tcx> fmt::Debug for ty::Clause<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
+ ty::Clause::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"),
ty::Clause::Trait(ref a) => a.fmt(f),
ty::Clause::RegionOutlives(ref pair) => pair.fmt(f),
ty::Clause::TypeOutlives(ref pair) => pair.fmt(f),
@@ -176,6 +177,7 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
write!(f, "TypeWellFormedFromEnv({:?})", ty)
}
ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"),
+ ty::PredicateKind::AliasEq(t1, t2) => write!(f, "AliasEq({t1:?}, {t2:?})"),
}
}
}
@@ -193,16 +195,27 @@ impl<'tcx> fmt::Debug for AliasTy<'tcx> {
// Atomic structs
//
// For things that don't carry any arena-allocated data (and are
-// copy...), just add them to this list.
+// copy...), just add them to one of these lists as appropriat.
-TrivialTypeTraversalAndLiftImpls! {
+// For things for which the type library provides traversal implementations
+// for all Interners, we only need to provide a Lift implementation:
+CloneLiftImpls! {
(),
bool,
usize,
- ::rustc_target::abi::VariantIdx,
+ u16,
u32,
u64,
String,
+ rustc_type_ir::DebruijnIndex,
+}
+
+// For things about which the type library does not know, or does not
+// provide any traversal implementations, we need to provide both a Lift
+// implementation and traversal implementations (the latter only for
+// TyCtxt<'_> interners).
+TrivialTypeTraversalAndLiftImpls! {
+ ::rustc_target::abi::VariantIdx,
crate::middle::region::Scope,
crate::ty::FloatTy,
::rustc_ast::InlineAsmOptions,
@@ -238,6 +251,7 @@ TrivialTypeTraversalAndLiftImpls! {
crate::ty::AssocKind,
crate::ty::AliasKind,
crate::ty::Placeholder<crate::ty::BoundRegionKind>,
+ crate::ty::Placeholder<crate::ty::BoundTyKind>,
crate::ty::ClosureKind,
crate::ty::FreeRegion,
crate::ty::InferTy,
@@ -249,11 +263,11 @@ TrivialTypeTraversalAndLiftImpls! {
crate::ty::UniverseIndex,
crate::ty::Variance,
::rustc_span::Span,
+ ::rustc_span::symbol::Ident,
::rustc_errors::ErrorGuaranteed,
Field,
interpret::Scalar,
rustc_target::abi::Size,
- rustc_type_ir::DebruijnIndex,
ty::BoundVar,
ty::Placeholder<ty::BoundVar>,
}
@@ -356,281 +370,106 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> {
}
///////////////////////////////////////////////////////////////////////////
-// TypeFoldable implementations.
+// Traversal implementations.
/// AdtDefs are basically the same as a DefId.
-impl<'tcx> TypeFoldable<'tcx> for ty::AdtDef<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ _folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for ty::AdtDef<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ _visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
ControlFlow::Continue(())
}
}
-impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
- ) -> Result<(T, U), F::Error> {
- Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
+ ) -> Result<Self, F::Error> {
+ folder.try_fold_binder(self)
}
}
-impl<'tcx, T: TypeVisitable<'tcx>, U: TypeVisitable<'tcx>> TypeVisitable<'tcx> for (T, U) {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.0.visit_with(visitor)?;
- self.1.visit_with(visitor)
+impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ visitor.visit_binder(self)
}
}
-impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> TypeFoldable<'tcx>
- for (A, B, C)
-{
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
+ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
- ) -> Result<(A, B, C), F::Error> {
- Ok((
- self.0.try_fold_with(folder)?,
- self.1.try_fold_with(folder)?,
- self.2.try_fold_with(folder)?,
- ))
+ ) -> Result<Self, F::Error> {
+ self.try_map_bound(|ty| ty.try_fold_with(folder))
}
}
-impl<'tcx, A: TypeVisitable<'tcx>, B: TypeVisitable<'tcx>, C: TypeVisitable<'tcx>>
- TypeVisitable<'tcx> for (A, B, C)
+impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeSuperVisitable<TyCtxt<'tcx>>
+ for ty::Binder<'tcx, T>
{
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.0.visit_with(visitor)?;
- self.1.visit_with(visitor)?;
- self.2.visit_with(visitor)
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
+ self.as_ref().skip_binder().visit_with(visitor)
}
}
-EnumTypeTraversalImpl! {
- impl<'tcx, T> TypeFoldable<'tcx> for Option<T> {
- (Some)(a),
- (None),
- } where T: TypeFoldable<'tcx>
-}
-EnumTypeTraversalImpl! {
- impl<'tcx, T> TypeVisitable<'tcx> for Option<T> {
- (Some)(a),
- (None),
- } where T: TypeVisitable<'tcx>
-}
-
-EnumTypeTraversalImpl! {
- impl<'tcx, T, E> TypeFoldable<'tcx> for Result<T, E> {
- (Ok)(a),
- (Err)(a),
- } where T: TypeFoldable<'tcx>, E: TypeFoldable<'tcx>,
-}
-EnumTypeTraversalImpl! {
- impl<'tcx, T, E> TypeVisitable<'tcx> for Result<T, E> {
- (Ok)(a),
- (Err)(a),
- } where T: TypeVisitable<'tcx>, E: TypeVisitable<'tcx>,
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(
- mut self,
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
folder: &mut F,
) -> Result<Self, F::Error> {
- // We merely want to replace the contained `T`, if at all possible,
- // so that we don't needlessly allocate a new `Rc` or indeed clone
- // the contained type.
- unsafe {
- // First step is to ensure that we have a unique reference to
- // the contained type, which `Rc::make_mut` will accomplish (by
- // allocating a new `Rc` and cloning the `T` only if required).
- // This is done *before* casting to `Rc<ManuallyDrop<T>>` so that
- // panicking during `make_mut` does not leak the `T`.
- Rc::make_mut(&mut self);
-
- // Casting to `Rc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
- // is `repr(transparent)`.
- let ptr = Rc::into_raw(self).cast::<ManuallyDrop<T>>();
- let mut unique = Rc::from_raw(ptr);
-
- // Call to `Rc::make_mut` above guarantees that `unique` is the
- // sole reference to the contained value, so we can avoid doing
- // a checked `get_mut` here.
- 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
- // folding fail, `ManuallyDrop` ensures that the "moved-out"
- // value is not re-dropped.
- let owned = ManuallyDrop::take(slot);
- let folded = owned.try_fold_with(folder)?;
- *slot = ManuallyDrop::new(folded);
-
- // Cast back to `Rc<T>`.
- Ok(Rc::from_raw(Rc::into_raw(unique).cast()))
- }
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_poly_existential_predicates(v))
}
}
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Rc<T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- (**self).visit_with(visitor)
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(
- mut self,
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Const<'tcx>> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
folder: &mut F,
) -> Result<Self, F::Error> {
- // We merely want to replace the contained `T`, if at all possible,
- // so that we don't needlessly allocate a new `Arc` or indeed clone
- // the contained type.
- unsafe {
- // First step is to ensure that we have a unique reference to
- // the contained type, which `Arc::make_mut` will accomplish (by
- // allocating a new `Arc` and cloning the `T` only if required).
- // This is done *before* casting to `Arc<ManuallyDrop<T>>` so that
- // panicking during `make_mut` does not leak the `T`.
- Arc::make_mut(&mut self);
-
- // Casting to `Arc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
- // is `repr(transparent)`.
- let ptr = Arc::into_raw(self).cast::<ManuallyDrop<T>>();
- let mut unique = Arc::from_raw(ptr);
-
- // Call to `Arc::make_mut` above guarantees that `unique` is the
- // sole reference to the contained value, so we can avoid doing
- // a checked `get_mut` here.
- 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
- // folding fail, `ManuallyDrop` ensures that the "moved-out"
- // value is not re-dropped.
- let owned = ManuallyDrop::take(slot);
- let folded = owned.try_fold_with(folder)?;
- *slot = ManuallyDrop::new(folded);
-
- // Cast back to `Arc<T>`.
- Ok(Arc::from_raw(Arc::into_raw(unique).cast()))
- }
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Arc<T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- (**self).visit_with(visitor)
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- self.try_map_id(|value| value.try_fold_with(folder))
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- (**self).visit_with(visitor)
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- self.try_map_id(|t| t.try_fold_with(folder))
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Vec<T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.iter().try_for_each(|t| t.visit_with(visitor))
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &[T] {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.iter().try_for_each(|t| t.visit_with(visitor))
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- self.try_map_id(|t| t.try_fold_with(folder))
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<[T]> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.iter().try_for_each(|t| t.visit_with(visitor))
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_const_list(v))
}
}
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- folder.try_fold_binder(self)
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for ty::Binder<'tcx, T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- visitor.visit_binder(self)
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeSuperFoldable<'tcx> for ty::Binder<'tcx, T> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ProjectionKind> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
- self.try_map_bound(|ty| ty.try_fold_with(folder))
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_projs(v))
}
}
-impl<'tcx, T: TypeVisitable<'tcx>> TypeSuperVisitable<'tcx> for ty::Binder<'tcx, T> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.as_ref().skip_binder().visit_with(visitor)
- }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v))
- }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Const<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.mk_const_list(v.iter()))
- }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v))
- }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
folder.try_fold_ty(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for Ty<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_ty(*self)
}
}
-impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
+ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
@@ -654,6 +493,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> {
ty::Generator(did, substs.try_fold_with(folder)?, movability)
}
ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?),
+ ty::GeneratorWitnessMIR(did, substs) => {
+ ty::GeneratorWitnessMIR(did, substs.try_fold_with(folder)?)
+ }
ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?),
ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
@@ -672,12 +514,15 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> {
| ty::Foreign(..) => return Ok(self),
};
- Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) })
+ Ok(if *self.kind() == kind { self } else { folder.interner().mk_ty_from_kind(kind) })
}
}
-impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
match self.kind() {
ty::RawPtr(ref tm) => tm.visit_with(visitor),
ty::Array(typ, sz) => {
@@ -699,6 +544,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::GeneratorWitnessMIR(_did, ref substs) => substs.visit_with(visitor),
ty::Closure(_did, ref substs) => substs.visit_with(visitor),
ty::Alias(_, ref data) => data.visit_with(visitor),
@@ -719,20 +565,23 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> {
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Region<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
folder.try_fold_region(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for ty::Region<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_region(*self)
}
}
-impl<'tcx> TypeSuperFoldable<'tcx> for ty::Region<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Region<'tcx> {
+ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
_folder: &mut F,
) -> Result<Self, F::Error> {
@@ -740,116 +589,127 @@ 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> {
+impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ _visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
ControlFlow::Continue(())
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
folder.try_fold_predicate(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for ty::Predicate<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_predicate(*self)
}
-
- #[inline]
- fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
- self.outer_exclusive_binder() > binder
- }
-
- #[inline]
- fn has_type_flags(&self, flags: ty::TypeFlags) -> bool {
- self.flags().intersects(flags)
- }
}
-impl<'tcx> TypeSuperFoldable<'tcx> for ty::Predicate<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
+ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
let new = self.kind().try_fold_with(folder)?;
- Ok(folder.tcx().reuse_or_mk_predicate(self, new))
+ Ok(folder.interner().reuse_or_mk_predicate(self, new))
}
}
-impl<'tcx> TypeSuperVisitable<'tcx> for ty::Predicate<'tcx> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
self.kind().visit_with(visitor)
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.intern_predicates(v))
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- self.try_map_id(|x| x.try_fold_with(folder))
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>, I: Idx> TypeVisitable<'tcx> for IndexVec<I, T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.iter().try_for_each(|t| t.visit_with(visitor))
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Predicate<'tcx>> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_predicates(v))
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
folder.try_fold_const(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for ty::Const<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_const(*self)
}
}
-impl<'tcx> TypeSuperFoldable<'tcx> for ty::Const<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
+ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
let ty = self.ty().try_fold_with(folder)?;
let kind = self.kind().try_fold_with(folder)?;
if ty != self.ty() || kind != self.kind() {
- Ok(folder.tcx().mk_const(kind, ty))
+ Ok(folder.interner().mk_const(kind, ty))
} else {
Ok(self)
}
}
}
-impl<'tcx> TypeSuperVisitable<'tcx> for ty::Const<'tcx> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
self.ty().visit_with(visitor)?;
self.kind().visit_with(visitor)
}
}
-impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for InferConst<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ _folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for InferConst<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ _visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
ControlFlow::Continue(())
}
}
-impl<'tcx> TypeSuperVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
self.substs.visit_with(visitor)
}
}
+
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ visitor.visit_ty(self.ty)
+ }
+}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 91a7d5d38..e6a73e8bb 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -8,7 +8,7 @@ use crate::ty::visit::ValidateBoundVars;
use crate::ty::InferTy::*;
use crate::ty::{
self, AdtDef, DefIdTree, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable,
- TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+ TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
};
use crate::ty::{List, ParamEnv};
use hir::def::DefKind;
@@ -107,6 +107,15 @@ impl BoundRegionKind {
_ => None,
}
}
+
+ pub fn expect_anon(&self) -> u32 {
+ match *self {
+ BoundRegionKind::BrNamed(_, _) | BoundRegionKind::BrEnv => {
+ bug!("expected anon region: {self:?}")
+ }
+ BoundRegionKind::BrAnon(idx, _) => idx,
+ }
+ }
}
pub trait Article {
@@ -250,7 +259,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
parts: ClosureSubstsParts<'tcx, Ty<'tcx>>,
) -> ClosureSubsts<'tcx> {
ClosureSubsts {
- substs: tcx.mk_substs(
+ substs: tcx.mk_substs_from_iter(
parts.parent_substs.iter().copied().chain(
[parts.closure_kind_ty, parts.closure_sig_as_fn_ptr_ty, parts.tupled_upvars_ty]
.iter()
@@ -377,7 +386,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
parts: GeneratorSubstsParts<'tcx, Ty<'tcx>>,
) -> GeneratorSubsts<'tcx> {
GeneratorSubsts {
- substs: tcx.mk_substs(
+ substs: tcx.mk_substs_from_iter(
parts.parent_substs.iter().copied().chain(
[
parts.resume_ty,
@@ -568,12 +577,12 @@ impl<'tcx> GeneratorSubsts<'tcx> {
self,
def_id: DefId,
tcx: TyCtxt<'tcx>,
- ) -> impl Iterator<Item = impl Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
+ ) -> impl Iterator<Item: Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
let layout = tcx.generator_layout(def_id).unwrap();
layout.variant_fields.iter().map(move |variant| {
- variant
- .iter()
- .map(move |field| ty::EarlyBinder(layout.field_tys[*field]).subst(tcx, self.substs))
+ variant.iter().map(move |field| {
+ ty::EarlyBinder(layout.field_tys[*field].ty).subst(tcx, self.substs)
+ })
})
}
@@ -655,7 +664,7 @@ impl<'tcx> InlineConstSubsts<'tcx> {
parts: InlineConstSubstsParts<'tcx, Ty<'tcx>>,
) -> InlineConstSubsts<'tcx> {
InlineConstSubsts {
- substs: tcx.mk_substs(
+ substs: tcx.mk_substs_from_iter(
parts.parent_substs.iter().copied().chain(std::iter::once(parts.ty.into())),
),
}
@@ -853,7 +862,7 @@ impl<'tcx> TraitRef<'tcx> {
substs: SubstsRef<'tcx>,
) -> ty::TraitRef<'tcx> {
let defs = tcx.generics_of(trait_id);
- tcx.mk_trait_ref(trait_id, tcx.intern_substs(&substs[..defs.params.len()]))
+ tcx.mk_trait_ref(trait_id, tcx.mk_substs(&substs[..defs.params.len()]))
}
}
@@ -899,7 +908,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> {
ty::ExistentialTraitRef {
def_id: trait_ref.def_id,
- substs: tcx.intern_substs(&trait_ref.substs[1..]),
+ substs: tcx.mk_substs(&trait_ref.substs[1..]),
}
}
@@ -983,7 +992,7 @@ pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>);
impl<'tcx, T> Binder<'tcx, T>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
/// Wraps `value` in a binder, asserting that `value` does not
/// contain any bound vars that would be bound by the
@@ -1051,14 +1060,14 @@ impl<'tcx, T> Binder<'tcx, T> {
Binder(value, self.1)
}
- pub fn map_bound_ref<F, U: TypeVisitable<'tcx>>(&self, f: F) -> Binder<'tcx, U>
+ pub fn map_bound_ref<F, U: TypeVisitable<TyCtxt<'tcx>>>(&self, f: F) -> Binder<'tcx, U>
where
F: FnOnce(&T) -> U,
{
self.as_ref().map_bound(f)
}
- pub fn map_bound<F, U: TypeVisitable<'tcx>>(self, f: F) -> Binder<'tcx, U>
+ pub fn map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>>(self, f: F) -> Binder<'tcx, U>
where
F: FnOnce(T) -> U,
{
@@ -1070,7 +1079,10 @@ impl<'tcx, T> Binder<'tcx, T> {
Binder(value, self.1)
}
- pub fn try_map_bound<F, U: TypeVisitable<'tcx>, E>(self, f: F) -> Result<Binder<'tcx, U>, E>
+ pub fn try_map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>, E>(
+ self,
+ f: F,
+ ) -> Result<Binder<'tcx, U>, E>
where
F: FnOnce(T) -> Result<U, E>,
{
@@ -1093,7 +1105,7 @@ impl<'tcx, T> Binder<'tcx, T> {
/// in `bind`. This may be (debug) asserted in the future.
pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U>
where
- U: TypeVisitable<'tcx>,
+ U: TypeVisitable<TyCtxt<'tcx>>,
{
if cfg!(debug_assertions) {
let mut validator = ValidateBoundVars::new(self.bound_vars());
@@ -1114,7 +1126,7 @@ impl<'tcx, T> Binder<'tcx, T> {
/// would not be that useful.)
pub fn no_bound_vars(self) -> Option<T>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
}
@@ -1153,16 +1165,16 @@ struct SkipBindersAt<'tcx> {
index: ty::DebruijnIndex,
}
-impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> {
+impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for SkipBindersAt<'tcx> {
type Error = ();
- fn tcx(&self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
where
- T: ty::TypeFoldable<'tcx>,
+ T: ty::TypeFoldable<TyCtxt<'tcx>>,
{
self.index.shift_in(1);
let value = t.try_map_bound(|t| t.try_fold_with(self));
@@ -1177,7 +1189,7 @@ impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> {
if index == self.index {
Err(())
} else {
- Ok(self.tcx().mk_ty(ty::Bound(index.shifted_out(1), bv)))
+ Ok(self.interner().mk_bound(index.shifted_out(1), bv))
}
} else {
ty.try_super_fold_with(self)
@@ -1191,7 +1203,7 @@ impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> {
if index == self.index {
Err(())
} else {
- Ok(self.tcx().mk_region(ty::ReLateBound(index.shifted_out(1), bv)))
+ Ok(self.interner().mk_re_late_bound(index.shifted_out(1), bv))
}
} else {
r.try_super_fold_with(self)
@@ -1205,7 +1217,7 @@ impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> {
if index == self.index {
Err(())
} else {
- Ok(self.tcx().mk_const(
+ Ok(self.interner().mk_const(
ty::ConstKind::Bound(index.shifted_out(1), bv),
ct.ty().try_fold_with(self)?,
))
@@ -1266,7 +1278,7 @@ impl<'tcx> AliasTy<'tcx> {
}
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- tcx.mk_ty(ty::Alias(self.kind(tcx), self))
+ tcx.mk_alias(self.kind(tcx), self)
}
}
@@ -1510,13 +1522,22 @@ pub struct BoundTy {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum BoundTyKind {
- Anon,
- Param(Symbol),
+ Anon(u32),
+ Param(DefId, Symbol),
+}
+
+impl BoundTyKind {
+ pub fn expect_anon(self) -> u32 {
+ match self {
+ BoundTyKind::Anon(i) => i,
+ _ => bug!(),
+ }
+ }
}
impl From<BoundVar> for BoundTy {
fn from(var: BoundVar) -> Self {
- BoundTy { var, kind: BoundTyKind::Anon }
+ BoundTy { var, kind: BoundTyKind::Anon(var.as_u32()) }
}
}
@@ -1539,7 +1560,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
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]);
+ let substs = tcx.mk_substs(&self.substs[..subst_count]);
ty::ExistentialTraitRef { def_id, substs }
}
@@ -1567,7 +1588,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
Self {
def_id: projection_predicate.projection_ty.def_id,
- substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
+ substs: tcx.mk_substs(&projection_predicate.projection_ty.substs[1..]),
term: projection_predicate.term,
}
}
@@ -1620,10 +1641,16 @@ impl<'tcx> Region<'tcx> {
ty::ReVar(..) => false,
ty::RePlaceholder(placeholder) => placeholder.name.is_named(),
ty::ReErased => false,
+ ty::ReError(_) => false,
}
}
#[inline]
+ pub fn is_error(self) -> bool {
+ matches!(*self, ty::ReError(_))
+ }
+
+ #[inline]
pub fn is_static(self) -> bool {
matches!(*self, ty::ReStatic)
}
@@ -1683,6 +1710,7 @@ impl<'tcx> Region<'tcx> {
ty::ReErased => {
flags = flags | TypeFlags::HAS_RE_ERASED;
}
+ ty::ReError(_) => {}
}
debug!("type_flags({:?}) = {:?}", self, flags);
@@ -1733,6 +1761,13 @@ impl<'tcx> Region<'tcx> {
pub fn is_var(self) -> bool {
matches!(self.kind(), ty::ReVar(_))
}
+
+ pub fn as_var(self) -> Option<RegionVid> {
+ match self.kind() {
+ ty::ReVar(vid) => Some(vid),
+ _ => None,
+ }
+ }
}
/// Type utilities
@@ -1867,7 +1902,7 @@ impl<'tcx> Ty<'tcx> {
// The way we evaluate the `N` in `[T; N]` here only works since we use
// `simd_size_and_type` post-monomorphization. It will probably start to ICE
// if we use it in generic code. See the `simd-array-trait` ui test.
- (f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, *f0_elem_ty)
+ (f0_len.eval_target_usize(tcx, ParamEnv::empty()) as u64, *f0_elem_ty)
}
// Otherwise, the fields of this Adt are the SIMD components (and we assume they
// all have the same type).
@@ -2028,7 +2063,7 @@ impl<'tcx> Ty<'tcx> {
pub fn contains(self, other: Ty<'tcx>) -> bool {
struct ContainsTyVisitor<'tcx>(Ty<'tcx>);
- impl<'tcx> TypeVisitor<'tcx> for ContainsTyVisitor<'tcx> {
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -2040,6 +2075,28 @@ impl<'tcx> Ty<'tcx> {
cf.is_break()
}
+ /// Checks whether a type recursively contains any closure
+ ///
+ /// Example: `Option<[closure@file.rs:4:20]>` returns true
+ pub fn contains_closure(self) -> bool {
+ struct ContainsClosureVisitor;
+
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsClosureVisitor {
+ type BreakTy = ();
+
+ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+ if let ty::Closure(_, _) = t.kind() {
+ ControlFlow::Break(())
+ } else {
+ t.super_visit_with(self)
+ }
+ }
+ }
+
+ let cf = self.visit_with(&mut ContainsClosureVisitor);
+ cf.is_break()
+ }
+
/// Returns the type and mutability of `*ty`.
///
/// The parameter `explicit` indicates if this is an *explicit* dereference.
@@ -2065,7 +2122,7 @@ impl<'tcx> Ty<'tcx> {
pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
match self.kind() {
- FnDef(def_id, substs) => tcx.bound_fn_sig(*def_id).subst(tcx, substs),
+ FnDef(def_id, substs) => tcx.fn_sig(*def_id).subst(tcx, substs),
FnPtr(f) => *f,
Error(_) => {
// ignore errors (#54954)
@@ -2161,7 +2218,7 @@ impl<'tcx> Ty<'tcx> {
let assoc_items = tcx.associated_item_def_ids(
tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
);
- tcx.mk_projection(assoc_items[0], tcx.intern_substs(&[self.into()]))
+ tcx.mk_projection(assoc_items[0], tcx.mk_substs(&[self.into()]))
}
ty::Bool
@@ -2181,6 +2238,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Dynamic(..)
| ty::Closure(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Tuple(_)
| ty::Error(_)
@@ -2216,6 +2274,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Ref(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Array(..)
| ty::Closure(..)
| ty::Never
@@ -2232,7 +2291,7 @@ impl<'tcx> Ty<'tcx> {
ty::Str | ty::Slice(_) => (tcx.types.usize, false),
ty::Dynamic(..) => {
let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
- (tcx.bound_type_of(dyn_metadata).subst(tcx, &[tail.into()]), false)
+ (tcx.type_of(dyn_metadata).subst(tcx, &[tail.into()]), false)
},
// type parameters only have unit metadata if they're sized, so return true
@@ -2302,6 +2361,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Ref(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Array(..)
| ty::Closure(..)
| ty::Never
@@ -2366,7 +2426,7 @@ impl<'tcx> Ty<'tcx> {
// anything with custom metadata it might be more complicated.
ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => false,
- ty::Generator(..) | ty::GeneratorWitness(..) => false,
+ ty::Generator(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => false,
// Might be, but not "trivial" so just giving the safe answer.
ty::Adt(..) | ty::Closure(..) => false,
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index a07582fc8..b090bd9d8 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -3,7 +3,7 @@
use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
-use crate::ty::visit::{TypeVisitable, TypeVisitor};
+use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
use rustc_data_structures::intern::Interned;
@@ -71,7 +71,7 @@ impl<'tcx> List<Ty<'tcx>> {
/// Allows to freely switch between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
///
/// As lists are interned, `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>` have
- /// be interned together, see `intern_type_list` for more details.
+ /// be interned together, see `mk_type_list` for more details.
#[inline]
pub fn as_substs(&'tcx self) -> SubstsRef<'tcx> {
assert_eq!(TYPE_TAG, 0);
@@ -227,8 +227,11 @@ impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {
}
}
-impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArg<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
match self.unpack() {
GenericArgKind::Lifetime(lt) => lt.try_fold_with(folder).map(Into::into),
GenericArgKind::Type(ty) => ty.try_fold_with(folder).map(Into::into),
@@ -237,8 +240,8 @@ impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> {
}
}
-impl<'tcx> TypeVisitable<'tcx> for GenericArg<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match self.unpack() {
GenericArgKind::Lifetime(lt) => lt.visit_with(visitor),
GenericArgKind::Type(ty) => ty.visit_with(visitor),
@@ -267,13 +270,11 @@ pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
impl<'tcx> InternalSubsts<'tcx> {
/// Checks whether all elements of this list are types, if so, transmute.
pub fn try_as_type_list(&'tcx self) -> Option<&'tcx List<Ty<'tcx>>> {
- if self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))) {
+ self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))).then(|| {
assert_eq!(TYPE_TAG, 0);
// SAFETY: All elements are types, see `List<Ty<'tcx>>::as_substs`.
- Some(unsafe { &*(self as *const List<GenericArg<'tcx>> as *const List<Ty<'tcx>>) })
- } else {
- None
- }
+ unsafe { &*(self as *const List<GenericArg<'tcx>> as *const List<Ty<'tcx>>) }
+ })
}
/// Interpret these substitutions as the substitutions of a closure type.
@@ -318,7 +319,7 @@ impl<'tcx> InternalSubsts<'tcx> {
let count = defs.count();
let mut substs = SmallVec::with_capacity(count);
Self::fill_item(&mut substs, tcx, defs, &mut mk_kind);
- tcx.intern_substs(&substs)
+ tcx.mk_substs(&substs)
}
pub fn extend_to<F>(&self, tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx>
@@ -467,26 +468,33 @@ impl<'tcx> InternalSubsts<'tcx> {
target_substs: SubstsRef<'tcx>,
) -> SubstsRef<'tcx> {
let defs = tcx.generics_of(source_ancestor);
- tcx.mk_substs(target_substs.iter().chain(self.iter().skip(defs.params.len())))
+ tcx.mk_substs_from_iter(target_substs.iter().chain(self.iter().skip(defs.params.len())))
}
pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> {
- tcx.mk_substs(self.iter().take(generics.count()))
+ tcx.mk_substs_from_iter(self.iter().take(generics.count()))
}
}
-impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
// This code is hot enough that it's worth specializing for the most
// common length lists, to avoid the overhead of `SmallVec` creation.
// The match arms are in order of frequency. The 1, 2, and 0 cases are
// typically hit in 90--99.99% of cases. When folding doesn't change
// the substs, it's faster to reuse the existing substs rather than
- // calling `intern_substs`.
+ // calling `mk_substs`.
match self.len() {
1 => {
let param0 = self[0].try_fold_with(folder)?;
- if param0 == self[0] { Ok(self) } else { Ok(folder.tcx().intern_substs(&[param0])) }
+ if param0 == self[0] {
+ Ok(self)
+ } else {
+ Ok(folder.interner().mk_substs(&[param0]))
+ }
}
2 => {
let param0 = self[0].try_fold_with(folder)?;
@@ -494,17 +502,20 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
if param0 == self[0] && param1 == self[1] {
Ok(self)
} else {
- Ok(folder.tcx().intern_substs(&[param0, param1]))
+ Ok(folder.interner().mk_substs(&[param0, param1]))
}
}
0 => Ok(self),
- _ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_substs(v)),
+ _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_substs(v)),
}
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
// This code is fairly hot, though not as hot as `SubstsRef`.
//
// When compiling stage 2, I get the following results:
@@ -527,17 +538,17 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
if param0 == self[0] && param1 == self[1] {
Ok(self)
} else {
- Ok(folder.tcx().intern_type_list(&[param0, param1]))
+ Ok(folder.interner().mk_type_list(&[param0, param1]))
}
}
- _ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)),
+ _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)),
}
}
}
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> {
+impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx ty::List<T> {
#[inline]
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
@@ -553,8 +564,8 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> {
pub struct EarlyBinder<T>(pub T);
/// For early binders, you should first call `subst` before using any visitors.
-impl<'tcx, T> !TypeFoldable<'tcx> for ty::EarlyBinder<T> {}
-impl<'tcx, T> !TypeVisitable<'tcx> for ty::EarlyBinder<T> {}
+impl<'tcx, T> !TypeFoldable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
+impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
impl<T> EarlyBinder<T> {
pub fn as_ref(&self) -> EarlyBinder<&T> {
@@ -615,7 +626,7 @@ impl<T, U> EarlyBinder<(T, U)> {
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
where
- I::Item: TypeFoldable<'tcx>,
+ I::Item: TypeFoldable<TyCtxt<'tcx>>,
{
pub fn subst_iter(
self,
@@ -634,7 +645,7 @@ pub struct SubstIter<'s, 'tcx, I: IntoIterator> {
impl<'tcx, I: IntoIterator> Iterator for SubstIter<'_, 'tcx, I>
where
- I::Item: TypeFoldable<'tcx>,
+ I::Item: TypeFoldable<TyCtxt<'tcx>>,
{
type Item = I::Item;
@@ -650,7 +661,7 @@ where
impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIter<'_, 'tcx, I>
where
I::IntoIter: DoubleEndedIterator,
- I::Item: TypeFoldable<'tcx>,
+ I::Item: TypeFoldable<TyCtxt<'tcx>>,
{
fn next_back(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(self.it.next_back()?).subst(self.tcx, self.substs))
@@ -660,14 +671,14 @@ where
impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIter<'_, 'tcx, I>
where
I::IntoIter: ExactSizeIterator,
- I::Item: TypeFoldable<'tcx>,
+ I::Item: TypeFoldable<TyCtxt<'tcx>>,
{
}
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
where
I::Item: Deref,
- <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
+ <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
{
pub fn subst_iter_copied(
self,
@@ -687,7 +698,7 @@ pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> {
impl<'tcx, I: IntoIterator> Iterator for SubstIterCopied<'_, 'tcx, I>
where
I::Item: Deref,
- <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
+ <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
{
type Item = <I::Item as Deref>::Target;
@@ -704,7 +715,7 @@ impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIterCopied<'_, 'tcx, I>
where
I::IntoIter: DoubleEndedIterator,
I::Item: Deref,
- <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
+ <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
{
fn next_back(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(*self.it.next_back()?).subst(self.tcx, self.substs))
@@ -715,7 +726,7 @@ impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIterCopied<'_, 'tcx, I>
where
I::IntoIter: ExactSizeIterator,
I::Item: Deref,
- <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
+ <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
{
}
@@ -741,7 +752,7 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> {
}
}
-impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder<T> {
+impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> {
pub fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T {
let mut folder = SubstFolder { tcx, substs, binders_passed: 0 };
self.0.fold_with(&mut folder)
@@ -758,6 +769,11 @@ impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder<T> {
pub fn subst_identity(self) -> T {
self.0
}
+
+ /// Returns the inner value, but only if it contains no bound vars.
+ pub fn no_bound_vars(self) -> Option<T> {
+ if !self.0.needs_subst() { Some(self.0) } else { None }
+ }
}
///////////////////////////////////////////////////////////////////////////
@@ -771,13 +787,13 @@ struct SubstFolder<'a, 'tcx> {
binders_passed: u32,
}
-impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> {
#[inline]
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -970,7 +986,7 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
/// As indicated in the diagram, here the same type `&'a i32` is substituted once, but in the
/// first case we do not increase the De Bruijn index and in the second case we do. The reason
/// is that only in the second case have we passed through a fn binder.
- fn shift_vars_through_binders<T: TypeFoldable<'tcx>>(&self, val: T) -> T {
+ fn shift_vars_through_binders<T: TypeFoldable<TyCtxt<'tcx>>>(&self, val: T) -> T {
debug!(
"shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})",
val,
@@ -982,7 +998,7 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
return val;
}
- let result = ty::fold::shift_vars(TypeFolder::tcx(self), val, self.binders_passed);
+ let result = ty::fold::shift_vars(TypeFolder::interner(self), val, self.binders_passed);
debug!("shift_vars: shifted result = {:?}", result);
result
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index b38a5fbf2..233c0df2d 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -1,6 +1,6 @@
use crate::traits::specialization_graph;
use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
-use crate::ty::visit::TypeVisitable;
+use crate::ty::visit::TypeVisitableExt;
use crate::ty::{Ident, Ty, TyCtxt};
use hir::def_id::LOCAL_CRATE;
use rustc_hir as hir;
@@ -31,6 +31,15 @@ pub struct TraitDef {
/// and thus `impl`s of it are allowed to overlap.
pub is_marker: bool,
+ /// If `true`, then this trait has to `#[rustc_coinductive]` attribute or
+ /// is an auto trait. This indicates that trait solver cycles involving an
+ /// `X: ThisTrait` goal are accepted.
+ ///
+ /// In the future all traits should be coinductive, but we need a better
+ /// formal understanding of what exactly that means and should probably
+ /// also have already switched to the new trait solver.
+ pub is_coinductive: bool,
+
/// If `true`, then this trait has the `#[rustc_skip_array_during_method_dispatch]`
/// attribute, indicating that editions before 2021 should not consider this trait
/// during method dispatch if the receiver is an array.
@@ -81,28 +90,6 @@ impl TraitImpls {
}
impl<'tcx> TraitDef {
- pub fn new(
- def_id: DefId,
- unsafety: hir::Unsafety,
- paren_sugar: bool,
- has_auto_impl: bool,
- is_marker: bool,
- skip_array_during_method_dispatch: bool,
- specialization_kind: TraitSpecializationKind,
- must_implement_one_of: Option<Box<[Ident]>>,
- ) -> TraitDef {
- TraitDef {
- def_id,
- unsafety,
- paren_sugar,
- has_auto_impl,
- is_marker,
- skip_array_during_method_dispatch,
- specialization_kind,
- must_implement_one_of,
- }
- }
-
pub fn ancestors(
&self,
tcx: TyCtxt<'tcx>,
@@ -238,7 +225,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
for &impl_def_id in tcx.hir().trait_impls(trait_id) {
let impl_def_id = impl_def_id.to_def_id();
- let impl_self_ty = tcx.type_of(impl_def_id);
+ let impl_self_ty = tcx.type_of(impl_def_id).subst_identity();
if impl_self_ty.references_error() {
continue;
}
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 2902c6dc5..586958247 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -1,6 +1,7 @@
use crate::{
hir::place::Place as HirPlace,
infer::canonical::Canonical,
+ traits::ObligationCause,
ty::{
self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData,
GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
@@ -193,6 +194,11 @@ pub struct TypeckResults<'tcx> {
/// that are live across the yield of this generator (if a generator).
pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
+ /// Stores the predicates that apply on generator witness types.
+ /// formatting modified file tests/ui/generator/retain-resume-ref.rs
+ pub generator_interior_predicates:
+ FxHashMap<LocalDefId, Vec<(ty::Predicate<'tcx>, ObligationCause<'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
@@ -271,6 +277,7 @@ impl<'tcx> TypeckResults<'tcx> {
closure_fake_reads: Default::default(),
rvalue_scopes: Default::default(),
generator_interior_types: ty::Binder::dummy(Default::default()),
+ generator_interior_predicates: Default::default(),
treat_byte_string_as_slice: Default::default(),
closure_size_eval: Default::default(),
}
@@ -365,7 +372,7 @@ impl<'tcx> TypeckResults<'tcx> {
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)))
+ bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id)))
})
}
@@ -544,9 +551,8 @@ fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
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 {:?}",
+ "node {} cannot be placed in TypeckResults with hir_owner {:?}",
tcx.hir().node_to_string(hir_id),
- hir_id.owner,
hir_owner
)
});
@@ -563,7 +569,7 @@ impl<'a, V> LocalTableInContext<'a, V> {
self.data.contains_key(&id.local_id)
}
- pub fn get(&self, id: hir::HirId) -> Option<&V> {
+ pub fn get(&self, id: hir::HirId) -> Option<&'a V> {
validate_hir_id_for_typeck_results(self.hir_owner, id);
self.data.get(&id.local_id)
}
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index d0d1dcc58..90270e0ee 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -3,10 +3,9 @@
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,
+ self, DefIdTree, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder,
+ TypeSuperFoldable, TypeVisitableExt,
};
use crate::ty::{GenericArgKind, SubstsRef};
use rustc_apfloat::Float as _;
@@ -168,7 +167,7 @@ impl<'tcx> TyCtxt<'tcx> {
| DefKind::Fn
| DefKind::AssocFn
| DefKind::AssocConst
- | DefKind::Impl,
+ | DefKind::Impl { .. },
def_id,
) => Some(def_id),
Res::Err => None,
@@ -363,7 +362,7 @@ impl<'tcx> TyCtxt<'tcx> {
let drop_trait = self.lang_items().drop_trait()?;
self.ensure().coherent_trait(drop_trait);
- let ty = self.type_of(adt_did);
+ let ty = self.type_of(adt_did).subst_identity();
let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
if validate(self, impl_did).is_ok() {
@@ -416,12 +415,12 @@ impl<'tcx> TyCtxt<'tcx> {
// <P1, P2, P0>, and then look up which of the impl substs refer to
// parameters marked as pure.
- let impl_substs = match *self.type_of(impl_def_id).kind() {
+ let impl_substs = match *self.type_of(impl_def_id).subst_identity().kind() {
ty::Adt(def_, substs) if def_ == def => substs,
_ => bug!(),
};
- let item_substs = match *self.type_of(def.did()).kind() {
+ let item_substs = match *self.type_of(def.did()).subst_identity().kind() {
ty::Adt(def_, substs) if def_ == def => substs,
_ => bug!(),
};
@@ -565,14 +564,14 @@ impl<'tcx> TyCtxt<'tcx> {
self,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
- env_region: ty::RegionKind<'tcx>,
+ env_region: ty::Region<'tcx>,
) -> Option<Ty<'tcx>> {
let closure_ty = self.mk_closure(closure_def_id, closure_substs);
let closure_kind_ty = closure_substs.as_closure().kind_ty();
let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
let env_ty = match closure_kind {
- ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
- ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
+ ty::ClosureKind::Fn => self.mk_imm_ref(env_region, closure_ty),
+ ty::ClosureKind::FnMut => self.mk_mut_ref(env_region, closure_ty),
ty::ClosureKind::FnOnce => closure_ty,
};
Some(env_ty)
@@ -603,7 +602,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// Get the type of the pointer to the static that we use in MIR.
pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
// Make sure that any constants in the static's type are evaluated.
- let static_ty = self.normalize_erasing_regions(ty::ParamEnv::empty(), self.type_of(def_id));
+ let static_ty = self.normalize_erasing_regions(
+ ty::ParamEnv::empty(),
+ self.type_of(def_id).subst_identity(),
+ );
// Make sure that accesses to unsafe statics end up using raw pointers.
// For thread-locals, this needs to be kept in sync with `Rvalue::ty`.
@@ -616,6 +618,36 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
+ /// Return the set of types that should be taken into accound when checking
+ /// trait bounds on a generator's internal state.
+ pub fn generator_hidden_types(
+ self,
+ def_id: DefId,
+ ) -> impl Iterator<Item = ty::EarlyBinder<Ty<'tcx>>> {
+ let generator_layout = &self.mir_generator_witnesses(def_id);
+ generator_layout
+ .field_tys
+ .iter()
+ .filter(|decl| !decl.ignore_for_traits)
+ .map(|decl| ty::EarlyBinder(decl.ty))
+ }
+
+ /// Normalizes all opaque types in the given value, replacing them
+ /// with their underlying types.
+ pub fn expand_opaque_types(self, val: Ty<'tcx>) -> Ty<'tcx> {
+ let mut visitor = OpaqueTypeExpander {
+ seen_opaque_tys: FxHashSet::default(),
+ expanded_cache: FxHashMap::default(),
+ primary_def_id: None,
+ found_recursion: false,
+ found_any_recursion: false,
+ check_recursion: false,
+ expand_generators: false,
+ tcx: self,
+ };
+ val.fold_with(&mut visitor)
+ }
+
/// Expands the given impl trait type, stopping if the type is recursive.
#[instrument(skip(self), level = "debug", ret)]
pub fn try_expand_impl_trait_type(
@@ -630,6 +662,7 @@ impl<'tcx> TyCtxt<'tcx> {
found_recursion: false,
found_any_recursion: false,
check_recursion: true,
+ expand_generators: true,
tcx: self,
};
@@ -637,10 +670,6 @@ impl<'tcx> TyCtxt<'tcx> {
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
}
- pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
- ty::EarlyBinder(self.type_of(def_id))
- }
-
pub fn bound_return_position_impl_trait_in_trait_tys(
self,
def_id: DefId,
@@ -648,10 +677,6 @@ impl<'tcx> TyCtxt<'tcx> {
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_explicit_item_bounds(
self,
def_id: DefId,
@@ -736,11 +761,39 @@ impl<'tcx> TyCtxt<'tcx> {
}
(generator_layout, generator_saved_local_names)
}
-}
-impl<'tcx> TyCtxtAt<'tcx> {
- pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
- ty::EarlyBinder(self.type_of(def_id))
+ /// Query and get an English description for the item's kind.
+ pub fn def_descr(self, def_id: DefId) -> &'static str {
+ self.def_kind_descr(self.def_kind(def_id), def_id)
+ }
+
+ /// Get an English description for the item's kind.
+ pub fn def_kind_descr(self, def_kind: DefKind, def_id: DefId) -> &'static str {
+ match def_kind {
+ DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "method",
+ DefKind::Generator => match self.generator_kind(def_id).unwrap() {
+ rustc_hir::GeneratorKind::Async(..) => "async closure",
+ rustc_hir::GeneratorKind::Gen => "generator",
+ },
+ _ => def_kind.descr(def_id),
+ }
+ }
+
+ /// Gets an English article for the [`TyCtxt::def_descr`].
+ pub fn def_descr_article(self, def_id: DefId) -> &'static str {
+ self.def_kind_descr_article(self.def_kind(def_id), def_id)
+ }
+
+ /// Gets an English article for the [`TyCtxt::def_kind_descr`].
+ pub fn def_kind_descr_article(self, def_kind: DefKind, def_id: DefId) -> &'static str {
+ match def_kind {
+ DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "a",
+ DefKind::Generator => match self.generator_kind(def_id).unwrap() {
+ rustc_hir::GeneratorKind::Async(..) => "an",
+ rustc_hir::GeneratorKind::Gen => "a",
+ },
+ _ => def_kind.article(),
+ }
}
}
@@ -756,6 +809,7 @@ struct OpaqueTypeExpander<'tcx> {
primary_def_id: Option<DefId>,
found_recursion: bool,
found_any_recursion: bool,
+ expand_generators: bool,
/// Whether or not to check for recursive opaque types.
/// This is `true` when we're explicitly checking for opaque type
/// recursion, and 'false' otherwise to avoid unnecessary work.
@@ -773,7 +827,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
Some(expanded_ty) => *expanded_ty,
None => {
- let generic_ty = self.tcx.bound_type_of(def_id);
+ let generic_ty = self.tcx.type_of(def_id);
let concrete_ty = generic_ty.subst(self.tcx, substs);
let expanded_ty = self.fold_ty(concrete_ty);
self.expanded_cache.insert((def_id, substs), expanded_ty);
@@ -792,20 +846,77 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
None
}
}
+
+ fn expand_generator(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option<Ty<'tcx>> {
+ if self.found_any_recursion {
+ return None;
+ }
+ let substs = substs.fold_with(self);
+ if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
+ let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
+ Some(expanded_ty) => *expanded_ty,
+ None => {
+ for bty in self.tcx.generator_hidden_types(def_id) {
+ let hidden_ty = bty.subst(self.tcx, substs);
+ self.fold_ty(hidden_ty);
+ }
+ let expanded_ty = self.tcx.mk_generator_witness_mir(def_id, substs);
+ self.expanded_cache.insert((def_id, substs), expanded_ty);
+ expanded_ty
+ }
+ };
+ if self.check_recursion {
+ self.seen_opaque_tys.remove(&def_id);
+ }
+ Some(expanded_ty)
+ } else {
+ // If another opaque type that we contain is recursive, then it
+ // will report the error, so we don't have to.
+ self.found_any_recursion = true;
+ self.found_recursion = def_id == *self.primary_def_id.as_ref().unwrap();
+ None
+ }
+ }
}
-impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() {
+ let mut t = 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() {
+ } else if t.has_opaque_types() || t.has_generators() {
t.super_fold_with(self)
} else {
t
+ };
+ if self.expand_generators {
+ if let ty::GeneratorWitnessMIR(def_id, substs) = *t.kind() {
+ t = self.expand_generator(def_id, substs).unwrap_or(t);
+ }
+ }
+ t
+ }
+
+ fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+ if let ty::PredicateKind::Clause(clause) = p.kind().skip_binder()
+ && let ty::Clause::Projection(projection_pred) = clause
+ {
+ p.kind()
+ .rebind(ty::ProjectionPredicate {
+ projection_ty: projection_pred.projection_ty.fold_with(self),
+ // Don't fold the term on the RHS of the projection predicate.
+ // This is because for default trait methods with RPITITs, we
+ // install a `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))`
+ // predicate, which would trivially cause a cycle when we do
+ // anything that requires `ParamEnv::with_reveal_all_normalized`.
+ term: projection_pred.term,
+ })
+ .to_predicate(self.tcx)
+ } else {
+ p.super_fold_with(self)
}
}
}
@@ -911,6 +1022,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Foreign(_)
| ty::Generator(..)
| ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
| ty::Infer(_)
| ty::Alias(..)
| ty::Param(_)
@@ -950,6 +1062,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Foreign(_)
| ty::Generator(..)
| ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
| ty::Infer(_)
| ty::Alias(..)
| ty::Param(_)
@@ -1077,7 +1190,10 @@ impl<'tcx> Ty<'tcx> {
false
}
- ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
+ ty::Foreign(_)
+ | ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
+ | ty::Error(_) => false,
}
}
@@ -1173,6 +1289,7 @@ pub fn needs_drop_components<'tcx>(
| ty::FnPtr(_)
| ty::Char
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::RawPtr(_)
| ty::Ref(..)
| ty::Str => Ok(SmallVec::new()),
@@ -1243,7 +1360,11 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
// Not trivial because they have components, and instead of looking inside,
// we'll just perform trait selection.
- ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(_) | ty::Adt(..) => false,
+ ty::Closure(..)
+ | ty::Generator(..)
+ | ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
+ | ty::Adt(..) => false,
ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty),
@@ -1262,8 +1383,8 @@ pub fn fold_list<'tcx, F, T>(
intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> &'tcx ty::List<T>,
) -> Result<&'tcx ty::List<T>, F::Error>
where
- F: FallibleTypeFolder<'tcx>,
- T: TypeFoldable<'tcx> + PartialEq + Copy,
+ F: FallibleTypeFolder<TyCtxt<'tcx>>,
+ T: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy,
{
let mut iter = list.iter();
// Look for the first element that changed
@@ -1279,7 +1400,7 @@ where
for t in iter {
new_list.push(t.try_fold_with(folder)?)
}
- Ok(intern(folder.tcx(), &new_list))
+ Ok(intern(folder.interner(), &new_list))
}
Some((_, Err(err))) => {
return Err(err);
@@ -1304,13 +1425,15 @@ pub fn reveal_opaque_types_in_bounds<'tcx>(
found_recursion: false,
found_any_recursion: false,
check_recursion: false,
+ expand_generators: false,
tcx,
};
val.fold_with(&mut visitor)
}
/// Determines whether an item is annotated with `doc(hidden)`.
-pub fn is_doc_hidden(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+fn is_doc_hidden(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+ assert!(def_id.is_local());
tcx.get_attrs(def_id, sym::doc)
.filter_map(|attr| attr.meta_item_list())
.any(|items| items.iter().any(|item| item.has_name(sym::hidden)))
@@ -1325,7 +1448,7 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
/// Determines whether an item is an intrinsic by Abi.
pub fn is_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
- matches!(tcx.fn_sig(def_id).abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
+ matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
}
pub fn provide(providers: &mut ty::query::Providers) {
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index bee3cc4d7..6814cadb9 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -1,69 +1,13 @@
-//! A visiting traversal mechanism for complex data structures that contain type
-//! information.
-//!
-//! This is a read-only traversal of the data structure.
-//!
-//! This traversal has limited flexibility. Only a small number of "types of
-//! interest" within the complex data structures can receive custom
-//! visitation. These are the ones containing the most important type-related
-//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
-//!
-//! There are three groups of traits involved in each traversal.
-//! - `TypeVisitable`. This is implemented once for many types, including:
-//! - Types of interest, for which the methods delegate to the visitor.
-//! - All other types, including generic containers like `Vec` and `Option`.
-//! It defines a "skeleton" of how they should be visited.
-//! - `TypeSuperVisitable`. This is implemented only for each type of interest,
-//! and defines the visiting "skeleton" for these types.
-//! - `TypeVisitor`. This is implemented for each visitor. This defines how
-//! types of interest are visited.
-//!
-//! This means each visit is a mixture of (a) generic visiting operations, and (b)
-//! custom visit operations that are specific to the visitor.
-//! - The `TypeVisitable` impls handle most of the traversal, and call into
-//! `TypeVisitor` when they encounter a type of interest.
-//! - A `TypeVisitor` may call into another `TypeVisitable` impl, because some of
-//! the types of interest are recursive and can contain other types of interest.
-//! - A `TypeVisitor` may also call into a `TypeSuperVisitable` impl, because each
-//! visitor might provide custom handling only for some types of interest, or
-//! only for some variants of each type of interest, and then use default
-//! traversal for the remaining cases.
-//!
-//! For example, if you have `struct S(Ty, U)` where `S: TypeVisitable` and `U:
-//! TypeVisitable`, and an instance `s = S(ty, u)`, it would be visited like so:
-//! ```text
-//! s.visit_with(visitor) calls
-//! - ty.visit_with(visitor) calls
-//! - visitor.visit_ty(ty) may call
-//! - ty.super_visit_with(visitor)
-//! - u.visit_with(visitor)
-//! ```
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
use rustc_errors::ErrorGuaranteed;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sso::SsoHashSet;
-use std::fmt;
use std::ops::ControlFlow;
-/// This trait is implemented for every type that can be visited,
-/// providing the skeleton of the traversal.
-///
-/// To implement this conveniently, use the derive macro located in
-/// `rustc_macros`.
-pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
- /// The entry point for visiting. To visit a value `t` with a visitor `v`
- /// call: `t.visit_with(v)`.
- ///
- /// For most types, this just traverses the value, calling `visit_with` on
- /// each field/element.
- ///
- /// For types of interest (such as `Ty`), the implementation of this method
- /// that calls a visitor method specifically for that type (such as
- /// `V::visit_ty`). This is where control transfers from `TypeFoldable` to
- /// `TypeVisitor`.
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
+pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
/// Returns `true` if `self` has any late-bound regions that are either
/// bound by `binder` or bound by some binder outside of `binder`.
/// If `binder` is `ty::INNERMOST`, this indicates whether
@@ -100,6 +44,9 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
fn has_opaque_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
}
+ fn has_generators(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_TY_GENERATOR)
+ }
fn references_error(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_ERROR)
}
@@ -182,45 +129,7 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
}
}
-pub trait TypeSuperVisitable<'tcx>: TypeVisitable<'tcx> {
- /// Provides a default visit for a type of interest. This should only be
- /// called within `TypeVisitor` methods, when a non-custom traversal is
- /// desired for the value of the type of interest passed to that method.
- /// For example, in `MyVisitor::visit_ty(ty)`, it is valid to call
- /// `ty.super_visit_with(self)`, but any other visiting should be done
- /// with `xyz.visit_with(self)`.
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
-}
-
-/// This trait is implemented for every visiting traversal. There is a visit
-/// method defined for every type of interest. Each such method has a default
-/// that recurses into the type's fields in a non-custom fashion.
-pub trait TypeVisitor<'tcx>: Sized {
- type BreakTy = !;
-
- fn visit_binder<T: TypeVisitable<'tcx>>(
- &mut self,
- t: &Binder<'tcx, T>,
- ) -> ControlFlow<Self::BreakTy> {
- t.super_visit_with(self)
- }
-
- fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- t.super_visit_with(self)
- }
-
- fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
- r.super_visit_with(self)
- }
-
- fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- c.super_visit_with(self)
- }
-
- fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
- p.super_visit_with(self)
- }
-}
+impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitableExt<'tcx> for T {}
///////////////////////////////////////////////////////////////////////////
// Region folder
@@ -229,7 +138,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Invoke `callback` on every region appearing free in `value`.
pub fn for_each_free_region(
self,
- value: &impl TypeVisitable<'tcx>,
+ value: &impl TypeVisitable<TyCtxt<'tcx>>,
mut callback: impl FnMut(ty::Region<'tcx>),
) {
self.any_free_region_meets(value, |r| {
@@ -241,7 +150,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Returns `true` if `callback` returns true for every region appearing free in `value`.
pub fn all_free_regions_meet(
self,
- value: &impl TypeVisitable<'tcx>,
+ value: &impl TypeVisitable<TyCtxt<'tcx>>,
mut callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
!self.any_free_region_meets(value, |r| !callback(r))
@@ -250,7 +159,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Returns `true` if `callback` returns true for some region appearing free in `value`.
pub fn any_free_region_meets(
self,
- value: &impl TypeVisitable<'tcx>,
+ value: &impl TypeVisitable<TyCtxt<'tcx>>,
callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
struct RegionVisitor<F> {
@@ -275,13 +184,13 @@ impl<'tcx> TyCtxt<'tcx> {
callback: F,
}
- impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
+ impl<'tcx, F> TypeVisitor<TyCtxt<'tcx>> for RegionVisitor<F>
where
F: FnMut(ty::Region<'tcx>) -> bool,
{
type BreakTy = ();
- fn visit_binder<T: TypeVisitable<'tcx>>(
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -328,7 +237,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: &Binder<'tcx, T>,
) -> FxHashSet<ty::BoundRegionKind>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
self.collect_late_bound_regions(value, true)
}
@@ -339,7 +248,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: &Binder<'tcx, T>,
) -> FxHashSet<ty::BoundRegionKind>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
self.collect_late_bound_regions(value, false)
}
@@ -350,7 +259,7 @@ impl<'tcx> TyCtxt<'tcx> {
just_constraint: bool,
) -> FxHashSet<ty::BoundRegionKind>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
let mut collector = LateBoundRegionsCollector::new(just_constraint);
let result = value.as_ref().skip_binder().visit_with(&mut collector);
@@ -377,10 +286,10 @@ impl<'tcx> ValidateBoundVars<'tcx> {
}
}
-impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
type BreakTy = ();
- fn visit_binder<T: TypeVisitable<'tcx>>(
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -489,10 +398,10 @@ struct HasEscapingVarsVisitor {
outer_index: ty::DebruijnIndex,
}
-impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasEscapingVarsVisitor {
type BreakTy = FoundEscapingVars;
- fn visit_binder<T: TypeVisitable<'tcx>>(
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -566,7 +475,7 @@ impl std::fmt::Debug for HasTypeFlagsVisitor {
}
}
-impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags;
#[inline]
@@ -636,8 +545,8 @@ impl LateBoundRegionsCollector {
}
}
-impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
- fn visit_binder<T: TypeVisitable<'tcx>>(
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -698,7 +607,7 @@ impl MaxUniverse {
}
}
-impl<'tcx> TypeVisitor<'tcx> for MaxUniverse {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Placeholder(placeholder) = t.kind() {
self.max_universe = ty::UniverseIndex::from_u32(
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index f77bd9f0c..b9b1cd73a 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -112,5 +112,5 @@ pub(super) fn vtable_allocation_provider<'tcx>(
}
vtable.mutability = Mutability::Not;
- tcx.create_memory_alloc(tcx.intern_const_alloc(vtable))
+ tcx.create_memory_alloc(tcx.mk_const_alloc(vtable))
}
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 708a5e4d0..182945b9c 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -190,6 +190,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
ty::Adt(_, substs)
| ty::Closure(_, substs)
| ty::Generator(_, substs, _)
+ | ty::GeneratorWitnessMIR(_, substs)
| ty::FnDef(_, substs) => {
stack.extend(substs.iter().rev());
}
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 34e8a5597..c4f526dbd 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -2,7 +2,7 @@ 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;
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{DefKind, Res};
use rustc_middle::ty::Representability;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc_query_system::query::QueryInfo;
@@ -16,7 +16,7 @@ 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()) }
+ unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error_misc()) }
}
}
@@ -34,7 +34,7 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::SymbolName<'_> {
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 err = tcx.ty_error_misc();
let arity = if let Some(frame) = stack.get(0)
&& frame.query.dep_kind == DepKind::fn_sig
@@ -199,7 +199,8 @@ fn find_item_ty_spans(
) {
match ty.kind {
hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
- if let Some(def_id) = path.res.opt_def_id() {
+ if let Res::Def(kind, def_id) = path.res
+ && kind != DefKind::TyAlias {
let check_params = def_id.as_local().map_or(true, |def_id| {
if def_id == needle {
spans.push(ty.span);