summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle')
-rw-r--r--compiler/rustc_middle/Cargo.toml1
-rw-r--r--compiler/rustc_middle/messages.ftl35
-rw-r--r--compiler/rustc_middle/src/arena.rs10
-rw-r--r--compiler/rustc_middle/src/error.rs55
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs19
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs59
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs7
-rw-r--r--compiler/rustc_middle/src/lib.rs5
-rw-r--r--compiler/rustc_middle/src/lint.rs9
-rw-r--r--compiler/rustc_middle/src/middle/limits.rs11
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs35
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs12
-rw-r--r--compiler/rustc_middle/src/mir/basic_blocks.rs13
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs48
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs444
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs31
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs23
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs12
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs230
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs22
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs123
-rw-r--r--compiler/rustc_middle/src/mir/query.rs10
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs9
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs100
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs47
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs5
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs77
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs16
-rw-r--r--compiler/rustc_middle/src/query/erase.rs21
-rw-r--r--compiler/rustc_middle/src/query/keys.rs15
-rw-r--r--compiler/rustc_middle/src/query/mod.rs100
-rw-r--r--compiler/rustc_middle/src/query/on_disk_cache.rs7
-rw-r--r--compiler/rustc_middle/src/thir.rs13
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs3
-rw-r--r--compiler/rustc_middle/src/traits/chalk.rs396
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs192
-rw-r--r--compiler/rustc_middle/src/traits/query.rs2
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs26
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect.rs83
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect/format.rs131
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs2
-rw-r--r--compiler/rustc_middle/src/traits/structural_impls.rs96
-rw-r--r--compiler/rustc_middle/src/traits/util.rs4
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs2
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs2
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs6
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs2
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs2
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs2
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs35
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs285
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs9
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs204
-rw-r--r--compiler/rustc_middle/src/ty/context.rs622
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs65
-rw-r--r--compiler/rustc_middle/src/ty/error.rs14
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs22
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs29
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs26
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs19
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs12
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs200
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs333
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs12
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs189
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs83
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs142
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs573
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs61
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs10
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs6
-rw-r--r--compiler/rustc_middle/src/ty/util.rs150
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs2
-rw-r--r--compiler/rustc_middle/src/values.rs15
77 files changed, 2880 insertions, 2819 deletions
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 7c56af1da..4c238308f 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -7,7 +7,6 @@ edition = "2021"
[dependencies]
bitflags = "1.2.1"
-chalk-ir = "0.87.0"
derive_more = "0.99.17"
either = "1.5.0"
gsgdt = "0.1.2"
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 3d581daa9..bb7147ac8 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -1,3 +1,38 @@
+middle_adjust_for_foreign_abi_error =
+ target architecture {$arch} does not support `extern {$abi}` ABI
+
+middle_assert_async_resume_after_panic = `async fn` resumed after panicking
+
+middle_assert_async_resume_after_return = `async fn` resumed after completion
+
+middle_assert_divide_by_zero =
+ attempt to divide `{$val}` by zero
+
+middle_assert_generator_resume_after_panic = generator resumed after panicking
+
+middle_assert_generator_resume_after_return = generator resumed after completion
+
+middle_assert_misaligned_ptr_deref =
+ misaligned pointer dereference: address must be a multiple of {$required} but is {$found}
+
+middle_assert_op_overflow =
+ attempt to compute `{$left} {$op} {$right}`, which would overflow
+
+middle_assert_overflow_neg =
+ attempt to negate `{$val}`, which would overflow
+
+middle_assert_remainder_by_zero =
+ attempt to calculate the remainder of `{$val}` with a divisor of zero
+
+middle_assert_shl_overflow =
+ attempt to shift left by `{$val}`, which would overflow
+
+middle_assert_shr_overflow =
+ attempt to shift right by `{$val}`, which would overflow
+
+middle_bounds_check =
+ index out of bounds: the length is {$len} but the index is {$index}
+
middle_cannot_be_normalized =
unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index a149a61ec..5a320865c 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -27,6 +27,11 @@ macro_rules! arena_types {
rustc_middle::mir::Promoted,
rustc_middle::mir::Body<'tcx>
>,
+ [decode] closure_debuginfo:
+ rustc_index::IndexVec<
+ rustc_target::abi::FieldIdx,
+ rustc_span::symbol::Symbol,
+ >,
[decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>,
[decode] borrowck_result:
rustc_middle::mir::BorrowCheckResult<'tcx>,
@@ -78,9 +83,9 @@ macro_rules! arena_types {
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>>
>,
- [] type_op_normalize_predicate:
+ [] type_op_normalize_clause:
rustc_middle::infer::canonical::Canonical<'tcx,
- rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Predicate<'tcx>>
+ rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Clause<'tcx>>
>,
[] type_op_normalize_ty:
rustc_middle::infer::canonical::Canonical<'tcx,
@@ -124,6 +129,7 @@ macro_rules! arena_types {
[] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>,
[decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
[] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>),
+ [] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem,
[] mod_child: rustc_middle::metadata::ModChild,
]);
)
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 046186d27..57b2de84b 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -1,3 +1,7 @@
+use std::borrow::Cow;
+use std::fmt;
+
+use rustc_errors::{DiagnosticArgValue, DiagnosticMessage};
use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
@@ -88,3 +92,54 @@ pub(super) struct ConstNotUsedTraitAlias {
#[primary_span]
pub span: Span,
}
+
+pub struct CustomSubdiagnostic<'a> {
+ pub msg: fn() -> DiagnosticMessage,
+ pub add_args:
+ Box<dyn FnOnce(&mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>)) + 'a>,
+}
+
+impl<'a> CustomSubdiagnostic<'a> {
+ pub fn label(x: fn() -> DiagnosticMessage) -> Self {
+ Self::label_and_then(x, |_| {})
+ }
+ pub fn label_and_then<
+ F: FnOnce(&mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>)) + 'a,
+ >(
+ msg: fn() -> DiagnosticMessage,
+ f: F,
+ ) -> Self {
+ Self { msg, add_args: Box::new(move |x| f(x)) }
+ }
+}
+
+impl fmt::Debug for CustomSubdiagnostic<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("CustomSubdiagnostic").finish_non_exhaustive()
+ }
+}
+
+#[derive(Diagnostic)]
+pub enum LayoutError<'tcx> {
+ #[diag(middle_unknown_layout)]
+ Unknown { ty: Ty<'tcx> },
+
+ #[diag(middle_values_too_big)]
+ Overflow { ty: Ty<'tcx> },
+
+ #[diag(middle_cannot_be_normalized)]
+ NormalizationFailure { ty: Ty<'tcx>, failure_ty: String },
+
+ #[diag(middle_cycle)]
+ Cycle,
+}
+
+#[derive(Diagnostic)]
+#[diag(middle_adjust_for_foreign_abi_error)]
+pub struct UnsupportedFnAbi {
+ pub arch: Symbol,
+ pub abi: &'static str,
+}
+
+/// Used by `rustc_const_eval`
+pub use crate::fluent_generated::middle_adjust_for_foreign_abi_error;
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index d1ddc8fc1..5f2eb890c 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -44,6 +44,7 @@ pub fn associated_body(node: Node<'_>) -> Option<(LocalDefId, BodyId)> {
}
Node::AnonConst(constant) => Some((constant.def_id, constant.body)),
+ Node::ConstBlock(constant) => Some((constant.def_id, constant.body)),
_ => None,
}
@@ -240,15 +241,8 @@ impl<'hir> Map<'hir> {
None => bug!("constructor node without a constructor"),
}
}
- Node::AnonConst(_) => {
- let inline = match self.find_parent(hir_id) {
- Some(Node::Expr(&Expr {
- kind: ExprKind::ConstBlock(ref anon_const), ..
- })) if anon_const.hir_id == hir_id => true,
- _ => false,
- };
- if inline { DefKind::InlineConst } else { DefKind::AnonConst }
- }
+ Node::AnonConst(_) => DefKind::AnonConst,
+ Node::ConstBlock(_) => DefKind::InlineConst,
Node::Field(_) => DefKind::Field,
Node::Expr(expr) => match expr.kind {
ExprKind::Closure(Closure { movability: None, .. }) => DefKind::Closure,
@@ -1060,6 +1054,7 @@ impl<'hir> Map<'hir> {
Node::Variant(variant) => variant.span,
Node::Field(field) => field.span,
Node::AnonConst(constant) => self.body(constant.body).value.span,
+ Node::ConstBlock(constant) => self.body(constant.body).value.span,
Node::Expr(expr) => expr.span,
Node::ExprField(field) => field.span,
Node::Stmt(stmt) => stmt.span,
@@ -1289,6 +1284,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
}
Some(Node::AnonConst(_)) => node_str("const"),
+ Some(Node::ConstBlock(_)) => node_str("const"),
Some(Node::Expr(_)) => node_str("expr"),
Some(Node::ExprField(_)) => node_str("expr field"),
Some(Node::Stmt(_)) => node_str("stmt"),
@@ -1434,6 +1430,11 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
intravisit::walk_anon_const(self, c)
}
+ fn visit_inline_const(&mut self, c: &'hir ConstBlock) {
+ self.body_owners.push(c.def_id);
+ intravisit::walk_inline_const(self, c)
+ }
+
fn visit_expr(&mut self, ex: &'hir Expr<'hir>) {
if let ExprKind::Closure(closure) = ex.kind {
self.body_owners.push(closure.def_id);
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 561713149..d5e8330b3 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -82,15 +82,40 @@ impl CanonicalVarValues<'_> {
}
pub fn is_identity_modulo_regions(&self) -> bool {
- self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
- ty::GenericArgKind::Lifetime(_) => true,
- ty::GenericArgKind::Type(ty) => {
- matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
- }
- ty::GenericArgKind::Const(ct) => {
- matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
+ let mut var = ty::BoundVar::from_u32(0);
+ for arg in self.var_values {
+ match arg.unpack() {
+ ty::GenericArgKind::Lifetime(r) => {
+ if let ty::ReLateBound(ty::INNERMOST, br) = *r
+ && var == br.var
+ {
+ var = var + 1;
+ } else {
+ // It's ok if this region var isn't unique
+ }
+ },
+ ty::GenericArgKind::Type(ty) => {
+ if let ty::Bound(ty::INNERMOST, bt) = *ty.kind()
+ && var == bt.var
+ {
+ var = var + 1;
+ } else {
+ return false;
+ }
+ }
+ ty::GenericArgKind::Const(ct) => {
+ if let ty::ConstKind::Bound(ty::INNERMOST, bc) = ct.kind()
+ && var == bc
+ {
+ var = var + 1;
+ } else {
+ return false;
+ }
+ }
}
- })
+ }
+
+ true
}
}
@@ -408,22 +433,24 @@ impl<'tcx> CanonicalVarValues<'tcx> {
|(i, info)| -> ty::GenericArg<'tcx> {
match info.kind {
CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
- tcx.mk_bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into()).into()
+ Ty::new_bound(tcx, 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(None),
};
- tcx.mk_re_late_bound(ty::INNERMOST, br).into()
+ ty::Region::new_late_bound(tcx, 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(),
+ | CanonicalVarKind::PlaceholderConst(_, ty) => ty::Const::new_bound(
+ tcx,
+ ty::INNERMOST,
+ ty::BoundVar::from_usize(i),
+ ty,
+ )
+ .into(),
}
},
)),
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index a873854f0..85fb9214d 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -90,15 +90,15 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
impl ToType for ty::IntVarValue {
fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match *self {
- ty::IntType(i) => tcx.mk_mach_int(i),
- ty::UintType(i) => tcx.mk_mach_uint(i),
+ ty::IntType(i) => Ty::new_int(tcx, i),
+ ty::UintType(i) => Ty::new_uint(tcx, i),
}
}
}
impl ToType for ty::FloatVarValue {
fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- tcx.mk_mach_float(self.0)
+ Ty::new_float(tcx, self.0)
}
}
@@ -116,7 +116,6 @@ pub enum ConstVariableOriginKind {
MiscVariable,
ConstInference,
ConstParameterDefinition(Symbol, DefId),
- SubstitutionPlaceholder,
}
#[derive(Copy, Clone, Debug)]
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 22ee2a8c5..1b125e8e2 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -48,12 +48,13 @@
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
#![feature(control_flow_enum)]
+#![feature(trait_upcasting)]
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(try_reserve_kind)]
#![feature(nonzero_ops)]
#![feature(decl_macro)]
-#![feature(drain_filter)]
+#![feature(extract_if)]
#![feature(intra_doc_pointers)]
#![feature(yeet_expr)]
#![feature(result_option_inspect)]
@@ -86,7 +87,7 @@ mod macros;
#[macro_use]
pub mod arena;
-pub(crate) mod error;
+pub mod error;
pub mod hir;
pub mod infer;
pub mod lint;
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 14343ac11..81c1ae4f6 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -251,7 +251,7 @@ pub fn explain_lint_level_source(
}
LintLevelSource::Node { name: lint_attr_name, span, reason, .. } => {
if let Some(rationale) = reason {
- err.note(rationale.as_str());
+ err.note(rationale.to_string());
}
err.span_note_once(span, "the lint level is defined here");
if lint_attr_name.as_str() != name {
@@ -388,10 +388,11 @@ pub fn struct_lint_level(
// it'll become a hard error, so we have to emit *something*. Also,
// if this lint occurs in the expansion of a macro from an external crate,
// allow individual lints to opt-out from being reported.
- let not_future_incompatible =
- future_incompatible.map(|f| f.reason.edition().is_some()).unwrap_or(true);
- if not_future_incompatible && !lint.report_in_external_macro {
+ let incompatible = future_incompatible.is_some_and(|f| f.reason.edition().is_none());
+
+ if !incompatible && !lint.report_in_external_macro {
err.cancel();
+
// Don't continue further, since we don't want to have
// `diag_span_note_once` called for a diagnostic that isn't emitted.
return;
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index bd859d4d6..d4f023958 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -1,8 +1,7 @@
//! Registering limits:
//! * recursion_limit,
-//! * move_size_limit,
-//! * type_length_limit, and
-//! * const_eval_limit
+//! * move_size_limit, and
+//! * type_length_limit
//!
//! There are various parts of the compiler that must impose arbitrary limits
//! on how deeply they recurse to prevent stack overflow. Users can override
@@ -34,12 +33,6 @@ pub fn provide(providers: &mut Providers) {
sym::type_length_limit,
1048576,
),
- const_eval_limit: get_limit(
- tcx.hir().krate_attrs(),
- tcx.sess,
- sym::const_eval_limit,
- 2_000_000,
- ),
}
}
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index f45cf788d..5baeb1ee0 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -4,6 +4,7 @@
use crate::ty::{TyCtxt, Visibility};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::def::DefKind;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID};
@@ -148,13 +149,12 @@ impl EffectiveVisibilities {
};
}
- pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) {
+ pub fn check_invariants(&self, tcx: TyCtxt<'_>) {
if !cfg!(debug_assertions) {
return;
}
for (&def_id, ev) in &self.map {
// More direct visibility levels can never go farther than less direct ones,
- // neither of effective visibilities can go farther than nominal visibility,
// and all effective visibilities are larger or equal than private visibility.
let private_vis = Visibility::Restricted(tcx.parent_module_from_def_id(def_id));
let span = tcx.def_span(def_id.to_def_id());
@@ -175,17 +175,20 @@ impl EffectiveVisibilities {
ev.reachable_through_impl_trait
);
}
- let nominal_vis = tcx.visibility(def_id);
- // FIXME: `rustc_privacy` is not yet updated for the new logic and can set
- // effective visibilities that are larger than the nominal one.
- if !nominal_vis.is_at_least(ev.reachable_through_impl_trait, tcx) && early {
- span_bug!(
- span,
- "{:?}: reachable_through_impl_trait {:?} > nominal {:?}",
- def_id,
- ev.reachable_through_impl_trait,
- nominal_vis
- );
+ // All effective visibilities except `reachable_through_impl_trait` are limited to
+ // nominal visibility. For some items nominal visibility doesn't make sense so we
+ // don't check this condition for them.
+ if !matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) {
+ let nominal_vis = tcx.visibility(def_id);
+ if !nominal_vis.is_at_least(ev.reachable, tcx) {
+ span_bug!(
+ span,
+ "{:?}: reachable {:?} > nominal {:?}",
+ def_id,
+ ev.reachable,
+ nominal_vis
+ );
+ }
}
}
}
@@ -212,7 +215,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
pub fn update(
&mut self,
id: Id,
- nominal_vis: Option<Visibility>,
+ max_vis: Option<Visibility>,
lazy_private_vis: impl FnOnce() -> Visibility,
inherited_effective_vis: EffectiveVisibility,
level: Level,
@@ -236,8 +239,8 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level
&& level != l)
{
- calculated_effective_vis = if let Some(nominal_vis) = nominal_vis && !nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
- nominal_vis
+ calculated_effective_vis = if let Some(max_vis) = max_vis && !max_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
+ max_vis
} else {
inherited_effective_vis_at_level
}
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 6354c0aab..60844c17e 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -104,7 +104,7 @@ pub fn report_unstable(
suggestion: Option<(Span, String, String, Applicability)>,
is_soft: bool,
span: Span,
- soft_handler: impl FnOnce(&'static Lint, Span, &str),
+ soft_handler: impl FnOnce(&'static Lint, Span, String),
) {
let msg = match reason {
Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
@@ -112,7 +112,7 @@ pub fn report_unstable(
};
if is_soft {
- soft_handler(SOFT_UNSTABLE, span, &msg)
+ soft_handler(SOFT_UNSTABLE, span, msg)
} else {
let mut err =
feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), msg);
@@ -225,7 +225,7 @@ pub fn deprecation_message_and_lint(
pub fn early_report_deprecation(
lint_buffer: &mut LintBuffer,
- message: &str,
+ message: String,
suggestion: Option<Symbol>,
lint: &'static Lint,
span: Span,
@@ -241,7 +241,7 @@ pub fn early_report_deprecation(
fn late_report_deprecation(
tcx: TyCtxt<'_>,
- message: &str,
+ message: String,
suggestion: Option<Symbol>,
lint: &'static Lint,
span: Span,
@@ -396,7 +396,7 @@ impl<'tcx> TyCtxt<'tcx> {
late_report_deprecation(
self,
- &deprecation_message(
+ deprecation_message(
is_in_effect,
depr_attr.since,
depr_attr.note,
@@ -619,7 +619,7 @@ impl<'tcx> TyCtxt<'tcx> {
allow_unstable: AllowUnstable,
unmarked: impl FnOnce(Span, DefId),
) -> bool {
- let soft_handler = |lint, span, msg: &_| {
+ let soft_handler = |lint, span, msg: String| {
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |lint| lint)
};
let eval_result =
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index 9d70dbfa0..7722e7b47 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -26,7 +26,7 @@ struct Cache {
predecessors: OnceCell<Predecessors>,
switch_sources: OnceCell<SwitchSources>,
is_cyclic: OnceCell<bool>,
- postorder: OnceCell<Vec<BasicBlock>>,
+ reverse_postorder: OnceCell<Vec<BasicBlock>>,
dominators: OnceCell<Dominators<BasicBlock>>,
}
@@ -62,11 +62,14 @@ impl<'tcx> BasicBlocks<'tcx> {
})
}
- /// Returns basic blocks in a postorder.
+ /// Returns basic blocks in a reverse postorder.
#[inline]
- pub fn postorder(&self) -> &[BasicBlock] {
- self.cache.postorder.get_or_init(|| {
- Postorder::new(&self.basic_blocks, START_BLOCK).map(|(bb, _)| bb).collect()
+ pub fn reverse_postorder(&self) -> &[BasicBlock] {
+ self.cache.reverse_postorder.get_or_init(|| {
+ let mut rpo: Vec<_> =
+ Postorder::new(&self.basic_blocks, START_BLOCK).map(|(bb, _)| bb).collect();
+ rpo.reverse();
+ rpo
})
}
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 1a8e48264..b8030d9db 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -296,25 +296,13 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
Allocation::from_bytes(slice, Align::ONE, Mutability::Not)
}
- /// Try to create an Allocation of `size` bytes, failing if there is not enough memory
- /// available to the compiler to do so.
- ///
- /// 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 = 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
- // evaluation (including ConstProp!) will make compilation fail (via hard error
- // or ICE) upon encountering a `MemoryExhausted` error.
- if panic_on_fail {
- panic!("Allocation::uninit called with panic_on_fail had allocation failure")
- }
- ty::tls::with(|tcx| {
- tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpretation")
- });
- InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
- })?;
+ fn uninit_inner<R>(size: Size, align: Align, fail: impl FnOnce() -> R) -> Result<Self, R> {
+ // 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
+ // evaluation (including ConstProp!) will make compilation fail (via hard error
+ // or ICE) upon encountering a `MemoryExhausted` error.
+ let bytes = Bytes::zeroed(size, align).ok_or_else(fail)?;
Ok(Allocation {
bytes,
@@ -325,6 +313,28 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
extra: (),
})
}
+
+ /// Try to create an Allocation of `size` bytes, failing if there is not enough memory
+ /// available to the compiler to do so.
+ pub fn try_uninit<'tcx>(size: Size, align: Align) -> InterpResult<'tcx, Self> {
+ Self::uninit_inner(size, align, || {
+ ty::tls::with(|tcx| {
+ tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpretation")
+ });
+ InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted).into()
+ })
+ }
+
+ /// Try to create an Allocation of `size` bytes, panics if there is not enough memory
+ /// available to the compiler to do so.
+ pub fn uninit(size: Size, align: Align) -> Self {
+ match Self::uninit_inner(size, align, || {
+ panic!("Allocation::uninit called with panic_on_fail had allocation failure");
+ }) {
+ Ok(x) => x,
+ Err(x) => x,
+ }
+ }
}
impl<Bytes: AllocBytes> Allocation<AllocId, (), Bytes> {
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 055d8e9a3..2435bc59e 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -5,11 +5,15 @@ use crate::query::TyCtxtAt;
use crate::ty::{layout, tls, Ty, ValTree};
use rustc_data_structures::sync::Lock;
-use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{
+ struct_span_err, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed,
+ IntoDiagnosticArg,
+};
use rustc_macros::HashStable;
use rustc_session::CtfeBacktrace;
use rustc_span::def_id::DefId;
-use rustc_target::abi::{call, Align, Size};
+use rustc_target::abi::{call, Align, Size, WrappingRange};
+use std::borrow::Cow;
use std::{any::Any, backtrace::Backtrace, fmt};
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
@@ -91,21 +95,54 @@ pub struct InterpErrorInfo<'tcx>(Box<InterpErrorInfoInner<'tcx>>);
#[derive(Debug)]
struct InterpErrorInfoInner<'tcx> {
kind: InterpError<'tcx>,
+ backtrace: InterpErrorBacktrace,
+}
+
+#[derive(Debug)]
+pub struct InterpErrorBacktrace {
backtrace: Option<Box<Backtrace>>,
}
-impl fmt::Display for InterpErrorInfo<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}", self.0.kind)
+impl InterpErrorBacktrace {
+ pub fn new() -> InterpErrorBacktrace {
+ let capture_backtrace = tls::with_opt(|tcx| {
+ if let Some(tcx) = tcx {
+ *Lock::borrow(&tcx.sess.ctfe_backtrace)
+ } else {
+ CtfeBacktrace::Disabled
+ }
+ });
+
+ let backtrace = match capture_backtrace {
+ CtfeBacktrace::Disabled => None,
+ CtfeBacktrace::Capture => Some(Box::new(Backtrace::force_capture())),
+ CtfeBacktrace::Immediate => {
+ // Print it now.
+ let backtrace = Backtrace::force_capture();
+ print_backtrace(&backtrace);
+ None
+ }
+ };
+
+ InterpErrorBacktrace { backtrace }
}
-}
-impl<'tcx> InterpErrorInfo<'tcx> {
pub fn print_backtrace(&self) {
- if let Some(backtrace) = self.0.backtrace.as_ref() {
+ if let Some(backtrace) = self.backtrace.as_ref() {
print_backtrace(backtrace);
}
}
+}
+
+impl<'tcx> InterpErrorInfo<'tcx> {
+ pub fn from_parts(kind: InterpError<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
+ Self(Box::new(InterpErrorInfoInner { kind, backtrace }))
+ }
+
+ pub fn into_parts(self) -> (InterpError<'tcx>, InterpErrorBacktrace) {
+ let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self;
+ (kind, backtrace)
+ }
pub fn into_kind(self) -> InterpError<'tcx> {
let InterpErrorInfo(box InterpErrorInfoInner { kind, .. }) = self;
@@ -130,32 +167,17 @@ impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpError<'tcx>) -> Self {
- let capture_backtrace = tls::with_opt(|tcx| {
- if let Some(tcx) = tcx {
- *Lock::borrow(&tcx.sess.ctfe_backtrace)
- } else {
- CtfeBacktrace::Disabled
- }
- });
-
- let backtrace = match capture_backtrace {
- CtfeBacktrace::Disabled => None,
- CtfeBacktrace::Capture => Some(Box::new(Backtrace::force_capture())),
- CtfeBacktrace::Immediate => {
- // Print it now.
- let backtrace = Backtrace::force_capture();
- print_backtrace(&backtrace);
- None
- }
- };
-
- InterpErrorInfo(Box::new(InterpErrorInfoInner { kind, backtrace }))
+ InterpErrorInfo(Box::new(InterpErrorInfoInner {
+ kind,
+ backtrace: InterpErrorBacktrace::new(),
+ }))
}
}
/// Error information for when the program we executed turned out not to actually be a valid
/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
/// where we work on generic code or execution does not have all information available.
+#[derive(Debug)]
pub enum InvalidProgramInfo<'tcx> {
/// Resolution can fail if we are in a too generic context.
TooGeneric,
@@ -174,25 +196,6 @@ pub enum InvalidProgramInfo<'tcx> {
UninitUnsizedLocal,
}
-impl fmt::Display for InvalidProgramInfo<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- use InvalidProgramInfo::*;
- match self {
- TooGeneric => write!(f, "encountered overly generic constant"),
- AlreadyReported(_) => {
- write!(
- f,
- "an error has already been reported elsewhere (this should not usually be printed)"
- )
- }
- Layout(ref err) => write!(f, "{err}"),
- FnAbiAdjustForForeignAbi(ref err) => write!(f, "{err}"),
- SizeOfUnsizedType(ty) => write!(f, "size_of called on unsized type `{ty}`"),
- UninitUnsizedLocal => write!(f, "unsized local is used while uninitialized"),
- }
- }
-}
-
/// Details of why a pointer had to be in-bounds.
#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
pub enum CheckInAllocMsg {
@@ -208,26 +211,25 @@ pub enum CheckInAllocMsg {
InboundsTest,
}
-impl fmt::Display for CheckInAllocMsg {
- /// When this is printed as an error the context looks like this:
- /// "{msg}{pointer} is a dangling pointer".
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(
- f,
- "{}",
- match *self {
- CheckInAllocMsg::DerefTest => "dereferencing pointer failed: ",
- CheckInAllocMsg::MemoryAccessTest => "memory access failed: ",
- CheckInAllocMsg::PointerArithmeticTest => "out-of-bounds pointer arithmetic: ",
- CheckInAllocMsg::OffsetFromTest => "out-of-bounds offset_from: ",
- CheckInAllocMsg::InboundsTest => "out-of-bounds pointer use: ",
- }
- )
+#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
+pub enum InvalidMetaKind {
+ /// Size of a `[T]` is too big
+ SliceTooBig,
+ /// Size of a DST is too big
+ TooBig,
+}
+
+impl IntoDiagnosticArg for InvalidMetaKind {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Borrowed(match self {
+ InvalidMetaKind::SliceTooBig => "slice_too_big",
+ InvalidMetaKind::TooBig => "too_big",
+ }))
}
}
/// Details of an access to uninitialized bytes where it is not allowed.
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
pub struct UninitBytesAccess {
/// Range of the original memory access.
pub access: AllocRange,
@@ -242,17 +244,32 @@ pub struct ScalarSizeMismatch {
pub data_size: u64,
}
+macro_rules! impl_into_diagnostic_arg_through_debug {
+ ($($ty:ty),*$(,)?) => {$(
+ impl IntoDiagnosticArg for $ty {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(format!("{self:?}")))
+ }
+ }
+ )*}
+}
+
+// These types have nice `Debug` output so we can just use them in diagnostics.
+impl_into_diagnostic_arg_through_debug! {
+ AllocId,
+ Pointer,
+ AllocRange,
+}
+
/// Error information for when the program caused Undefined Behavior.
-pub enum UndefinedBehaviorInfo {
- /// Free-form case. Only for errors that are never caught!
+#[derive(Debug)]
+pub enum UndefinedBehaviorInfo<'a> {
+ /// Free-form case. Only for errors that are never caught! Used by miri
Ub(String),
/// Unreachable code was executed.
Unreachable,
/// A slice/array index projection went out-of-bounds.
- BoundsCheckFailed {
- len: u64,
- index: u64,
- },
+ BoundsCheckFailed { len: u64, index: u64 },
/// Something was divided by 0 (x / 0).
DivisionByZero,
/// Something was "remainded" by 0 (x % 0).
@@ -263,8 +280,8 @@ pub enum UndefinedBehaviorInfo {
RemainderOverflow,
/// Overflowing inbounds pointer arithmetic.
PointerArithOverflow,
- /// Invalid metadata in a wide pointer (using `str` to avoid allocations).
- InvalidMeta(&'static str),
+ /// Invalid metadata in a wide pointer
+ InvalidMeta(InvalidMetaKind),
/// Reading a C string that does not end within its allocation.
UnterminatedCString(Pointer),
/// Dereferencing a dangling pointer after it got freed.
@@ -281,25 +298,13 @@ pub enum UndefinedBehaviorInfo {
/// Using an integer as a pointer in the wrong way.
DanglingIntPointer(u64, CheckInAllocMsg),
/// Used a pointer with bad alignment.
- AlignmentCheckFailed {
- required: Align,
- has: Align,
- },
+ AlignmentCheckFailed { required: Align, has: Align },
/// Writing to read-only memory.
WriteToReadOnly(AllocId),
- // Trying to access the data behind a function pointer.
+ /// Trying to access the data behind a function pointer.
DerefFunctionPointer(AllocId),
- // Trying to access the data behind a vtable pointer.
+ /// Trying to access the data behind a vtable pointer.
DerefVTablePointer(AllocId),
- /// The value validity check found a problem.
- /// Should only be thrown by `validity.rs` and always point out which part of the value
- /// is the problem.
- ValidationFailure {
- /// The "path" to the value in question, e.g. `.0[5].field` for a struct
- /// field in the 6th element of an array that is the first element of a tuple.
- path: Option<String>,
- msg: String,
- },
/// Using a non-boolean `u8` as bool.
InvalidBool(u8),
/// Using a non-character `u32` as character.
@@ -320,110 +325,100 @@ pub enum UndefinedBehaviorInfo {
ScalarSizeMismatch(ScalarSizeMismatch),
/// A discriminant of an uninhabited enum variant is written.
UninhabitedEnumVariantWritten,
+ /// Validation error.
+ Validation(ValidationErrorInfo<'a>),
+ // FIXME(fee1-dead) these should all be actual variants of the enum instead of dynamically
+ // dispatched
+ /// A custom (free-form) error, created by `err_ub_custom!`.
+ Custom(crate::error::CustomSubdiagnostic<'a>),
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum PointerKind {
+ Ref,
+ Box,
+}
+
+impl IntoDiagnosticArg for PointerKind {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(
+ match self {
+ Self::Ref => "ref",
+ Self::Box => "box",
+ }
+ .into(),
+ )
+ }
}
-impl fmt::Display for UndefinedBehaviorInfo {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- use UndefinedBehaviorInfo::*;
- match self {
- Ub(msg) => write!(f, "{msg}"),
- Unreachable => write!(f, "entering unreachable code"),
- BoundsCheckFailed { ref len, ref index } => {
- write!(f, "indexing out of bounds: the len is {len} but the index is {index}")
- }
- DivisionByZero => write!(f, "dividing by zero"),
- RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
- DivisionOverflow => write!(f, "overflow in signed division (dividing MIN by -1)"),
- RemainderOverflow => write!(f, "overflow in signed remainder (dividing MIN by -1)"),
- PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
- InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {msg}"),
- UnterminatedCString(p) => write!(
- f,
- "reading a null-terminated string starting at {p:?} with no null found before end of allocation",
- ),
- PointerUseAfterFree(a) => {
- write!(f, "pointer to {a:?} was dereferenced after this allocation got freed")
- }
- PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size: Size::ZERO, msg } => {
- write!(
- f,
- "{msg}{alloc_id:?} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds",
- alloc_size = alloc_size.bytes(),
- )
- }
- PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => write!(
- f,
- "{msg}{alloc_id:?} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds",
- alloc_size = alloc_size.bytes(),
- ptr_size = ptr_size.bytes(),
- ptr_size_p = pluralize!(ptr_size.bytes()),
- ),
- DanglingIntPointer(i, msg) => {
- write!(
- f,
- "{msg}{pointer} is a dangling pointer (it has no provenance)",
- pointer = Pointer::<Option<AllocId>>::from_addr_invalid(*i),
- )
- }
- AlignmentCheckFailed { required, has } => write!(
- f,
- "accessing memory with alignment {has}, but alignment {required} is required",
- has = has.bytes(),
- required = required.bytes()
- ),
- WriteToReadOnly(a) => write!(f, "writing to {a:?} which is read-only"),
- DerefFunctionPointer(a) => write!(f, "accessing {a:?} which contains a function"),
- DerefVTablePointer(a) => write!(f, "accessing {a:?} which contains a vtable"),
- ValidationFailure { path: None, msg } => {
- write!(f, "constructing invalid value: {msg}")
- }
- ValidationFailure { path: Some(path), msg } => {
- write!(f, "constructing invalid value at {path}: {msg}")
- }
- InvalidBool(b) => {
- write!(f, "interpreting an invalid 8-bit value as a bool: 0x{b:02x}")
- }
- InvalidChar(c) => {
- write!(f, "interpreting an invalid 32-bit value as a char: 0x{c:08x}")
- }
- InvalidTag(val) => write!(f, "enum value has invalid tag: {val:x}"),
- InvalidFunctionPointer(p) => {
- write!(f, "using {p:?} as function pointer but it does not point to a function")
- }
- InvalidVTablePointer(p) => {
- write!(f, "using {p:?} as vtable pointer but it does not point to a vtable")
- }
- InvalidStr(err) => write!(f, "this string is not valid UTF-8: {err}"),
- InvalidUninitBytes(Some((alloc, info))) => write!(
- f,
- "reading memory at {alloc:?}{access:?}, \
- but memory is uninitialized at {uninit:?}, \
- and this operation requires initialized memory",
- access = info.access,
- uninit = info.uninit,
- ),
- InvalidUninitBytes(None) => write!(
- f,
- "using uninitialized data, but this operation requires initialized memory"
- ),
- DeadLocal => write!(f, "accessing a dead local variable"),
- ScalarSizeMismatch(self::ScalarSizeMismatch { target_size, data_size }) => write!(
- f,
- "scalar size mismatch: expected {target_size} bytes but got {data_size} bytes instead",
- ),
- UninhabitedEnumVariantWritten => {
- write!(f, "writing discriminant of an uninhabited enum")
- }
+#[derive(Debug)]
+pub struct ValidationErrorInfo<'tcx> {
+ pub path: Option<String>,
+ pub kind: ValidationErrorKind<'tcx>,
+}
+
+#[derive(Debug)]
+pub enum ExpectedKind {
+ Reference,
+ Box,
+ RawPtr,
+ InitScalar,
+ Bool,
+ Char,
+ Float,
+ Int,
+ FnPtr,
+}
+
+impl From<PointerKind> for ExpectedKind {
+ fn from(x: PointerKind) -> ExpectedKind {
+ match x {
+ PointerKind::Box => ExpectedKind::Box,
+ PointerKind::Ref => ExpectedKind::Reference,
}
}
}
+#[derive(Debug)]
+pub enum ValidationErrorKind<'tcx> {
+ PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
+ PtrToStatic { ptr_kind: PointerKind },
+ PtrToMut { ptr_kind: PointerKind },
+ ExpectedNonPtr { value: String },
+ MutableRefInConst,
+ NullFnPtr,
+ NeverVal,
+ NullablePtrOutOfRange { range: WrappingRange, max_value: u128 },
+ PtrOutOfRange { range: WrappingRange, max_value: u128 },
+ OutOfRange { value: String, range: WrappingRange, max_value: u128 },
+ UnsafeCell,
+ UninhabitedVal { ty: Ty<'tcx> },
+ InvalidEnumTag { value: String },
+ UninitEnumTag,
+ UninitStr,
+ Uninit { expected: ExpectedKind },
+ UninitVal,
+ InvalidVTablePtr { value: String },
+ InvalidMetaSliceTooLarge { ptr_kind: PointerKind },
+ InvalidMetaTooLarge { ptr_kind: PointerKind },
+ UnalignedPtr { ptr_kind: PointerKind, required_bytes: u64, found_bytes: u64 },
+ NullPtr { ptr_kind: PointerKind },
+ DanglingPtrNoProvenance { ptr_kind: PointerKind, pointer: String },
+ DanglingPtrOutOfBounds { ptr_kind: PointerKind },
+ DanglingPtrUseAfterFree { ptr_kind: PointerKind },
+ InvalidBool { value: String },
+ InvalidChar { value: String },
+ InvalidFnPtr { value: String },
+}
+
/// Error information for when the program did something that might (or might not) be correct
/// to do according to the Rust spec, but due to limitations in the interpreter, the
/// operation could not be carried out. These limitations can differ between CTFE and the
/// Miri engine, e.g., CTFE does not support dereferencing pointers at integral addresses.
+#[derive(Debug)]
pub enum UnsupportedOpInfo {
/// Free-form case. Only for errors that are never caught!
+ // FIXME still use translatable diagnostics
Unsupported(String),
//
// The variants below are only reachable from CTFE/const prop, miri will never emit them.
@@ -442,83 +437,42 @@ pub enum UnsupportedOpInfo {
ReadExternStatic(DefId),
}
-impl fmt::Display for UnsupportedOpInfo {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- use UnsupportedOpInfo::*;
- match self {
- Unsupported(ref msg) => write!(f, "{msg}"),
- PartialPointerOverwrite(ptr) => {
- write!(f, "unable to overwrite parts of a pointer in memory at {ptr:?}")
- }
- PartialPointerCopy(ptr) => {
- write!(f, "unable to copy parts of a pointer from memory at {ptr:?}")
- }
- ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes"),
- ThreadLocalStatic(did) => write!(f, "cannot access thread local static ({did:?})"),
- ReadExternStatic(did) => write!(f, "cannot read from extern static ({did:?})"),
- }
- }
-}
-
/// Error information for when the program exhausted the resources granted to it
/// by the interpreter.
+#[derive(Debug)]
pub enum ResourceExhaustionInfo {
/// The stack grew too big.
StackFrameLimitReached,
- /// The program ran for too long.
- ///
- /// The exact limit is set by the `const_eval_limit` attribute.
- StepLimitReached,
/// 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 {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- use ResourceExhaustionInfo::*;
- match self {
- StackFrameLimitReached => {
- write!(f, "reached the configured maximum number of stack frames")
- }
- StepLimitReached => {
- write!(f, "exceeded interpreter step limit (see `#[const_eval_limit]`)")
- }
- 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")
- }
- }
- }
-}
-
-/// A trait to work around not having trait object upcasting.
-pub trait AsAny: Any {
- fn as_any(&self) -> &dyn Any;
-}
-impl<T: Any> AsAny for T {
- #[inline(always)]
- fn as_any(&self) -> &dyn Any {
- self
- }
-}
-
/// A trait for machine-specific errors (or other "machine stop" conditions).
-pub trait MachineStopType: AsAny + fmt::Display + Send {}
+pub trait MachineStopType: Any + fmt::Debug + Send {
+ /// The diagnostic message for this error
+ fn diagnostic_message(&self) -> DiagnosticMessage;
+ /// Add diagnostic arguments by passing name and value pairs to `adder`, which are passed to
+ /// fluent for formatting the translated diagnostic message.
+ fn add_args(
+ self: Box<Self>,
+ adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>),
+ );
+}
impl dyn MachineStopType {
#[inline(always)]
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
- self.as_any().downcast_ref()
+ let x: &dyn Any = self;
+ x.downcast_ref()
}
}
+#[derive(Debug)]
pub enum InterpError<'tcx> {
/// The program caused undefined behavior.
- UndefinedBehavior(UndefinedBehaviorInfo),
+ UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
/// The program did something the interpreter does not support (some of these *might* be UB
/// but the interpreter is not sure).
Unsupported(UnsupportedOpInfo),
@@ -534,26 +488,6 @@ pub enum InterpError<'tcx> {
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
-impl fmt::Display for InterpError<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- use InterpError::*;
- match *self {
- Unsupported(ref msg) => write!(f, "{msg}"),
- InvalidProgram(ref msg) => write!(f, "{msg}"),
- UndefinedBehavior(ref msg) => write!(f, "{msg}"),
- ResourceExhaustion(ref msg) => write!(f, "{msg}"),
- MachineStop(ref msg) => write!(f, "{msg}"),
- }
- }
-}
-
-// Forward `Debug` to `Display`, so it does not look awful.
-impl fmt::Debug for InterpError<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(self, f)
- }
-}
-
impl InterpError<'_> {
/// Some errors do string formatting even if the error is never printed.
/// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors,
@@ -562,7 +496,7 @@ impl InterpError<'_> {
matches!(
self,
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
- | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. })
+ | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Validation { .. })
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
)
}
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 3620385fa..2d2cfee1b 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -89,6 +89,30 @@ macro_rules! throw_machine_stop {
($($tt:tt)*) => { do yeet err_machine_stop!($($tt)*) };
}
+#[macro_export]
+macro_rules! err_ub_custom {
+ ($msg:expr $(, $($name:ident = $value:expr),* $(,)?)?) => {{
+ $(
+ let ($($name,)*) = ($($value,)*);
+ )?
+ err_ub!(Custom(
+ rustc_middle::error::CustomSubdiagnostic {
+ msg: || $msg,
+ add_args: Box::new(move |mut set_arg| {
+ $($(
+ set_arg(stringify!($name).into(), rustc_errors::IntoDiagnosticArg::into_diagnostic_arg($name));
+ )*)?
+ })
+ }
+ ))
+ }};
+}
+
+#[macro_export]
+macro_rules! throw_ub_custom {
+ ($($tt:tt)*) => { do yeet err_ub_custom!($($tt)*) };
+}
+
mod allocation;
mod error;
mod pointer;
@@ -119,9 +143,10 @@ use crate::ty::{self, Instance, Ty, TyCtxt};
pub use self::error::{
struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
- EvalToValTreeResult, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo,
- MachineStopType, ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch,
- UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
+ EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind,
+ InvalidProgramInfo, MachineStopType, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo,
+ ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
+ ValidationErrorInfo, ValidationErrorKind,
};
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index f53dc8cb0..9c97431f3 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -95,8 +95,15 @@ impl<'tcx> TyCtxt<'tcx> {
// used generic parameters is a bug of evaluation, so checking for it
// here does feel somewhat sensible.
if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
- assert!(matches!(self.def_kind(ct.def), DefKind::AnonConst));
- let mir_body = self.mir_for_ctfe(ct.def);
+ let def_kind = self.def_kind(instance.def_id());
+ assert!(
+ matches!(
+ def_kind,
+ DefKind::InlineConst | DefKind::AnonConst | DefKind::AssocConst
+ ),
+ "{cid:?} is {def_kind:?}",
+ );
+ let mir_body = self.mir_for_ctfe(instance.def_id());
if mir_body.is_polymorphic {
let Some(local_def_id) = ct.def.as_local() else { return };
self.struct_span_lint_hir(
@@ -236,15 +243,3 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
self.eval_to_allocation_raw(param_env.and(gid))
}
}
-
-impl<'tcx> TyCtxt<'tcx> {
- /// Destructure a mir constant ADT or array into its variant index and its field values.
- /// Panics if the destructuring fails, use `try_destructure_mir_constant` for fallible version.
- pub fn destructure_mir_constant(
- self,
- param_env: ty::ParamEnv<'tcx>,
- constant: mir::ConstantKind<'tcx>,
- ) -> mir::DestructuredConstant<'tcx> {
- self.try_destructure_mir_constant(param_env.and(constant)).unwrap()
- }
-}
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 36dbbe4bf..0416411df 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -97,6 +97,10 @@ impl<'tcx> ConstValue<'tcx> {
ConstValue::Scalar(Scalar::from_u64(i))
}
+ pub fn from_u128(i: u128) -> Self {
+ ConstValue::Scalar(Scalar::from_u128(i))
+ }
+
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
ConstValue::Scalar(Scalar::from_target_usize(i, cx))
}
@@ -241,6 +245,11 @@ impl<Prov> Scalar<Prov> {
}
#[inline]
+ pub fn from_u128(i: u128) -> Self {
+ Scalar::Int(i.into())
+ }
+
+ #[inline]
pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
Self::from_uint(i, cx.data_layout().pointer_size)
}
@@ -375,7 +384,8 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
#[inline(always)]
#[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
pub fn assert_bits(self, target_size: Size) -> u128 {
- self.to_bits(target_size).unwrap()
+ self.to_bits(target_size)
+ .unwrap_or_else(|_| panic!("assertion failed: {self:?} fits {target_size:?}"))
}
pub fn to_bool(self) -> InterpResult<'tcx, bool> {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 5c71910a9..28c505878 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -3,7 +3,7 @@
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
use crate::mir::interpret::{
- AllocRange, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, LitToConstInput, Scalar,
+ AllocRange, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
};
use crate::mir::visit::MirVisitable;
use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -15,7 +15,7 @@ use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
use rustc_data_structures::captures::Captures;
-use rustc_errors::ErrorGuaranteed;
+use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg};
use rustc_hir::def::{CtorKind, Namespace};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::{self, GeneratorKind, ImplicitSelfKind};
@@ -145,7 +145,7 @@ impl MirPhase {
}
"analysis" => Self::Analysis(AnalysisPhase::parse(phase)),
"runtime" => Self::Runtime(RuntimePhase::parse(phase)),
- _ => panic!("Unknown MIR dialect {}", dialect),
+ _ => bug!("Unknown MIR dialect: '{}'", dialect),
}
}
}
@@ -159,7 +159,7 @@ impl AnalysisPhase {
match &*phase.to_ascii_lowercase() {
"initial" => Self::Initial,
"post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
- _ => panic!("Unknown analysis phase {}", phase),
+ _ => bug!("Unknown analysis phase: '{}'", phase),
}
}
}
@@ -174,7 +174,7 @@ impl RuntimePhase {
"initial" => Self::Initial,
"post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
"optimized" => Self::Optimized,
- _ => panic!("Unknown runtime phase {}", phase),
+ _ => bug!("Unknown runtime phase: '{}'", phase),
}
}
}
@@ -476,7 +476,7 @@ impl<'tcx> Body<'tcx> {
/// Returns the return type; it always return first element from `local_decls` array.
#[inline]
pub fn bound_return_ty(&self) -> ty::EarlyBinder<Ty<'tcx>> {
- ty::EarlyBinder(self.local_decls[RETURN_PLACE].ty)
+ ty::EarlyBinder::bind(self.local_decls[RETURN_PLACE].ty)
}
/// Gets the location of the terminator for the given block.
@@ -1371,55 +1371,61 @@ impl<O> AssertKind<O> {
_ => write!(f, "\"{}\"", self.description()),
}
}
-}
-impl<O: fmt::Debug> fmt::Debug for AssertKind<O> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ pub fn diagnostic_message(&self) -> DiagnosticMessage {
+ use crate::fluent_generated::*;
use AssertKind::*;
+
match self {
- BoundsCheck { ref len, ref index } => write!(
- f,
- "index out of bounds: the length is {:?} but the index is {:?}",
- len, index
- ),
- OverflowNeg(op) => write!(f, "attempt to negate `{:#?}`, which would overflow", op),
- DivisionByZero(op) => write!(f, "attempt to divide `{:#?}` by zero", op),
- RemainderByZero(op) => write!(
- f,
- "attempt to calculate the remainder of `{:#?}` with a divisor of zero",
- op
- ),
- Overflow(BinOp::Add, l, r) => {
- write!(f, "attempt to compute `{:#?} + {:#?}`, which would overflow", l, r)
- }
- Overflow(BinOp::Sub, l, r) => {
- write!(f, "attempt to compute `{:#?} - {:#?}`, which would overflow", l, r)
- }
- Overflow(BinOp::Mul, l, r) => {
- write!(f, "attempt to compute `{:#?} * {:#?}`, which would overflow", l, r)
- }
- Overflow(BinOp::Div, l, r) => {
- write!(f, "attempt to compute `{:#?} / {:#?}`, which would overflow", l, r)
+ BoundsCheck { .. } => middle_bounds_check,
+ Overflow(BinOp::Shl, _, _) => middle_assert_shl_overflow,
+ Overflow(BinOp::Shr, _, _) => middle_assert_shr_overflow,
+ Overflow(_, _, _) => middle_assert_op_overflow,
+ OverflowNeg(_) => middle_assert_overflow_neg,
+ DivisionByZero(_) => middle_assert_divide_by_zero,
+ RemainderByZero(_) => middle_assert_remainder_by_zero,
+ ResumedAfterReturn(GeneratorKind::Async(_)) => middle_assert_async_resume_after_return,
+ ResumedAfterReturn(GeneratorKind::Gen) => middle_assert_generator_resume_after_return,
+ ResumedAfterPanic(GeneratorKind::Async(_)) => middle_assert_async_resume_after_panic,
+ ResumedAfterPanic(GeneratorKind::Gen) => middle_assert_generator_resume_after_panic,
+
+ MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref,
+ }
+ }
+
+ pub fn add_args(self, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>))
+ where
+ O: fmt::Debug,
+ {
+ use AssertKind::*;
+
+ macro_rules! add {
+ ($name: expr, $value: expr) => {
+ adder($name.into(), $value.into_diagnostic_arg());
+ };
+ }
+
+ match self {
+ BoundsCheck { len, index } => {
+ add!("len", format!("{len:?}"));
+ add!("index", format!("{index:?}"));
}
- Overflow(BinOp::Rem, l, r) => write!(
- f,
- "attempt to compute the remainder of `{:#?} % {:#?}`, which would overflow",
- l, r
- ),
- Overflow(BinOp::Shr, _, r) => {
- write!(f, "attempt to shift right by `{:#?}`, which would overflow", r)
+ Overflow(BinOp::Shl | BinOp::Shr, _, val)
+ | DivisionByZero(val)
+ | RemainderByZero(val)
+ | OverflowNeg(val) => {
+ add!("val", format!("{val:#?}"));
}
- Overflow(BinOp::Shl, _, r) => {
- write!(f, "attempt to shift left by `{:#?}`, which would overflow", r)
+ Overflow(binop, left, right) => {
+ add!("op", binop.to_hir_binop().as_str());
+ add!("left", format!("{left:#?}"));
+ add!("right", format!("{right:#?}"));
}
+ ResumedAfterReturn(_) | ResumedAfterPanic(_) => {}
MisalignedPointerDereference { required, found } => {
- write!(
- f,
- "misaligned pointer dereference: address must be a multiple of {:?} but is {:?}",
- required, found
- )
+ add!("required", format!("{required:#?}"));
+ add!("found", format!("{found:#?}"));
}
- _ => write!(f, "{}", self.description()),
}
}
}
@@ -1907,7 +1913,7 @@ impl<'tcx> Operand<'tcx> {
substs: impl IntoIterator<Item = GenericArg<'tcx>>,
span: Span,
) -> Self {
- let ty = tcx.mk_fn_def(def_id, substs);
+ let ty = Ty::new_fn_def(tcx, def_id, substs);
Operand::Constant(Box::new(Constant {
span,
user_ty: None,
@@ -2008,7 +2014,7 @@ impl<'tcx> Rvalue<'tcx> {
| CastKind::IntToFloat
| CastKind::FnPtrToPtr
| CastKind::PtrToPtr
- | CastKind::Pointer(_)
+ | CastKind::PointerCoercion(_)
| CastKind::PointerFromExposedAddress
| CastKind::DynStar
| CastKind::Transmute,
@@ -2029,23 +2035,19 @@ impl<'tcx> Rvalue<'tcx> {
impl BorrowKind {
pub fn mutability(&self) -> Mutability {
match *self {
- BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => Mutability::Not,
+ BorrowKind::Shared | BorrowKind::Shallow => Mutability::Not,
BorrowKind::Mut { .. } => Mutability::Mut,
}
}
pub fn allows_two_phase_borrow(&self) -> bool {
match *self {
- BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false,
- BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow,
- }
- }
-
- // FIXME: won't be used after diagnostic migration
- pub fn describe_mutability(&self) -> &str {
- match *self {
- BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => "immutable",
- BorrowKind::Mut { .. } => "mutable",
+ BorrowKind::Shared
+ | BorrowKind::Shallow
+ | BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::ClosureCapture } => {
+ false
+ }
+ BorrowKind::Mut { kind: MutBorrowKind::TwoPhaseBorrow } => true,
}
}
}
@@ -2084,7 +2086,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
let kind_str = match borrow_kind {
BorrowKind::Shared => "",
BorrowKind::Shallow => "shallow ",
- BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ",
+ BorrowKind::Mut { .. } => "mut ",
};
// When printing regions, add trailing space if necessary.
@@ -2327,10 +2329,10 @@ impl<'tcx> ConstantKind<'tcx> {
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
match self {
Self::Ty(c) => {
- if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) {
+ if let Some(val) = c.try_eval_for_mir(tcx, param_env) {
match val {
Ok(val) => Self::Val(val, c.ty()),
- Err(guar) => Self::Ty(tcx.const_error(self.ty(), guar)),
+ Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())),
}
} else {
self
@@ -2342,7 +2344,9 @@ impl<'tcx> ConstantKind<'tcx> {
match tcx.const_eval_resolve(param_env, uneval, None) {
Ok(val) => Self::Val(val, ty),
Err(ErrorHandled::TooGeneric) => self,
- Err(ErrorHandled::Reported(guar)) => Self::Ty(tcx.const_error(ty, guar.into())),
+ Err(ErrorHandled::Reported(guar)) => {
+ Self::Ty(ty::Const::new_error(tcx, guar.into(), ty))
+ }
}
}
}
@@ -2461,51 +2465,6 @@ impl<'tcx> ConstantKind<'tcx> {
Self::Val(val, ty)
}
- #[instrument(skip(tcx), level = "debug", ret)]
- pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let body_id = match tcx.hir().get(hir_id) {
- hir::Node::AnonConst(ac) => ac.body,
- _ => span_bug!(
- tcx.def_span(def_id.to_def_id()),
- "from_inline_const can only process anonymous constants"
- ),
- };
- let expr = &tcx.hir().body(body_id).value;
- let ty = tcx.typeck(def_id).node_type(hir_id);
-
- let lit_input = match expr.kind {
- hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
- hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
- hir::ExprKind::Lit(ref lit) => {
- Some(LitToConstInput { lit: &lit.node, ty, neg: true })
- }
- _ => None,
- },
- _ => None,
- };
- if let Some(lit_input) = lit_input {
- // If an error occurred, ignore that it's a literal and leave reporting the error up to
- // mir.
- match tcx.at(expr.span).lit_to_mir_constant(lit_input) {
- Ok(c) => return c,
- Err(_) => {}
- }
- }
-
- let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
- let parent_substs =
- tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
- let substs =
- ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
- .substs;
-
- let uneval = UnevaluatedConst { def: def_id.to_def_id(), substs, promoted: None };
- debug_assert!(!uneval.has_free_regions());
-
- Self::Unevaluated(uneval, ty)
- }
-
/// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
/// converted to a constant, everything else becomes `Unevaluated`.
#[instrument(skip(tcx), level = "debug", ret)]
@@ -2553,7 +2512,7 @@ impl<'tcx> ConstantKind<'tcx> {
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
let name = tcx.item_name(def_id);
- let ty_const = tcx.mk_const(ty::ParamConst::new(index, name), ty);
+ let ty_const = ty::Const::new_param(tcx, ty::ParamConst::new(index, name), ty);
debug!(?ty_const);
return Self::Ty(ty_const);
@@ -2624,10 +2583,9 @@ pub struct UnevaluatedConst<'tcx> {
}
impl<'tcx> UnevaluatedConst<'tcx> {
- // FIXME: probably should get rid of this method. It's also wrong to
- // shrink and then later expand a promoted.
#[inline]
pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> {
+ assert_eq!(self.promoted, None);
ty::UnevaluatedConst { def: self.def, substs: self.substs }
}
}
@@ -2818,7 +2776,7 @@ impl<'tcx> Display for ConstantKind<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
match *self {
ConstantKind::Ty(c) => pretty_print_const(c, fmt, true),
- ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true),
+ ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt),
// FIXME(valtrees): Correctly print mir constants.
ConstantKind::Unevaluated(..) => {
fmt.write_str("_")?;
@@ -2848,13 +2806,16 @@ fn pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Resul
write!(fmt, "b\"{}\"", byte_str.escape_ascii())
}
-fn comma_sep<'tcx>(fmt: &mut Formatter<'_>, elems: Vec<ConstantKind<'tcx>>) -> fmt::Result {
+fn comma_sep<'tcx>(
+ fmt: &mut Formatter<'_>,
+ elems: Vec<(ConstValue<'tcx>, Ty<'tcx>)>,
+) -> fmt::Result {
let mut first = true;
- for elem in elems {
+ for (ct, ty) in elems {
if !first {
fmt.write_str(", ")?;
}
- fmt.write_str(&format!("{}", elem))?;
+ pretty_print_const_value(ct, ty, fmt)?;
first = false;
}
Ok(())
@@ -2865,7 +2826,6 @@ fn pretty_print_const_value<'tcx>(
ct: ConstValue<'tcx>,
ty: Ty<'tcx>,
fmt: &mut Formatter<'_>,
- print_ty: bool,
) -> fmt::Result {
use crate::ty::print::PrettyPrinter;
@@ -2909,7 +2869,7 @@ fn pretty_print_const_value<'tcx>(
}
}
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
- let n = n.kind().try_to_bits(tcx.data_layout.pointer_size).unwrap();
+ let n = n.try_to_bits(tcx.data_layout.pointer_size).unwrap();
// cast is ok because we already checked for pointer size (32 or 64 bit) above
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();
@@ -2924,16 +2884,11 @@ fn pretty_print_const_value<'tcx>(
// 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)`
- //
- // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
- // correct `ty::ParamEnv` to allow printing *all* constant values.
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => {
let ct = tcx.lift(ct).unwrap();
let ty = tcx.lift(ty).unwrap();
- if let Some(contents) = tcx.try_destructure_mir_constant(
- ty::ParamEnv::reveal_all().and(ConstantKind::Val(ct, ty)),
- ) {
- let fields = contents.fields.to_vec();
+ if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics((ct, ty)) {
+ let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec();
match *ty.kind() {
ty::Array(..) => {
fmt.write_str("[")?;
@@ -2972,12 +2927,14 @@ fn pretty_print_const_value<'tcx>(
None => {
fmt.write_str(" {{ ")?;
let mut first = true;
- for (field_def, field) in iter::zip(&variant_def.fields, fields)
+ for (field_def, (ct, ty)) in
+ iter::zip(&variant_def.fields, fields)
{
if !first {
fmt.write_str(", ")?;
}
- fmt.write_str(&format!("{}: {}", field_def.name, field))?;
+ write!(fmt, "{}: ", field_def.name)?;
+ pretty_print_const_value(ct, ty, fmt)?;
first = false;
}
fmt.write_str(" }}")?;
@@ -2987,20 +2944,13 @@ fn pretty_print_const_value<'tcx>(
_ => unreachable!(),
}
return Ok(());
- } else {
- // Fall back to debug pretty printing for invalid constants.
- fmt.write_str(&format!("{:?}", ct))?;
- if print_ty {
- fmt.write_str(&format!(": {}", ty))?;
- }
- return Ok(());
- };
+ }
}
(ConstValue::Scalar(scalar), _) => {
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
cx.print_alloc_ids = true;
let ty = tcx.lift(ty).unwrap();
- cx = cx.pretty_print_const_scalar(scalar, ty, print_ty)?;
+ cx = cx.pretty_print_const_scalar(scalar, ty)?;
fmt.write_str(&cx.into_buffer())?;
return Ok(());
}
@@ -3015,12 +2965,8 @@ fn pretty_print_const_value<'tcx>(
// their fields instead of just dumping the memory.
_ => {}
}
- // fallback
- fmt.write_str(&format!("{:?}", ct))?;
- if print_ty {
- fmt.write_str(&format!(": {}", ty))?;
- }
- Ok(())
+ // Fall back to debug pretty printing for invalid constants.
+ write!(fmt, "{ct:?}: {ty}")
})
}
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index f31b343c9..ca735d523 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -231,7 +231,7 @@ pub struct CodegenUnit<'tcx> {
/// as well as the crate name and disambiguator.
name: Symbol,
items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>,
- size_estimate: Option<usize>,
+ size_estimate: usize,
primary: bool,
/// True if this is CGU is used to hold code coverage information for dead code,
/// false otherwise.
@@ -269,7 +269,7 @@ impl<'tcx> CodegenUnit<'tcx> {
CodegenUnit {
name,
items: Default::default(),
- size_estimate: None,
+ size_estimate: 0,
primary: false,
is_code_coverage_dead_code_cgu: false,
}
@@ -291,10 +291,12 @@ impl<'tcx> CodegenUnit<'tcx> {
self.primary = true;
}
+ /// The order of these items is non-determinstic.
pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
&self.items
}
+ /// The order of these items is non-determinstic.
pub fn items_mut(&mut self) -> &mut FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
&mut self.items
}
@@ -318,23 +320,21 @@ impl<'tcx> CodegenUnit<'tcx> {
base_n::encode(hash, base_n::CASE_INSENSITIVE)
}
- pub fn create_size_estimate(&mut self, tcx: TyCtxt<'tcx>) {
+ pub fn compute_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());
+ self.size_estimate = self.items.keys().map(|mi| mi.size_estimate(tcx)).sum();
}
#[inline]
- /// Should only be called if [`create_size_estimate`] has previously been called.
+ /// Should only be called if [`compute_size_estimate`] has previously been called.
///
- /// [`create_size_estimate`]: Self::create_size_estimate
+ /// [`compute_size_estimate`]: Self::compute_size_estimate
pub fn size_estimate(&self) -> usize {
+ // Items are never zero-sized, so if we have items the estimate must be
+ // non-zero, unless we forgot to call `compute_size_estimate` first.
+ assert!(self.items.is_empty() || self.size_estimate != 0);
self.size_estimate
- .expect("create_size_estimate must be called before getting a size_estimate")
- }
-
- pub fn modify_size_estimate(&mut self, delta: usize) {
- *self.size_estimate.as_mut().unwrap() += delta;
}
pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool {
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 62c3d8cf2..ffa7a5400 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -353,14 +353,22 @@ where
for statement in &data.statements {
extra_data(PassWhere::BeforeLocation(current_location), w)?;
let indented_body = format!("{0}{0}{1:?};", INDENT, statement);
- writeln!(
- w,
- "{:A$} // {}{}",
- indented_body,
- if tcx.sess.verbose() { format!("{:?}: ", current_location) } else { String::new() },
- comment(tcx, statement.source_info, body.span),
- A = ALIGN,
- )?;
+ if tcx.sess.opts.unstable_opts.mir_include_spans {
+ writeln!(
+ w,
+ "{:A$} // {}{}",
+ indented_body,
+ if tcx.sess.verbose() {
+ format!("{:?}: ", current_location)
+ } else {
+ String::new()
+ },
+ comment(tcx, statement.source_info),
+ A = ALIGN,
+ )?;
+ } else {
+ writeln!(w, "{}", indented_body)?;
+ }
write_extra(tcx, w, |visitor| {
visitor.visit_statement(statement, current_location);
@@ -374,14 +382,18 @@ where
// Terminator at the bottom.
extra_data(PassWhere::BeforeLocation(current_location), w)?;
let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind);
- writeln!(
- w,
- "{:A$} // {}{}",
- indented_terminator,
- if tcx.sess.verbose() { format!("{:?}: ", current_location) } else { String::new() },
- comment(tcx, data.terminator().source_info, body.span),
- A = ALIGN,
- )?;
+ if tcx.sess.opts.unstable_opts.mir_include_spans {
+ writeln!(
+ w,
+ "{:A$} // {}{}",
+ indented_terminator,
+ if tcx.sess.verbose() { format!("{:?}: ", current_location) } else { String::new() },
+ comment(tcx, data.terminator().source_info),
+ A = ALIGN,
+ )?;
+ } else {
+ writeln!(w, "{}", indented_terminator)?;
+ }
write_extra(tcx, w, |visitor| {
visitor.visit_terminator(data.terminator(), current_location);
@@ -400,10 +412,12 @@ fn write_extra<'tcx, F>(tcx: TyCtxt<'tcx>, write: &mut dyn Write, mut visit_op:
where
F: FnMut(&mut ExtraComments<'tcx>),
{
- let mut extra_comments = ExtraComments { tcx, comments: vec![] };
- visit_op(&mut extra_comments);
- for comment in extra_comments.comments {
- writeln!(write, "{:A$} // {}", "", comment, A = ALIGN)?;
+ if tcx.sess.opts.unstable_opts.mir_include_spans {
+ let mut extra_comments = ExtraComments { tcx, comments: vec![] };
+ visit_op(&mut extra_comments);
+ for comment in extra_comments.comments {
+ writeln!(write, "{:A$} // {}", "", comment, A = ALIGN)?;
+ }
}
Ok(())
}
@@ -522,13 +536,8 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
}
}
-fn comment(tcx: TyCtxt<'_>, SourceInfo { span, scope }: SourceInfo, function_span: Span) -> String {
- let location = if tcx.sess.opts.unstable_opts.mir_pretty_relative_line_numbers {
- tcx.sess.source_map().span_to_relative_line_string(span, function_span)
- } else {
- tcx.sess.source_map().span_to_embeddable_string(span)
- };
-
+fn comment(tcx: TyCtxt<'_>, SourceInfo { span, scope }: SourceInfo) -> String {
+ let location = tcx.sess.source_map().span_to_embeddable_string(span);
format!("scope {} at {}", scope.index(), location,)
}
@@ -560,13 +569,17 @@ fn write_scope_tree(
var_debug_info.value,
);
- writeln!(
- w,
- "{0:1$} // in {2}",
- indented_debug_info,
- ALIGN,
- comment(tcx, var_debug_info.source_info, body.span),
- )?;
+ if tcx.sess.opts.unstable_opts.mir_include_spans {
+ writeln!(
+ w,
+ "{0:1$} // in {2}",
+ indented_debug_info,
+ ALIGN,
+ comment(tcx, var_debug_info.source_info),
+ )?;
+ } else {
+ writeln!(w, "{}", indented_debug_info)?;
+ }
}
// Local variable types.
@@ -594,14 +607,18 @@ fn write_scope_tree(
let local_name = if local == RETURN_PLACE { " return place" } else { "" };
- writeln!(
- w,
- "{0:1$} //{2} in {3}",
- indented_decl,
- ALIGN,
- local_name,
- comment(tcx, local_decl.source_info, body.span),
- )?;
+ if tcx.sess.opts.unstable_opts.mir_include_spans {
+ writeln!(
+ w,
+ "{0:1$} //{2} in {3}",
+ indented_decl,
+ ALIGN,
+ local_name,
+ comment(tcx, local_decl.source_info),
+ )?;
+ } else {
+ writeln!(w, "{}", indented_decl,)?;
+ }
}
let Some(children) = scope_tree.get(&parent) else {
@@ -627,14 +644,18 @@ fn write_scope_tree(
let indented_header = format!("{0:1$}scope {2}{3} {{", "", indent, child.index(), special);
- if let Some(span) = span {
- writeln!(
- w,
- "{0:1$} // at {2}",
- indented_header,
- ALIGN,
- tcx.sess.source_map().span_to_embeddable_string(span),
- )?;
+ if tcx.sess.opts.unstable_opts.mir_include_spans {
+ if let Some(span) = span {
+ writeln!(
+ w,
+ "{0:1$} // at {2}",
+ indented_header,
+ ALIGN,
+ tcx.sess.source_map().span_to_embeddable_string(span),
+ )?;
+ } else {
+ writeln!(w, "{}", indented_header)?;
+ }
} else {
writeln!(w, "{}", indented_header)?;
}
@@ -846,7 +867,7 @@ 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, Bytes: AllocBytes>(
+pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
tcx: TyCtxt<'tcx>,
alloc: &Allocation<Prov, Extra, Bytes>,
w: &mut dyn std::fmt::Write,
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 53fd2dd23..613b132ff 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -1,6 +1,6 @@
//! Values computed by queries that use MIR.
-use crate::mir::ConstantKind;
+use crate::mir::interpret::ConstValue;
use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::unord::UnordSet;
@@ -9,6 +9,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::BitMatrix;
use rustc_index::{Idx, IndexVec};
+use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx};
use smallvec::SmallVec;
@@ -150,6 +151,9 @@ pub struct GeneratorLayout<'tcx> {
/// The type of every local stored inside the generator.
pub field_tys: IndexVec<GeneratorSavedLocal, GeneratorSavedTy<'tcx>>,
+ /// The name for debuginfo.
+ pub field_names: IndexVec<GeneratorSavedLocal, Option<Symbol>>,
+
/// Which of the above fields are in each variant. Note that one field may
/// be stored in multiple variants.
pub variant_fields: IndexVec<VariantIdx, IndexVec<FieldIdx, GeneratorSavedLocal>>,
@@ -413,7 +417,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
ty::ReVar(vid) => {
let br =
ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon(None) };
- tcx.mk_re_late_bound(depth, br)
+ ty::Region::new_late_bound(tcx, depth, br)
}
_ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
});
@@ -440,7 +444,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
#[derive(Copy, Clone, Debug, HashStable)]
pub struct DestructuredConstant<'tcx> {
pub variant: Option<VariantIdx>,
- pub fields: &'tcx [ConstantKind<'tcx>],
+ pub fields: &'tcx [(ConstValue<'tcx>, Ty<'tcx>)],
}
/// Coverage information summarized from a MIR if instrumented for source code coverage (see
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 2165403da..730c55157 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -3,7 +3,7 @@ use rustc_middle::hir;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::MirSpanview;
-use rustc_span::{BytePos, Pos, Span, SyntaxContext};
+use rustc_span::{BytePos, Pos, Span};
use std::cmp;
use std::io::{self, Write};
@@ -15,8 +15,9 @@ const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT B
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>
-<html>
-<head>"#;
+<html lang="en">
+<head>
+<meta charset="utf-8">"#;
const START_BODY: &str = r#"</head>
<body>"#;
const FOOTER: &str = r#"</body>
@@ -327,7 +328,7 @@ fn compute_block_span(data: &BasicBlockData<'_>, body_span: Span) -> Span {
let mut span = data.terminator().source_info.span;
for statement_span in data.statements.iter().map(|statement| statement.source_info.span) {
// Only combine Spans from the root context, and within the function's body_span.
- if statement_span.ctxt() == SyntaxContext::root() && body_span.contains(statement_span) {
+ if statement_span.ctxt().is_root() && body_span.contains(statement_span) {
span = span.to(statement_span);
}
}
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 3e474c1d3..7f1d38203 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -7,7 +7,7 @@ use super::{BasicBlock, Constant, Local, SwitchTargets, UserTypeProjection};
use crate::mir::coverage::{CodeRegion, CoverageKind};
use crate::traits::Reveal;
-use crate::ty::adjustment::PointerCast;
+use crate::ty::adjustment::PointerCoercion;
use crate::ty::subst::SubstsRef;
use crate::ty::{self, List, Ty};
use crate::ty::{Region, UserTypeAnnotationIndex};
@@ -182,6 +182,16 @@ pub enum BorrowKind {
/// We can also report errors with this kind of borrow differently.
Shallow,
+ /// Data is mutable and not aliasable.
+ Mut { kind: MutBorrowKind },
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
+#[derive(Hash, HashStable)]
+pub enum MutBorrowKind {
+ Default,
+ /// This borrow arose from method-call auto-ref. (i.e., `adjustment::Adjust::Borrow`)
+ TwoPhaseBorrow,
/// Data must be immutable but not aliasable. This kind of borrow
/// cannot currently be expressed by the user and is used only in
/// implicit closure bindings. It is needed when the closure is
@@ -216,23 +226,14 @@ pub enum BorrowKind {
/// user code, if awkward, but extra weird for closures, since the
/// borrow is hidden.
///
- /// So we introduce a "unique imm" borrow -- the referent is
- /// immutable, but not aliasable. This solves the problem. For
- /// simplicity, we don't give users the way to express this
- /// borrow, it's just used when translating closures.
+ /// So we introduce a `ClosureCapture` borrow -- user will not have to mark the variable
+ /// containing the mutable reference as `mut`, as they didn't ever
+ /// intend to mutate the mutable reference itself. We still mutable capture it in order to
+ /// mutate the pointed value through it (but not mutating the reference itself).
///
- // FIXME(#112072): This is wrong. Unique borrows are mutable borrows except
- // that they do not require their pointee to be marked as a mutable.
- // They should still be treated as mutable borrows in every other way,
- // e.g. for variance or overlap checking.
- Unique,
-
- /// Data is mutable and not aliasable.
- Mut {
- /// `true` if this borrow arose from method-call auto-ref
- /// (i.e., `adjustment::Adjust::Borrow`).
- allow_two_phase_borrow: bool,
- },
+ /// This solves the problem. For simplicity, we don't give users the way to express this
+ /// borrow, it's just used when translating closures.
+ ClosureCapture,
}
///////////////////////////////////////////////////////////////////////////
@@ -512,6 +513,31 @@ pub struct CopyNonOverlapping<'tcx> {
pub count: Operand<'tcx>,
}
+/// Represents how a `TerminatorKind::Call` was constructed, used for diagnostics
+#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, Hash, HashStable)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub enum CallSource {
+ /// This came from something such as `a > b` or `a + b`. In THIR, if `from_hir_call`
+ /// is false then this is the desugaring.
+ OverloadedOperator,
+ /// This was from comparison generated by a match, used by const-eval for better errors
+ /// when the comparison cannot be done in compile time.
+ ///
+ /// (see <https://github.com/rust-lang/rust/issues/90237>)
+ MatchCmp,
+ /// Other types of desugaring that did not come from the HIR, but we don't care about
+ /// for diagnostics (yet).
+ Misc,
+ /// Normal function call, no special source
+ Normal,
+}
+
+impl CallSource {
+ pub fn from_hir_call(self) -> bool {
+ matches!(self, CallSource::Normal)
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
// Terminators
@@ -638,11 +664,10 @@ pub enum TerminatorKind<'tcx> {
target: Option<BasicBlock>,
/// Action to be taken if the call unwinds.
unwind: UnwindAction,
- /// `true` if this is from a call in HIR rather than from an overloaded
- /// operator. True for overloaded function call.
- from_hir_call: bool,
+ /// Where this call came from in HIR/THIR.
+ call_source: CallSource,
/// This `Span` is the span of the function, without the dot and receiver
- /// (e.g. `foo(a, b)` in `x.foo(a, b)`
+ /// e.g. `foo(a, b)` in `x.foo(a, b)`
fn_span: Span,
},
@@ -801,7 +826,8 @@ pub enum UnwindAction {
}
/// Information about an assertion failure.
-#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
+#[derive(Clone, Hash, HashStable, PartialEq, Debug)]
+#[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
pub enum AssertKind<O> {
BoundsCheck { len: O, index: O },
Overflow(BinOp, O, O),
@@ -1204,9 +1230,9 @@ pub enum CastKind {
/// An address-to-pointer cast that picks up an exposed provenance.
/// See the docs on `from_exposed_addr` for more details.
PointerFromExposedAddress,
- /// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are
+ /// Pointer related casts that are done by coercions. Note that reference-to-raw-ptr casts are
/// translated into `&raw mut/const *r`, i.e., they are not actually casts.
- Pointer(PointerCast),
+ PointerCoercion(PointerCoercion),
/// Cast into a dyn* object.
DynStar,
IntToInt,
@@ -1266,19 +1292,30 @@ pub enum UnOp {
pub enum BinOp {
/// The `+` operator (addition)
Add,
+ /// Like `Add`, but with UB on overflow. (Integers only.)
+ AddUnchecked,
/// The `-` operator (subtraction)
Sub,
+ /// Like `Sub`, but with UB on overflow. (Integers only.)
+ SubUnchecked,
/// The `*` operator (multiplication)
Mul,
+ /// Like `Mul`, but with UB on overflow. (Integers only.)
+ MulUnchecked,
/// The `/` operator (division)
///
- /// Division by zero is UB, because the compiler should have inserted checks
- /// prior to this.
+ /// For integer types, division by zero is UB, as is `MIN / -1` for signed.
+ /// The compiler should have inserted checks prior to this.
+ ///
+ /// Floating-point division by zero is safe, and does not need guards.
Div,
/// The `%` operator (modulus)
///
- /// Using zero as the modulus (second operand) is UB, because the compiler
- /// should have inserted checks prior to this.
+ /// For integer types, using zero as the modulus (second operand) is UB,
+ /// as is `MIN % -1` for signed.
+ /// The compiler should have inserted checks prior to this.
+ ///
+ /// Floating-point remainder by zero is safe, and does not need guards.
Rem,
/// The `^` operator (bitwise xor)
BitXor,
@@ -1290,10 +1327,17 @@ pub enum BinOp {
///
/// The offset is truncated to the size of the first operand before shifting.
Shl,
+ /// Like `Shl`, but is UB if the RHS >= LHS::BITS
+ ShlUnchecked,
/// The `>>` operator (shift right)
///
/// The offset is truncated to the size of the first operand before shifting.
+ ///
+ /// This is an arithmetic shift if the LHS is signed
+ /// and a logical shift if the LHS is unsigned.
Shr,
+ /// Like `Shl`, but is UB if the RHS >= LHS::BITS
+ ShrUnchecked,
/// The `==` operator (equality)
Eq,
/// The `<` operator (less than)
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 5ca824134..8618a5315 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -95,11 +95,13 @@ impl<'tcx> PlaceTy<'tcx> {
ProjectionElem::Subslice { from, to, from_end } => {
PlaceTy::from_ty(match self.ty.kind() {
ty::Slice(..) => self.ty,
- ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64),
+ ty::Array(inner, _) if !from_end => {
+ Ty::new_array(tcx, *inner, (to - from) as u64)
+ }
ty::Array(inner, size) if from_end => {
let size = size.eval_target_usize(tcx, param_env);
let len = size - from - to;
- tcx.mk_array(*inner, len)
+ Ty::new_array(tcx, *inner, len)
}
_ => bug!("cannot subslice non-array type: `{:?}`", self),
})
@@ -162,16 +164,16 @@ impl<'tcx> Rvalue<'tcx> {
match *self {
Rvalue::Use(ref operand) => operand.ty(local_decls, tcx),
Rvalue::Repeat(ref operand, count) => {
- tcx.mk_array_with_const_len(operand.ty(local_decls, tcx), count)
+ Ty::new_array_with_const_len(tcx, operand.ty(local_decls, tcx), count)
}
Rvalue::ThreadLocalRef(did) => tcx.thread_local_ptr_ty(did),
Rvalue::Ref(reg, bk, ref place) => {
let place_ty = place.ty(local_decls, tcx).ty;
- tcx.mk_ref(reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() })
+ Ty::new_ref(tcx, reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() })
}
Rvalue::AddressOf(mutability, ref place) => {
let place_ty = place.ty(local_decls, tcx).ty;
- tcx.mk_ptr(ty::TypeAndMut { ty: place_ty, mutbl: mutability })
+ Ty::new_ptr(tcx, ty::TypeAndMut { ty: place_ty, mutbl: mutability })
}
Rvalue::Len(..) => tcx.types.usize,
Rvalue::Cast(.., ty) => ty,
@@ -184,7 +186,7 @@ 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.mk_tup(&[ty, tcx.types.bool])
+ Ty::new_tup(tcx, &[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),
@@ -192,17 +194,17 @@ impl<'tcx> Rvalue<'tcx> {
tcx.types.usize
}
Rvalue::Aggregate(ref ak, ref ops) => match **ak {
- AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64),
+ AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64),
AggregateKind::Tuple => {
- tcx.mk_tup_from_iter(ops.iter().map(|op| op.ty(local_decls, tcx)))
+ Ty::new_tup_from_iter(tcx, ops.iter().map(|op| op.ty(local_decls, tcx)))
}
AggregateKind::Adt(did, _, substs, _, _) => tcx.type_of(did).subst(tcx, substs),
- AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs),
+ AggregateKind::Closure(did, substs) => Ty::new_closure(tcx, did, substs),
AggregateKind::Generator(did, substs, movability) => {
- tcx.mk_generator(did, substs, movability)
+ Ty::new_generator(tcx, did, substs, movability)
}
},
- Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty),
+ Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty),
Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty,
}
}
@@ -235,8 +237,11 @@ impl<'tcx> BinOp {
// FIXME: handle SIMD correctly
match self {
&BinOp::Add
+ | &BinOp::AddUnchecked
| &BinOp::Sub
+ | &BinOp::SubUnchecked
| &BinOp::Mul
+ | &BinOp::MulUnchecked
| &BinOp::Div
| &BinOp::Rem
| &BinOp::BitXor
@@ -246,7 +251,11 @@ impl<'tcx> BinOp {
assert_eq!(lhs_ty, rhs_ty);
lhs_ty
}
- &BinOp::Shl | &BinOp::Shr | &BinOp::Offset => {
+ &BinOp::Shl
+ | &BinOp::ShlUnchecked
+ | &BinOp::Shr
+ | &BinOp::ShrUnchecked
+ | &BinOp::Offset => {
lhs_ty // lhs_ty can be != rhs_ty
}
&BinOp::Eq | &BinOp::Lt | &BinOp::Le | &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
@@ -262,11 +271,6 @@ impl BorrowKind {
BorrowKind::Mut { .. } => hir::Mutability::Mut,
BorrowKind::Shared => hir::Mutability::Not,
- // We have no type corresponding to a unique imm borrow, so
- // use `&mut`. It gives all the capabilities of a `&uniq`
- // and hence is a safe "over approximation".
- BorrowKind::Unique => hir::Mutability::Mut,
-
// We have no type corresponding to a shallow borrow, so use
// `&` as an approximation.
BorrowKind::Shallow => hir::Mutability::Not,
@@ -293,7 +297,14 @@ impl BinOp {
BinOp::Gt => hir::BinOpKind::Gt,
BinOp::Le => hir::BinOpKind::Le,
BinOp::Ge => hir::BinOpKind::Ge,
- BinOp::Offset => unreachable!(),
+ BinOp::AddUnchecked
+ | BinOp::SubUnchecked
+ | BinOp::MulUnchecked
+ | BinOp::ShlUnchecked
+ | BinOp::ShrUnchecked
+ | BinOp::Offset => {
+ unreachable!()
+ }
}
}
}
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 2c6126cdd..1b9c1438f 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -105,7 +105,7 @@ pub struct Terminator<'tcx> {
pub kind: TerminatorKind<'tcx>,
}
-pub type Successors<'a> = impl Iterator<Item = BasicBlock> + 'a;
+pub type Successors<'a> = impl DoubleEndedIterator<Item = BasicBlock> + 'a;
pub type SuccessorsMut<'a> =
iter::Chain<std::option::IntoIter<&'a mut BasicBlock>, slice::IterMut<'a, BasicBlock>>;
@@ -272,7 +272,8 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
let unwind = match self.unwind() {
// Not needed or included in successors
- None | Some(UnwindAction::Continue) | Some(UnwindAction::Cleanup(_)) => None,
+ None | Some(UnwindAction::Cleanup(_)) => None,
+ Some(UnwindAction::Continue) => Some("unwind continue"),
Some(UnwindAction::Unreachable) => Some("unwind unreachable"),
Some(UnwindAction::Terminate) => Some("unwind terminate"),
};
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index 7d247eeb6..ec16a8470 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -149,7 +149,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
// B C
// | |
// | |
- // D |
+ // | D
// \ /
// \ /
// E
@@ -159,26 +159,26 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
//
// When the first call to `traverse_successor` happens, the following happens:
//
- // [(B, [D]), // `B` taken from the successors of `A`, pushed to the
- // // top of the stack along with the successors of `B`
- // (A, [C])]
+ // [(C, [D]), // `C` taken from the successors of `A`, pushed to the
+ // // top of the stack along with the successors of `C`
+ // (A, [B])]
//
- // [(D, [E]), // `D` taken from successors of `B`, pushed to stack
- // (B, []),
- // (A, [C])]
+ // [(D, [E]), // `D` taken from successors of `C`, pushed to stack
+ // (C, []),
+ // (A, [B])]
//
// [(E, []), // `E` taken from successors of `D`, pushed to stack
// (D, []),
- // (B, []),
- // (A, [C])]
+ // (C, []),
+ // (A, [B])]
//
// Now that the top of the stack has no successors we can traverse, each item will
- // be popped off during iteration until we get back to `A`. This yields [E, D, B].
+ // be popped off during iteration until we get back to `A`. This yields [E, D, C].
//
- // When we yield `B` and call `traverse_successor`, we push `C` to the stack, but
+ // When we yield `C` and call `traverse_successor`, we push `B` to the stack, but
// since we've already visited `E`, that child isn't added to the stack. The last
- // two iterations yield `C` and finally `A` for a final traversal of [E, D, B, C, A]
- while let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() && let Some(bb) = iter.next() {
+ // two iterations yield `B` and finally `A` for a final traversal of [E, D, C, B, A]
+ while let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() && let Some(bb) = iter.next_back() {
if self.visited.insert(bb) {
if let Some(term) = &self.basic_blocks[bb].terminator {
self.visit_stack.push((bb, term.successors()));
@@ -188,10 +188,6 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
}
}
-pub fn postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> Postorder<'a, 'tcx> {
- Postorder::new(&body.basic_blocks, START_BLOCK)
-}
-
impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
type Item = (BasicBlock, &'a BasicBlockData<'tcx>);
@@ -219,6 +215,17 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
}
}
+/// Creates an iterator over the `Body`'s basic blocks, that:
+/// - returns basic blocks in a postorder,
+/// - traverses the `BasicBlocks` CFG cache's reverse postorder backwards, and does not cache the
+/// postorder itself.
+pub fn postorder<'a, 'tcx>(
+ body: &'a Body<'tcx>,
+) -> impl Iterator<Item = (BasicBlock, &'a BasicBlockData<'tcx>)> + ExactSizeIterator + DoubleEndedIterator
+{
+ reverse_postorder(body).rev()
+}
+
/// Reverse postorder traversal of a graph
///
/// Reverse postorder is the reverse order of a postorder traversal.
@@ -295,34 +302,12 @@ pub fn reachable_as_bitset(body: &Body<'_>) -> BitSet<BasicBlock> {
iter.visited
}
-#[derive(Clone)]
-pub struct ReversePostorderIter<'a, 'tcx> {
+/// Creates an iterator over the `Body`'s basic blocks, that:
+/// - returns basic blocks in a reverse postorder,
+/// - makes use of the `BasicBlocks` CFG cache's reverse postorder.
+pub fn reverse_postorder<'a, 'tcx>(
body: &'a Body<'tcx>,
- blocks: &'a [BasicBlock],
- idx: usize,
-}
-
-impl<'a, 'tcx> Iterator for ReversePostorderIter<'a, 'tcx> {
- type Item = (BasicBlock, &'a BasicBlockData<'tcx>);
-
- fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> {
- if self.idx == 0 {
- return None;
- }
- self.idx -= 1;
-
- self.blocks.get(self.idx).map(|&bb| (bb, &self.body[bb]))
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.idx, Some(self.idx))
- }
-}
-
-impl<'a, 'tcx> ExactSizeIterator for ReversePostorderIter<'a, 'tcx> {}
-
-pub fn reverse_postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> ReversePostorderIter<'a, 'tcx> {
- let blocks = body.basic_blocks.postorder();
- let len = blocks.len();
- ReversePostorderIter { body, blocks, idx: len }
+) -> impl Iterator<Item = (BasicBlock, &'a BasicBlockData<'tcx>)> + ExactSizeIterator + DoubleEndedIterator
+{
+ body.basic_blocks.reverse_postorder().iter().map(|&bb| (bb, &body.basic_blocks[bb]))
}
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 8d44e929a..205dc9ec7 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -519,7 +519,7 @@ macro_rules! make_mir_visitor {
destination,
target: _,
unwind: _,
- from_hir_call: _,
+ call_source: _,
fn_span: _
} => {
self.visit_operand(func, location);
@@ -650,9 +650,6 @@ macro_rules! make_mir_visitor {
BorrowKind::Shallow => PlaceContext::NonMutatingUse(
NonMutatingUseContext::ShallowBorrow
),
- BorrowKind::Unique => PlaceContext::MutatingUse(
- MutatingUseContext::Borrow
- ),
BorrowKind::Mut { .. } =>
PlaceContext::MutatingUse(MutatingUseContext::Borrow),
};
@@ -1136,13 +1133,12 @@ macro_rules! visit_place_fns {
fn visit_projection_elem(
&mut self,
- local: Local,
- proj_base: &[PlaceElem<'tcx>],
+ place_ref: PlaceRef<'tcx>,
elem: PlaceElem<'tcx>,
context: PlaceContext,
location: Location,
) {
- self.super_projection_elem(local, proj_base, elem, context, location);
+ self.super_projection_elem(place_ref, elem, context, location);
}
fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
@@ -1171,15 +1167,13 @@ macro_rules! visit_place_fns {
location: Location,
) {
for (base, elem) in place_ref.iter_projections().rev() {
- let base_proj = base.projection;
- self.visit_projection_elem(place_ref.local, base_proj, elem, context, location);
+ self.visit_projection_elem(base, elem, context, location);
}
}
fn super_projection_elem(
&mut self,
- _local: Local,
- _proj_base: &[PlaceElem<'tcx>],
+ _place_ref: PlaceRef<'tcx>,
elem: PlaceElem<'tcx>,
_context: PlaceContext,
location: Location,
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index fd02a1613..2c481745d 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -55,6 +55,10 @@ impl<T> EraseType for &'_ ty::List<T> {
type Result = [u8; size_of::<*const ()>()];
}
+impl<I: rustc_index::Idx, T> EraseType for &'_ rustc_index::IndexSlice<I, T> {
+ type Result = [u8; size_of::<&'static rustc_index::IndexSlice<u32, ()>>()];
+}
+
impl<T> EraseType for Result<&'_ T, traits::query::NoSolution> {
type Result = [u8; size_of::<Result<&'static (), traits::query::NoSolution>>()];
}
@@ -67,8 +71,8 @@ impl<T> EraseType for Result<&'_ T, traits::CodegenObligationError> {
type Result = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()];
}
-impl<T> EraseType for Result<&'_ T, ty::layout::FnAbiError<'_>> {
- type Result = [u8; size_of::<Result<&'static (), ty::layout::FnAbiError<'static>>>()];
+impl<T> EraseType for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> {
+ type Result = [u8; size_of::<Result<&'static (), &'static ty::layout::FnAbiError<'static>>>()];
}
impl<T> EraseType for Result<(&'_ T, rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed> {
@@ -92,15 +96,17 @@ impl EraseType for Result<ty::GenericArg<'_>, traits::query::NoSolution> {
type Result = [u8; size_of::<Result<ty::GenericArg<'static>, traits::query::NoSolution>>()];
}
-impl EraseType for Result<bool, ty::layout::LayoutError<'_>> {
- type Result = [u8; size_of::<Result<bool, ty::layout::LayoutError<'static>>>()];
+impl EraseType for Result<bool, &ty::layout::LayoutError<'_>> {
+ type Result = [u8; size_of::<Result<bool, &'static ty::layout::LayoutError<'static>>>()];
}
-impl EraseType for Result<rustc_target::abi::TyAndLayout<'_, Ty<'_>>, ty::layout::LayoutError<'_>> {
+impl EraseType
+ for Result<rustc_target::abi::TyAndLayout<'_, Ty<'_>>, &ty::layout::LayoutError<'_>>
+{
type Result = [u8; size_of::<
Result<
rustc_target::abi::TyAndLayout<'static, Ty<'static>>,
- ty::layout::LayoutError<'static>,
+ &'static ty::layout::LayoutError<'static>,
>,
>()];
}
@@ -309,7 +315,6 @@ tcx_lifetime! {
rustc_middle::mir::interpret::ConstValue,
rustc_middle::mir::interpret::GlobalId,
rustc_middle::mir::interpret::LitToConstInput,
- rustc_middle::traits::ChalkEnvironmentAndGoal,
rustc_middle::traits::query::MethodAutoderefStepsResult,
rustc_middle::traits::query::type_op::AscribeUserType,
rustc_middle::traits::query::type_op::Eq,
@@ -317,7 +322,7 @@ tcx_lifetime! {
rustc_middle::traits::query::type_op::Subtype,
rustc_middle::ty::AdtDef,
rustc_middle::ty::AliasTy,
- rustc_middle::ty::Clause,
+ rustc_middle::ty::ClauseKind,
rustc_middle::ty::ClosureTypeInfo,
rustc_middle::ty::Const,
rustc_middle::ty::DestructuredConst,
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index fa62b7f32..28e699cd2 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -2,6 +2,7 @@
use crate::infer::canonical::Canonical;
use crate::mir;
+use crate::mir::interpret::ConstValue;
use crate::traits;
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::layout::{TyAndLayout, ValidityRequirement};
@@ -317,11 +318,11 @@ impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
}
}
-impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
+impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) {
type CacheSelector = DefaultCacheSelector<Self>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
- tcx.def_span(self.1.def_id())
+ tcx.def_span(self.1.def_id)
}
}
@@ -333,6 +334,14 @@ impl<'tcx> Key for (ty::Const<'tcx>, FieldIdx) {
}
}
+impl<'tcx> Key for (ConstValue<'tcx>, Ty<'tcx>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
+ fn default_span(&self, _: TyCtxt<'_>) -> Span {
+ DUMMY_SP
+ }
+}
+
impl<'tcx> Key for mir::interpret::ConstAlloc<'tcx> {
type CacheSelector = DefaultCacheSelector<Self>;
@@ -420,7 +429,7 @@ impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
}
}
-impl<'tcx> Key for &'tcx ty::List<ty::Predicate<'tcx>> {
+impl<'tcx> Key for &'tcx ty::List<ty::Clause<'tcx>> {
type CacheSelector = DefaultCacheSelector<Self>;
fn default_span(&self, _: TyCtxt<'_>) -> Span {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 1528be42f..a059590e6 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -39,8 +39,8 @@ use crate::traits::query::{
};
use crate::traits::specialization_graph;
use crate::traits::{
- CanonicalChalkEnvironmentAndGoal, CodegenObligationError, EvaluationResult, ImplSource,
- ObjectSafetyViolation, ObligationCause, OverflowError, WellFormedLoc,
+ CodegenObligationError, EvaluationResult, ImplSource, ObjectSafetyViolation, ObligationCause,
+ OverflowError, WellFormedLoc,
};
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::layout::ValidityRequirement;
@@ -54,7 +54,7 @@ use crate::ty::{
};
use rustc_arena::TypedArena;
use rustc_ast as ast;
-use rustc_ast::expand::allocator::AllocatorKind;
+use rustc_ast::expand::{allocator::AllocatorKind, StrippedCfgItem};
use rustc_attr as attr;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
@@ -346,7 +346,7 @@ rustc_queries! {
/// `key` is the `DefId` of the associated type or opaque type.
///
/// Bounds from the parent (e.g. with nested impl trait) are not included.
- query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, Span)]> {
+ query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> {
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
@@ -373,7 +373,7 @@ rustc_queries! {
/// ```
///
/// Bounds from the parent (e.g. with nested impl trait) are not included.
- query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
+ query item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx ty::List<ty::Clause<'tcx>>> {
desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
}
@@ -531,6 +531,19 @@ rustc_queries! {
}
}
+ /// Returns names of captured upvars for closures and generators.
+ ///
+ /// Here are some examples:
+ /// - `name__field1__field2` when the upvar is captured by value.
+ /// - `_ref__name__field` when the upvar is captured by reference.
+ ///
+ /// For generators this only contains upvars that are shared by all states.
+ query closure_saved_names_of_captured_variables(def_id: DefId) -> &'tcx IndexVec<abi::FieldIdx, Symbol> {
+ arena_cache
+ desc { |tcx| "computing debuginfo for closure `{}`", tcx.def_path_str(def_id) }
+ separate_provide_extern
+ }
+
query mir_generator_witnesses(key: DefId) -> &'tcx Option<mir::GeneratorLayout<'tcx>> {
arena_cache
desc { |tcx| "generator witness types for `{}`", tcx.def_path_str(key) }
@@ -868,7 +881,7 @@ rustc_queries! {
///
/// Note that we've liberated the late bound regions of function signatures, so
/// this can not be used to check whether these types are well formed.
- query assumed_wf_types(key: DefId) -> &'tcx ty::List<Ty<'tcx>> {
+ query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) }
}
@@ -1074,19 +1087,13 @@ rustc_queries! {
}
/// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index
- /// and its field values.
- query try_destructure_mir_constant(
- key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
+ /// and its field values. This should only be used for pretty printing.
+ query try_destructure_mir_constant_for_diagnostics(
+ key: (ConstValue<'tcx>, Ty<'tcx>)
) -> Option<mir::DestructuredConstant<'tcx>> {
desc { "destructuring MIR constant"}
- }
-
- /// Dereference a constant reference or raw pointer and turn the result into a constant
- /// again.
- query deref_mir_constant(
- key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
- ) -> mir::ConstantKind<'tcx> {
- desc { "dereferencing MIR constant" }
+ no_hash
+ eval_always
}
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
@@ -1100,10 +1107,6 @@ rustc_queries! {
desc { "converting literal to const" }
}
- query lit_to_mir_constant(key: LitToConstInput<'tcx>) -> Result<mir::ConstantKind<'tcx>, LitToConstError> {
- desc { "converting literal to mir constant" }
- }
-
query check_match(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> {
desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) }
cache_on_disk_if { true }
@@ -1275,7 +1278,7 @@ rustc_queries! {
}
query codegen_select_candidate(
- key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
+ key: (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>)
) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
cache_on_disk_if { true }
desc { |tcx| "computing candidate for `{}`", key.1 }
@@ -1382,7 +1385,7 @@ rustc_queries! {
/// executes in "reveal all" mode, and will normalize the input type.
query layout_of(
key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
- ) -> Result<ty::layout::TyAndLayout<'tcx>, ty::layout::LayoutError<'tcx>> {
+ ) -> Result<ty::layout::TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> {
depth_limit
desc { "computing layout of `{}`", key.value }
}
@@ -1393,7 +1396,7 @@ rustc_queries! {
/// instead, where the instance is an `InstanceDef::Virtual`.
query fn_abi_of_fn_ptr(
key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
- ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
+ ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
desc { "computing call ABI of `{}` function pointers", key.value.0 }
}
@@ -1404,7 +1407,7 @@ rustc_queries! {
/// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
query fn_abi_of_instance(
key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
- ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
+ ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> {
desc { "computing call ABI of `{}`", key.value.0 }
}
@@ -1487,8 +1490,9 @@ rustc_queries! {
desc { "getting traits in scope at a block" }
}
- query impl_defaultness(def_id: DefId) -> hir::Defaultness {
- desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) }
+ /// Returns whether the impl or associated function has the `default` keyword.
+ query defaultness(def_id: DefId) -> hir::Defaultness {
+ desc { |tcx| "looking up whether `{}` has `default`", tcx.def_path_str(def_id) }
separate_provide_extern
feedable
}
@@ -1915,6 +1919,16 @@ rustc_queries! {
}
/// Do not call this query directly: invoke `normalize` instead.
+ query normalize_weak_ty(
+ goal: CanonicalProjectionGoal<'tcx>
+ ) -> Result<
+ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
+ NoSolution,
+ > {
+ desc { "normalizing `{}`", goal.value.value }
+ }
+
+ /// Do not call this query directly: invoke `normalize` instead.
query normalize_inherent_projection_ty(
goal: CanonicalProjectionGoal<'tcx>
) -> Result<
@@ -1959,15 +1973,6 @@ rustc_queries! {
desc { "evaluating trait selection obligation `{}`", goal.value.value }
}
- query evaluate_goal(
- goal: CanonicalChalkEnvironmentAndGoal<'tcx>
- ) -> Result<
- &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
- NoSolution
- > {
- desc { "evaluating trait selection obligation `{}`", goal.value }
- }
-
/// Do not call this query directly: part of the `Eq` type-op
query type_op_ascribe_user_type(
goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx>
@@ -2019,10 +2024,10 @@ rustc_queries! {
}
/// Do not call this query directly: part of the `Normalize` type-op
- query type_op_normalize_predicate(
- goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>>
+ query type_op_normalize_clause(
+ goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Clause<'tcx>>
) -> Result<
- &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>,
+ &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Clause<'tcx>>>,
NoSolution,
> {
desc { "normalizing `{:?}`", goal.value.value.value }
@@ -2113,7 +2118,7 @@ rustc_queries! {
desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
}
- query reveal_opaque_types_in_bounds(key: &'tcx ty::List<ty::Predicate<'tcx>>) -> &'tcx ty::List<ty::Predicate<'tcx>> {
+ query reveal_opaque_types_in_bounds(key: &'tcx ty::List<ty::Clause<'tcx>>) -> &'tcx ty::List<ty::Clause<'tcx>> {
desc { "revealing opaque types in `{:?}`", key }
}
@@ -2152,7 +2157,7 @@ rustc_queries! {
separate_provide_extern
}
- query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, ty::layout::LayoutError<'tcx>> {
+ query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, &'tcx ty::layout::LayoutError<'tcx>> {
desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 }
}
@@ -2185,6 +2190,19 @@ rustc_queries! {
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"}
}
+
+ /// Get all item paths that were stripped by a `#[cfg]` in a particular crate.
+ /// Should not be called for the local crate before the resolver outputs are created, as it
+ /// is only fed there.
+ query stripped_cfg_items(cnum: CrateNum) -> &'tcx [StrippedCfgItem] {
+ feedable
+ desc { "getting cfg-ed out item names" }
+ separate_provide_extern
+ }
+
+ query generics_require_sized_self(def_id: DefId) -> bool {
+ desc { "check whether the item has a `where Self: Sized` bound" }
+ }
}
rustc_query_append! { define_callbacks! }
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 220118ae5..8751d3b78 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -791,13 +791,6 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
}
}
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
- #[inline]
- fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
- RefDecodable::decode(d)
- }
-}
-
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Clause<'tcx>, Span)] {
#[inline]
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 813e109c4..e9af5070e 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -18,7 +18,7 @@ use rustc_index::IndexVec;
use rustc_middle::middle::region;
use rustc_middle::mir::interpret::AllocId;
use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp};
-use rustc_middle::ty::adjustment::PointerCast;
+use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarSubsts};
use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
@@ -329,9 +329,10 @@ pub enum ExprKind<'tcx> {
NeverToAny {
source: ExprId,
},
- /// A pointer cast. More information can be found in [`PointerCast`].
- Pointer {
- cast: PointerCast,
+ /// A pointer coercion. More information can be found in [`PointerCoercion`].
+ /// Pointer casts that cannot be done by coercions are represented by [`ExprKind::Cast`].
+ PointerCoercion {
+ cast: PointerCoercion,
source: ExprId,
},
/// A `loop` expression.
@@ -410,6 +411,10 @@ pub enum ExprKind<'tcx> {
Return {
value: Option<ExprId>,
},
+ /// A `become` expression.
+ Become {
+ value: ExprId,
+ },
/// An inline `const` block, e.g. `const {}`.
ConstBlock {
did: DefId,
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index 5c7ec31cf..14bc1ac0c 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -65,7 +65,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
Use { source } => visitor.visit_expr(&visitor.thir()[source]),
NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
- Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
+ PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
Let { expr, .. } => {
visitor.visit_expr(&visitor.thir()[expr]);
}
@@ -100,6 +100,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
visitor.visit_expr(&visitor.thir()[value])
}
}
+ Become { value } => visitor.visit_expr(&visitor.thir()[value]),
ConstBlock { did: _, substs: _ } => {}
Repeat { value, count: _ } => {
visitor.visit_expr(&visitor.thir()[value]);
diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs
deleted file mode 100644
index fcc8f457a..000000000
--- a/compiler/rustc_middle/src/traits/chalk.rs
+++ /dev/null
@@ -1,396 +0,0 @@
-//! Types required for Chalk-related queries
-//!
-//! The primary purpose of this file is defining an implementation for the
-//! `chalk_ir::interner::Interner` trait. The primary purpose of this trait, as
-//! its name suggest, is to provide an abstraction boundary for creating
-//! interned Chalk types.
-
-use rustc_middle::ty::{self, AdtDef, TyCtxt};
-
-use rustc_hir::def_id::DefId;
-use rustc_target::spec::abi::Abi;
-
-use std::cmp::Ordering;
-use std::fmt;
-use std::hash::{Hash, Hasher};
-
-#[derive(Copy, Clone)]
-pub struct RustInterner<'tcx> {
- pub tcx: TyCtxt<'tcx>,
-}
-
-/// We don't ever actually need this. It's only required for derives.
-impl<'tcx> Hash for RustInterner<'tcx> {
- fn hash<H: Hasher>(&self, _state: &mut H) {}
-}
-
-/// We don't ever actually need this. It's only required for derives.
-impl<'tcx> Ord for RustInterner<'tcx> {
- fn cmp(&self, _other: &Self) -> Ordering {
- Ordering::Equal
- }
-}
-
-/// We don't ever actually need this. It's only required for derives.
-impl<'tcx> PartialOrd for RustInterner<'tcx> {
- fn partial_cmp(&self, _other: &Self) -> Option<Ordering> {
- None
- }
-}
-
-/// We don't ever actually need this. It's only required for derives.
-impl<'tcx> PartialEq for RustInterner<'tcx> {
- fn eq(&self, _other: &Self) -> bool {
- false
- }
-}
-
-/// We don't ever actually need this. It's only required for derives.
-impl<'tcx> Eq for RustInterner<'tcx> {}
-
-impl fmt::Debug for RustInterner<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "RustInterner")
- }
-}
-
-// Right now, there is no interning at all. I was running into problems with
-// adding interning in `ty/context.rs` for Chalk types with
-// `parallel-compiler = true`. -jackh726
-impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
- type InternedType = Box<chalk_ir::TyData<Self>>;
- type InternedLifetime = Box<chalk_ir::LifetimeData<Self>>;
- type InternedConst = Box<chalk_ir::ConstData<Self>>;
- type InternedConcreteConst = ty::ValTree<'tcx>;
- type InternedGenericArg = Box<chalk_ir::GenericArgData<Self>>;
- type InternedGoal = Box<chalk_ir::GoalData<Self>>;
- type InternedGoals = Vec<chalk_ir::Goal<Self>>;
- type InternedSubstitution = Vec<chalk_ir::GenericArg<Self>>;
- type InternedProgramClause = Box<chalk_ir::ProgramClauseData<Self>>;
- type InternedProgramClauses = Vec<chalk_ir::ProgramClause<Self>>;
- type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>;
- type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>;
- type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>;
- type InternedVariances = Vec<chalk_ir::Variance>;
- type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
- type DefId = DefId;
- type InternedAdtId = AdtDef<'tcx>;
- type Identifier = ();
- type FnAbi = Abi;
-
- fn debug_program_clause_implication(
- pci: &chalk_ir::ProgramClauseImplication<Self>,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- let mut write = || {
- write!(fmt, "{:?}", pci.consequence)?;
-
- let conditions = pci.conditions.interned();
- let constraints = pci.constraints.interned();
-
- let conds = conditions.len();
- let consts = constraints.len();
- if conds == 0 && consts == 0 {
- return Ok(());
- }
-
- write!(fmt, " :- ")?;
-
- if conds != 0 {
- for cond in &conditions[..conds - 1] {
- write!(fmt, "{:?}, ", cond)?;
- }
- write!(fmt, "{:?}", conditions[conds - 1])?;
- }
-
- if conds != 0 && consts != 0 {
- write!(fmt, " ; ")?;
- }
-
- if consts != 0 {
- for constraint in &constraints[..consts - 1] {
- write!(fmt, "{:?}, ", constraint)?;
- }
- write!(fmt, "{:?}", constraints[consts - 1])?;
- }
-
- Ok(())
- };
- Some(write())
- }
-
- fn debug_substitution(
- substitution: &chalk_ir::Substitution<Self>,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", substitution.interned()))
- }
-
- fn debug_separator_trait_ref(
- separator_trait_ref: &chalk_ir::SeparatorTraitRef<'_, Self>,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- let substitution = &separator_trait_ref.trait_ref.substitution;
- let parameters = substitution.interned();
- Some(write!(
- fmt,
- "{:?}{}{:?}{:?}",
- parameters[0],
- separator_trait_ref.separator,
- separator_trait_ref.trait_ref.trait_id,
- chalk_ir::debug::Angle(&parameters[1..])
- ))
- }
-
- fn debug_quantified_where_clauses(
- clauses: &chalk_ir::QuantifiedWhereClauses<Self>,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", clauses.interned()))
- }
-
- fn debug_ty(ty: &chalk_ir::Ty<Self>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
- match &ty.interned().kind {
- chalk_ir::TyKind::Ref(chalk_ir::Mutability::Not, lifetime, ty) => {
- Some(write!(fmt, "(&{:?} {:?})", lifetime, ty))
- }
- chalk_ir::TyKind::Ref(chalk_ir::Mutability::Mut, lifetime, ty) => {
- Some(write!(fmt, "(&{:?} mut {:?})", lifetime, ty))
- }
- chalk_ir::TyKind::Array(ty, len) => Some(write!(fmt, "[{:?}; {:?}]", ty, len)),
- chalk_ir::TyKind::Slice(ty) => Some(write!(fmt, "[{:?}]", ty)),
- chalk_ir::TyKind::Tuple(len, substs) => Some(
- try {
- write!(fmt, "(")?;
- for (idx, substitution) in substs.interned().iter().enumerate() {
- if idx == *len && *len != 1 {
- // Don't add a trailing comma if the tuple has more than one element
- write!(fmt, "{:?}", substitution)?;
- } else {
- write!(fmt, "{:?},", substitution)?;
- }
- }
- write!(fmt, ")")?;
- },
- ),
- _ => None,
- }
- }
-
- fn debug_alias(
- alias_ty: &chalk_ir::AliasTy<Self>,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- match alias_ty {
- chalk_ir::AliasTy::Projection(projection_ty) => {
- Self::debug_projection_ty(projection_ty, fmt)
- }
- chalk_ir::AliasTy::Opaque(opaque_ty) => Self::debug_opaque_ty(opaque_ty, fmt),
- }
- }
-
- fn debug_projection_ty(
- projection_ty: &chalk_ir::ProjectionTy<Self>,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(
- fmt,
- "projection: {:?} {:?}",
- projection_ty.associated_ty_id, projection_ty.substitution,
- ))
- }
-
- fn debug_opaque_ty(
- opaque_ty: &chalk_ir::OpaqueTy<Self>,
- fmt: &mut fmt::Formatter<'_>,
- ) -> Option<fmt::Result> {
- Some(write!(fmt, "{:?}", opaque_ty.opaque_ty_id))
- }
-
- fn intern_ty(self, ty: chalk_ir::TyKind<Self>) -> Self::InternedType {
- let flags = ty.compute_flags(self);
- Box::new(chalk_ir::TyData { kind: ty, flags: flags })
- }
-
- fn ty_data(self, ty: &Self::InternedType) -> &chalk_ir::TyData<Self> {
- ty
- }
-
- fn intern_lifetime(self, lifetime: chalk_ir::LifetimeData<Self>) -> Self::InternedLifetime {
- Box::new(lifetime)
- }
-
- fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &chalk_ir::LifetimeData<Self> {
- &lifetime
- }
-
- fn intern_const(self, constant: chalk_ir::ConstData<Self>) -> Self::InternedConst {
- Box::new(constant)
- }
-
- fn const_data(self, constant: &Self::InternedConst) -> &chalk_ir::ConstData<Self> {
- &constant
- }
-
- fn const_eq(
- self,
- _ty: &Self::InternedType,
- c1: &Self::InternedConcreteConst,
- c2: &Self::InternedConcreteConst,
- ) -> bool {
- c1 == c2
- }
-
- fn intern_generic_arg(self, data: chalk_ir::GenericArgData<Self>) -> Self::InternedGenericArg {
- Box::new(data)
- }
-
- fn generic_arg_data(self, data: &Self::InternedGenericArg) -> &chalk_ir::GenericArgData<Self> {
- &data
- }
-
- fn intern_goal(self, goal: chalk_ir::GoalData<Self>) -> Self::InternedGoal {
- Box::new(goal)
- }
-
- fn goal_data(self, goal: &Self::InternedGoal) -> &chalk_ir::GoalData<Self> {
- &goal
- }
-
- fn intern_goals<E>(
- self,
- data: impl IntoIterator<Item = Result<chalk_ir::Goal<Self>, E>>,
- ) -> Result<Self::InternedGoals, E> {
- data.into_iter().collect::<Result<Vec<_>, _>>()
- }
-
- fn goals_data(self, goals: &Self::InternedGoals) -> &[chalk_ir::Goal<Self>] {
- goals
- }
-
- fn intern_substitution<E>(
- self,
- data: impl IntoIterator<Item = Result<chalk_ir::GenericArg<Self>, E>>,
- ) -> Result<Self::InternedSubstitution, E> {
- data.into_iter().collect::<Result<Vec<_>, _>>()
- }
-
- fn substitution_data(
- self,
- substitution: &Self::InternedSubstitution,
- ) -> &[chalk_ir::GenericArg<Self>] {
- substitution
- }
-
- fn intern_program_clause(
- self,
- data: chalk_ir::ProgramClauseData<Self>,
- ) -> Self::InternedProgramClause {
- Box::new(data)
- }
-
- fn program_clause_data(
- self,
- clause: &Self::InternedProgramClause,
- ) -> &chalk_ir::ProgramClauseData<Self> {
- &clause
- }
-
- fn intern_program_clauses<E>(
- self,
- data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>,
- ) -> Result<Self::InternedProgramClauses, E> {
- data.into_iter().collect::<Result<Vec<_>, _>>()
- }
-
- fn program_clauses_data(
- self,
- clauses: &Self::InternedProgramClauses,
- ) -> &[chalk_ir::ProgramClause<Self>] {
- clauses
- }
-
- fn intern_quantified_where_clauses<E>(
- self,
- data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>,
- ) -> Result<Self::InternedQuantifiedWhereClauses, E> {
- data.into_iter().collect::<Result<Vec<_>, _>>()
- }
-
- fn quantified_where_clauses_data(
- self,
- clauses: &Self::InternedQuantifiedWhereClauses,
- ) -> &[chalk_ir::QuantifiedWhereClause<Self>] {
- clauses
- }
-
- fn intern_generic_arg_kinds<E>(
- self,
- data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>,
- ) -> Result<Self::InternedVariableKinds, E> {
- data.into_iter().collect::<Result<Vec<_>, _>>()
- }
-
- fn variable_kinds_data(
- self,
- parameter_kinds: &Self::InternedVariableKinds,
- ) -> &[chalk_ir::VariableKind<Self>] {
- parameter_kinds
- }
-
- fn intern_canonical_var_kinds<E>(
- self,
- data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>,
- ) -> Result<Self::InternedCanonicalVarKinds, E> {
- data.into_iter().collect::<Result<Vec<_>, _>>()
- }
-
- fn canonical_var_kinds_data(
- self,
- canonical_var_kinds: &Self::InternedCanonicalVarKinds,
- ) -> &[chalk_ir::CanonicalVarKind<Self>] {
- canonical_var_kinds
- }
-
- fn intern_constraints<E>(
- self,
- data: impl IntoIterator<Item = Result<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>, E>>,
- ) -> Result<Self::InternedConstraints, E> {
- data.into_iter().collect::<Result<Vec<_>, _>>()
- }
-
- fn constraints_data(
- self,
- constraints: &Self::InternedConstraints,
- ) -> &[chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>] {
- constraints
- }
-
- fn intern_variances<E>(
- self,
- data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>,
- ) -> Result<Self::InternedVariances, E> {
- data.into_iter().collect::<Result<Vec<_>, _>>()
- }
-
- fn variances_data(self, variances: &Self::InternedVariances) -> &[chalk_ir::Variance] {
- variances
- }
-}
-
-impl<'tcx> chalk_ir::interner::HasInterner for RustInterner<'tcx> {
- type Interner = Self;
-}
-
-/// A chalk environment and goal.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, TypeVisitable)]
-pub struct ChalkEnvironmentAndGoal<'tcx> {
- pub environment: &'tcx ty::List<ty::Predicate<'tcx>>,
- pub goal: ty::Predicate<'tcx>,
-}
-
-impl<'tcx> fmt::Display for ChalkEnvironmentAndGoal<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "environment: {:?}, goal: {}", self.environment, self.goal)
- }
-}
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 0a903a769..c7d2e4c22 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -2,7 +2,6 @@
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
-mod chalk;
pub mod query;
pub mod select;
pub mod solve;
@@ -30,12 +29,8 @@ use std::hash::{Hash, Hasher};
pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
-pub type CanonicalChalkEnvironmentAndGoal<'tcx> = Canonical<'tcx, ChalkEnvironmentAndGoal<'tcx>>;
-
pub use self::ObligationCauseCode::*;
-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, Encodable, Decodable)]
@@ -445,6 +440,12 @@ pub enum ObligationCauseCode<'tcx> {
/// Obligations to prove that a `std::ops::Drop` impl is not stronger than
/// the ADT it's being implemented for.
DropImpl,
+
+ /// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy`
+ ConstParam(Ty<'tcx>),
+
+ /// Obligations emitted during the normalization of a weak type alias.
+ TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId),
}
/// The 'location' at which we try to perform HIR-based wf checking.
@@ -587,6 +588,10 @@ pub enum SelectionError<'tcx> {
/// Signaling that an error has already been emitted, to avoid
/// multiple errors being shown.
ErrorReporting,
+ /// Computing an opaque type's hidden type caused an error (e.g. a cycle error).
+ /// We can thus not know whether the hidden type implements an auto trait, so
+ /// we should not presume anything about it.
+ OpaqueTypeAutoTraitLeakageUnknown(DefId),
}
#[derive(Clone, Debug, TypeVisitable, Lift)]
@@ -640,12 +645,6 @@ pub enum ImplSource<'tcx, N> {
/// ImplSource identifying a particular impl.
UserDefined(ImplSourceUserDefinedData<'tcx, N>),
- /// ImplSource for auto trait implementations.
- /// This carries the information and nested obligations with regards
- /// to an auto implementation for a trait `Trait`. The nested obligations
- /// ensure the trait implementation holds for all the constituent types.
- AutoImpl(ImplSourceAutoImplData<N>),
-
/// Successful resolution to an obligation provided by the caller
/// for some type parameter. The `Vec<N>` represents the
/// obligations incurred from normalizing the where-clause (if
@@ -653,84 +652,40 @@ pub enum ImplSource<'tcx, N> {
Param(Vec<N>, ty::BoundConstness),
/// Virtual calls through an object.
- Object(ImplSourceObjectData<'tcx, N>),
+ Object(ImplSourceObjectData<N>),
/// Successful resolution for a builtin trait.
- Builtin(ImplSourceBuiltinData<N>),
+ Builtin(Vec<N>),
/// ImplSource for trait upcasting coercion
- TraitUpcasting(ImplSourceTraitUpcastingData<'tcx, N>),
-
- /// ImplSource automatically generated for a closure. The `DefId` is the ID
- /// of the closure expression. This is an `ImplSource::UserDefined` in spirit, but the
- /// impl is generated by the compiler and does not appear in the source.
- Closure(ImplSourceClosureData<'tcx, N>),
-
- /// Same as above, but for a function pointer type with the given signature.
- FnPointer(ImplSourceFnPointerData<'tcx, N>),
-
- /// ImplSource automatically generated for a generator.
- Generator(ImplSourceGeneratorData<'tcx, N>),
-
- /// ImplSource automatically generated for a generator backing an async future.
- Future(ImplSourceFutureData<'tcx, N>),
-
- /// ImplSource for a trait alias.
- TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
-
- /// ImplSource for a `const Drop` implementation.
- ConstDestruct(ImplSourceConstDestructData<N>),
+ TraitUpcasting(ImplSourceTraitUpcastingData<N>),
}
impl<'tcx, N> ImplSource<'tcx, N> {
pub fn nested_obligations(self) -> Vec<N> {
match self {
ImplSource::UserDefined(i) => i.nested,
- ImplSource::Param(n, _) => n,
- ImplSource::Builtin(i) => i.nested,
- ImplSource::AutoImpl(d) => d.nested,
- ImplSource::Closure(c) => c.nested,
- ImplSource::Generator(c) => c.nested,
- ImplSource::Future(c) => c.nested,
+ ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
ImplSource::Object(d) => d.nested,
- ImplSource::FnPointer(d) => d.nested,
- ImplSource::TraitAlias(d) => d.nested,
ImplSource::TraitUpcasting(d) => d.nested,
- ImplSource::ConstDestruct(i) => i.nested,
}
}
pub fn borrow_nested_obligations(&self) -> &[N] {
match self {
ImplSource::UserDefined(i) => &i.nested,
- ImplSource::Param(n, _) => n,
- ImplSource::Builtin(i) => &i.nested,
- ImplSource::AutoImpl(d) => &d.nested,
- ImplSource::Closure(c) => &c.nested,
- ImplSource::Generator(c) => &c.nested,
- ImplSource::Future(c) => &c.nested,
+ ImplSource::Param(n, _) | ImplSource::Builtin(n) => &n,
ImplSource::Object(d) => &d.nested,
- ImplSource::FnPointer(d) => &d.nested,
- ImplSource::TraitAlias(d) => &d.nested,
ImplSource::TraitUpcasting(d) => &d.nested,
- ImplSource::ConstDestruct(i) => &i.nested,
}
}
pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] {
match self {
ImplSource::UserDefined(i) => &mut i.nested,
- ImplSource::Param(n, _) => n,
- ImplSource::Builtin(i) => &mut i.nested,
- ImplSource::AutoImpl(d) => &mut d.nested,
- ImplSource::Closure(c) => &mut c.nested,
- ImplSource::Generator(c) => &mut c.nested,
- ImplSource::Future(c) => &mut c.nested,
+ ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
ImplSource::Object(d) => &mut d.nested,
- ImplSource::FnPointer(d) => &mut d.nested,
- ImplSource::TraitAlias(d) => &mut d.nested,
ImplSource::TraitUpcasting(d) => &mut d.nested,
- ImplSource::ConstDestruct(i) => &mut i.nested,
}
}
@@ -745,54 +700,17 @@ impl<'tcx, N> ImplSource<'tcx, N> {
nested: i.nested.into_iter().map(f).collect(),
}),
ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct),
- ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData {
- nested: i.nested.into_iter().map(f).collect(),
- }),
+ ImplSource::Builtin(n) => ImplSource::Builtin(n.into_iter().map(f).collect()),
ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData {
- upcast_trait_ref: o.upcast_trait_ref,
vtable_base: o.vtable_base,
nested: o.nested.into_iter().map(f).collect(),
}),
- ImplSource::AutoImpl(d) => ImplSource::AutoImpl(ImplSourceAutoImplData {
- trait_def_id: d.trait_def_id,
- nested: d.nested.into_iter().map(f).collect(),
- }),
- ImplSource::Closure(c) => ImplSource::Closure(ImplSourceClosureData {
- closure_def_id: c.closure_def_id,
- substs: c.substs,
- nested: c.nested.into_iter().map(f).collect(),
- }),
- ImplSource::Generator(c) => ImplSource::Generator(ImplSourceGeneratorData {
- generator_def_id: c.generator_def_id,
- substs: c.substs,
- nested: c.nested.into_iter().map(f).collect(),
- }),
- ImplSource::Future(c) => ImplSource::Future(ImplSourceFutureData {
- generator_def_id: c.generator_def_id,
- substs: c.substs,
- nested: c.nested.into_iter().map(f).collect(),
- }),
- ImplSource::FnPointer(p) => ImplSource::FnPointer(ImplSourceFnPointerData {
- fn_ty: p.fn_ty,
- nested: p.nested.into_iter().map(f).collect(),
- }),
- ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData {
- alias_def_id: d.alias_def_id,
- substs: d.substs,
- nested: d.nested.into_iter().map(f).collect(),
- }),
ImplSource::TraitUpcasting(d) => {
ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData {
- upcast_trait_ref: d.upcast_trait_ref,
vtable_vptr_slot: d.vtable_vptr_slot,
nested: d.nested.into_iter().map(f).collect(),
})
}
- ImplSource::ConstDestruct(i) => {
- ImplSource::ConstDestruct(ImplSourceConstDestructData {
- nested: i.nested.into_iter().map(f).collect(),
- })
- }
}
}
}
@@ -817,47 +735,7 @@ pub struct ImplSourceUserDefinedData<'tcx, N> {
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceGeneratorData<'tcx, N> {
- pub generator_def_id: DefId,
- pub substs: SubstsRef<'tcx>,
- /// Nested obligations. This can be non-empty if the generator
- /// signature contains associated types.
- pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceFutureData<'tcx, N> {
- pub generator_def_id: DefId,
- pub substs: SubstsRef<'tcx>,
- /// Nested obligations. This can be non-empty if the generator
- /// signature contains associated types.
- pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceClosureData<'tcx, N> {
- pub closure_def_id: DefId,
- pub substs: SubstsRef<'tcx>,
- /// Nested obligations. This can be non-empty if the closure
- /// signature contains associated types.
- pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceAutoImplData<N> {
- pub trait_def_id: DefId,
- pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceTraitUpcastingData<'tcx, N> {
- /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
- pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
-
+pub struct ImplSourceTraitUpcastingData<N> {
/// The vtable is formed by concatenating together the method lists of
/// the base object trait and all supertraits, pointers to supertrait vtable will
/// be provided when necessary; this is the position of `upcast_trait_ref`'s vtable
@@ -867,18 +745,9 @@ pub struct ImplSourceTraitUpcastingData<'tcx, N> {
pub nested: Vec<N>,
}
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceBuiltinData<N> {
- pub nested: Vec<N>,
-}
-
#[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceObjectData<'tcx, N> {
- /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
- pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
-
+pub struct ImplSourceObjectData<N> {
/// The vtable is formed by concatenating together the method lists of
/// the base object trait and all supertraits, pointers to supertrait vtable will
/// be provided when necessary; this is the start of `upcast_trait_ref`'s methods
@@ -888,27 +757,6 @@ pub struct ImplSourceObjectData<'tcx, N> {
pub nested: Vec<N>,
}
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceFnPointerData<'tcx, N> {
- pub fn_ty: Ty<'tcx>,
- pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceConstDestructData<N> {
- pub nested: Vec<N>,
-}
-
-#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ImplSourceTraitAliasData<'tcx, N> {
- pub alias_def_id: DefId,
- pub substs: SubstsRef<'tcx>,
- pub nested: Vec<N>,
-}
-
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
pub enum ObjectSafetyViolation {
/// `Self: Sized` declared on the trait.
@@ -1109,7 +957,7 @@ pub enum CodegenObligationError {
FulfillmentError,
}
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
pub enum DefiningAnchor {
/// `DefId` of the item.
Bind(LocalDefId),
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index eae5a280e..60a38747f 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -92,7 +92,7 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
-#[derive(Copy, Clone, Debug, HashStable, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Hash, HashStable, PartialEq, Eq)]
pub struct NoSolution;
impl<'tcx> From<TypeError<'tcx>> for NoSolution {
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index 2c5b64a59..73b332fd8 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -11,6 +11,8 @@ use crate::ty::{
TypeVisitor,
};
+pub mod inspect;
+
pub type EvaluationCache<'tcx> = Cache<CanonicalInput<'tcx>, QueryResult<'tcx>>;
/// A goal is a statement, i.e. `predicate`, we want to prove
@@ -18,7 +20,7 @@ pub type EvaluationCache<'tcx> = Cache<CanonicalInput<'tcx>, QueryResult<'tcx>>;
///
/// Most of the time the `param_env` contains the `where`-bounds of the function
/// we're currently typechecking while the `predicate` is some trait bound.
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
pub struct Goal<'tcx, P> {
pub predicate: P,
pub param_env: ty::ParamEnv<'tcx>,
@@ -39,7 +41,7 @@ impl<'tcx, P> Goal<'tcx, P> {
}
}
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
pub struct Response<'tcx> {
pub certainty: Certainty,
pub var_values: CanonicalVarValues<'tcx>,
@@ -47,7 +49,7 @@ pub struct Response<'tcx> {
pub external_constraints: ExternalConstraints<'tcx>,
}
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
pub enum Certainty {
Yes,
Maybe(MaybeCause),
@@ -86,7 +88,7 @@ impl Certainty {
}
/// Why we failed to evaluate a goal.
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
pub enum MaybeCause {
/// We failed due to ambiguity. This ambiguity can either
/// be a true ambiguity, i.e. there are multiple different answers,
@@ -96,7 +98,7 @@ pub enum MaybeCause {
Overflow,
}
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
pub struct QueryInput<'tcx, T> {
pub goal: Goal<'tcx, T>,
pub anchor: DefiningAnchor,
@@ -104,12 +106,12 @@ pub struct QueryInput<'tcx, T> {
}
/// Additional constraints returned on success.
-#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
+#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default)]
pub struct PredefinedOpaquesData<'tcx> {
pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
}
-#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
+#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable)]
pub struct PredefinedOpaques<'tcx>(pub(crate) Interned<'tcx, PredefinedOpaquesData<'tcx>>);
impl<'tcx> std::ops::Deref for PredefinedOpaques<'tcx> {
@@ -132,7 +134,7 @@ pub type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
/// solver, merge the two responses again.
pub type QueryResult<'tcx> = Result<CanonicalResponse<'tcx>, NoSolution>;
-#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
+#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable)]
pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>);
impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
@@ -144,7 +146,7 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
}
/// Additional constraints returned on success.
-#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
+#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default)]
pub struct ExternalConstraintsData<'tcx> {
// FIXME: implement this.
pub region_constraints: QueryRegionConstraints<'tcx>,
@@ -226,3 +228,9 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
self.opaque_types.visit_with(visitor)
}
}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
+pub enum IsNormalizesToHack {
+ Yes,
+ No,
+}
diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs
new file mode 100644
index 000000000..527afa005
--- /dev/null
+++ b/compiler/rustc_middle/src/traits/solve/inspect.rs
@@ -0,0 +1,83 @@
+use super::{
+ CanonicalInput, Certainty, Goal, IsNormalizesToHack, NoSolution, QueryInput, QueryResult,
+};
+use crate::ty;
+use format::ProofTreeFormatter;
+use std::fmt::{Debug, Write};
+
+mod format;
+
+#[derive(Eq, PartialEq, Debug, Hash, HashStable)]
+pub enum CacheHit {
+ Provisional,
+ Global,
+}
+
+#[derive(Eq, PartialEq, Hash, HashStable)]
+pub struct GoalEvaluation<'tcx> {
+ pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>,
+ pub canonicalized_goal: CanonicalInput<'tcx>,
+
+ pub kind: GoalEvaluationKind<'tcx>,
+ pub is_normalizes_to_hack: IsNormalizesToHack,
+ pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
+
+ pub result: QueryResult<'tcx>,
+}
+
+#[derive(Eq, PartialEq, Hash, HashStable)]
+pub enum GoalEvaluationKind<'tcx> {
+ CacheHit(CacheHit),
+ Uncached { revisions: Vec<GoalEvaluationStep<'tcx>> },
+}
+impl Debug for GoalEvaluation<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ ProofTreeFormatter { f, on_newline: true }.format_goal_evaluation(self)
+ }
+}
+
+#[derive(Eq, PartialEq, Hash, HashStable)]
+pub struct AddedGoalsEvaluation<'tcx> {
+ pub evaluations: Vec<Vec<GoalEvaluation<'tcx>>>,
+ pub result: Result<Certainty, NoSolution>,
+}
+impl Debug for AddedGoalsEvaluation<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ ProofTreeFormatter { f, on_newline: true }.format_nested_goal_evaluation(self)
+ }
+}
+
+#[derive(Eq, PartialEq, Hash, HashStable)]
+pub struct GoalEvaluationStep<'tcx> {
+ pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>,
+
+ pub nested_goal_evaluations: Vec<AddedGoalsEvaluation<'tcx>>,
+ pub candidates: Vec<GoalCandidate<'tcx>>,
+
+ pub result: QueryResult<'tcx>,
+}
+impl Debug for GoalEvaluationStep<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ ProofTreeFormatter { f, on_newline: true }.format_evaluation_step(self)
+ }
+}
+
+#[derive(Eq, PartialEq, Hash, HashStable)]
+pub struct GoalCandidate<'tcx> {
+ pub nested_goal_evaluations: Vec<AddedGoalsEvaluation<'tcx>>,
+ pub candidates: Vec<GoalCandidate<'tcx>>,
+ pub kind: CandidateKind<'tcx>,
+}
+
+#[derive(Eq, PartialEq, Debug, Hash, HashStable)]
+pub enum CandidateKind<'tcx> {
+ /// Probe entered when normalizing the self ty during candidate assembly
+ NormalizedSelfTyAssembly,
+ /// A normal candidate for proving a goal
+ Candidate { name: String, result: QueryResult<'tcx> },
+}
+impl Debug for GoalCandidate<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ ProofTreeFormatter { f, on_newline: true }.format_candidate(self)
+ }
+}
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
new file mode 100644
index 000000000..2ee625674
--- /dev/null
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -0,0 +1,131 @@
+use super::*;
+
+pub(super) struct ProofTreeFormatter<'a, 'b> {
+ pub(super) f: &'a mut (dyn Write + 'b),
+ pub(super) on_newline: bool,
+}
+
+impl Write for ProofTreeFormatter<'_, '_> {
+ fn write_str(&mut self, s: &str) -> std::fmt::Result {
+ for line in s.split_inclusive("\n") {
+ if self.on_newline {
+ self.f.write_str(" ")?;
+ }
+ self.on_newline = line.ends_with("\n");
+ self.f.write_str(line)?;
+ }
+
+ Ok(())
+ }
+}
+
+impl ProofTreeFormatter<'_, '_> {
+ fn nested(&mut self) -> ProofTreeFormatter<'_, '_> {
+ ProofTreeFormatter { f: self, on_newline: true }
+ }
+
+ pub(super) fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result {
+ let f = &mut *self.f;
+
+ let goal_text = match goal.is_normalizes_to_hack {
+ IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL",
+ IsNormalizesToHack::No => "GOAL",
+ };
+
+ writeln!(f, "{}: {:?}", goal_text, goal.uncanonicalized_goal,)?;
+ writeln!(f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?;
+
+ match &goal.kind {
+ GoalEvaluationKind::CacheHit(CacheHit::Global) => {
+ writeln!(f, "GLOBAL CACHE HIT: {:?}", goal.result)
+ }
+ GoalEvaluationKind::CacheHit(CacheHit::Provisional) => {
+ writeln!(f, "PROVISIONAL CACHE HIT: {:?}", goal.result)
+ }
+ GoalEvaluationKind::Uncached { revisions } => {
+ for (n, step) in revisions.iter().enumerate() {
+ let f = &mut *self.f;
+ writeln!(f, "REVISION {n}: {:?}", step.result)?;
+ let mut f = self.nested();
+ f.format_evaluation_step(step)?;
+ }
+
+ let f = &mut *self.f;
+ writeln!(f, "RESULT: {:?}", goal.result)
+ }
+ }?;
+
+ if goal.returned_goals.len() > 0 {
+ let f = &mut *self.f;
+ writeln!(f, "NESTED GOALS ADDED TO CALLER: [")?;
+ let mut f = self.nested();
+ for goal in goal.returned_goals.iter() {
+ writeln!(f, "ADDED GOAL: {:?},", goal)?;
+ }
+ writeln!(self.f, "]")?;
+ }
+
+ Ok(())
+ }
+
+ pub(super) fn format_evaluation_step(
+ &mut self,
+ evaluation_step: &GoalEvaluationStep<'_>,
+ ) -> std::fmt::Result {
+ let f = &mut *self.f;
+ writeln!(f, "INSTANTIATED: {:?}", evaluation_step.instantiated_goal)?;
+
+ for candidate in &evaluation_step.candidates {
+ let mut f = self.nested();
+ f.format_candidate(candidate)?;
+ }
+ for nested_goal_evaluation in &evaluation_step.nested_goal_evaluations {
+ let mut f = self.nested();
+ f.format_nested_goal_evaluation(nested_goal_evaluation)?;
+ }
+
+ Ok(())
+ }
+
+ pub(super) fn format_candidate(&mut self, candidate: &GoalCandidate<'_>) -> std::fmt::Result {
+ let f = &mut *self.f;
+
+ match &candidate.kind {
+ CandidateKind::NormalizedSelfTyAssembly => {
+ writeln!(f, "NORMALIZING SELF TY FOR ASSEMBLY:")
+ }
+ CandidateKind::Candidate { name, result } => {
+ writeln!(f, "CANDIDATE {}: {:?}", name, result)
+ }
+ }?;
+
+ let mut f = self.nested();
+ for candidate in &candidate.candidates {
+ f.format_candidate(candidate)?;
+ }
+ for nested_evaluations in &candidate.nested_goal_evaluations {
+ f.format_nested_goal_evaluation(nested_evaluations)?;
+ }
+
+ Ok(())
+ }
+
+ pub(super) fn format_nested_goal_evaluation(
+ &mut self,
+ nested_goal_evaluation: &AddedGoalsEvaluation<'_>,
+ ) -> std::fmt::Result {
+ let f = &mut *self.f;
+ writeln!(f, "TRY_EVALUATE_ADDED_GOALS: {:?}", nested_goal_evaluation.result)?;
+
+ for (n, revision) in nested_goal_evaluation.evaluations.iter().enumerate() {
+ let f = &mut *self.f;
+ writeln!(f, "REVISION {n}")?;
+ let mut f = self.nested();
+ for goal_evaluation in revision {
+ f.format_goal_evaluation(goal_evaluation)?;
+ }
+ }
+
+ Ok(())
+ }
+}
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index c016f7227..dc2cd2035 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -228,7 +228,7 @@ impl<'tcx> Ancestors<'tcx> {
if let Some(item) = node.item(tcx, trait_item_def_id) {
if finalizing_node.is_none() {
let is_specializable = item.defaultness(tcx).is_default()
- || tcx.impl_defaultness(node.def_id()).is_default();
+ || tcx.defaultness(node.def_id()).is_default();
if !is_specializable {
finalizing_node = Some(node);
diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs
index 6acb7745d..a703e3c95 100644
--- a/compiler/rustc_middle/src/traits/structural_impls.rs
+++ b/compiler/rustc_middle/src/traits/structural_impls.rs
@@ -9,15 +9,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
match *self {
super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v),
- super::ImplSource::AutoImpl(ref t) => write!(f, "{:?}", t),
-
- super::ImplSource::Closure(ref d) => write!(f, "{:?}", d),
-
- super::ImplSource::Generator(ref d) => write!(f, "{:?}", d),
-
- super::ImplSource::Future(ref d) => write!(f, "{:?}", d),
-
- super::ImplSource::FnPointer(ref d) => write!(f, "({:?})", d),
+ super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d),
super::ImplSource::Object(ref d) => write!(f, "{:?}", d),
@@ -25,13 +17,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
write!(f, "ImplSourceParamData({:?}, {:?})", n, ct)
}
- super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d),
-
- super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d),
-
super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),
-
- super::ImplSource::ConstDestruct(ref d) => write!(f, "{:?}", d),
}
}
}
@@ -46,90 +32,22 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceUserDefinedData<'tcx,
}
}
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceGeneratorData<'tcx, N> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(
- f,
- "ImplSourceGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})",
- self.generator_def_id, self.substs, self.nested
- )
- }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFutureData<'tcx, N> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(
- f,
- "ImplSourceFutureData(generator_def_id={:?}, substs={:?}, nested={:?})",
- self.generator_def_id, self.substs, self.nested
- )
- }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceClosureData<'tcx, N> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(
- f,
- "ImplSourceClosureData(closure_def_id={:?}, substs={:?}, nested={:?})",
- self.closure_def_id, self.substs, self.nested
- )
- }
-}
-
-impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceBuiltinData<N> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "ImplSourceBuiltinData(nested={:?})", self.nested)
- }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitUpcastingData<'tcx, N> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(
- f,
- "ImplSourceTraitUpcastingData(upcast={:?}, vtable_vptr_slot={:?}, nested={:?})",
- self.upcast_trait_ref, self.vtable_vptr_slot, self.nested
- )
- }
-}
-
-impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceAutoImplData<N> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(
- f,
- "ImplSourceAutoImplData(trait_def_id={:?}, nested={:?})",
- self.trait_def_id, self.nested
- )
- }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceObjectData<'tcx, N> {
+impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitUpcastingData<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
- "ImplSourceObjectData(upcast={:?}, vtable_base={}, nested={:?})",
- self.upcast_trait_ref, self.vtable_base, self.nested
+ "ImplSourceTraitUpcastingData(vtable_vptr_slot={:?}, nested={:?})",
+ self.vtable_vptr_slot, self.nested
)
}
}
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFnPointerData<'tcx, N> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "ImplSourceFnPointerData(fn_ty={:?}, nested={:?})", self.fn_ty, self.nested)
- }
-}
-
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx, N> {
+impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceObjectData<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
- "ImplSourceTraitAliasData(alias_def_id={:?}, substs={:?}, nested={:?})",
- self.alias_def_id, self.substs, self.nested
+ "ImplSourceObjectData(vtable_base={}, nested={:?})",
+ self.vtable_base, self.nested
)
}
}
-
-impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDestructData<N> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "ImplSourceConstDestructData(nested={:?})", self.nested)
- }
-}
diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs
index d54b8c599..05c06efaf 100644
--- a/compiler/rustc_middle/src/traits/util.rs
+++ b/compiler/rustc_middle/src/traits/util.rs
@@ -25,9 +25,7 @@ impl<'tcx> Elaborator<'tcx> {
.super_predicates_of(trait_ref.def_id())
.predicates
.into_iter()
- .flat_map(|(pred, _)| {
- pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_pred()
- })
+ .flat_map(|(pred, _)| pred.subst_supertrait(self.tcx, &trait_ref).as_trait_clause())
.map(|t| t.map_bound(|pred| pred.trait_ref))
.filter(|supertrait_ref| self.visited.insert(*supertrait_ref));
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index cbc68fde9..09517200b 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -81,7 +81,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(guar)),
+ (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.tcx(), guar)),
_ => relate::structurally_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 a39631da9..ffee7ba28 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -53,7 +53,7 @@ impl<'tcx> TyCtxt<'tcx> {
fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
let ct = match c.kind() {
ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
- Err(e) => self.tcx.const_error(c.ty(), e),
+ Err(e) => ty::Const::new_error(self.tcx, e, c.ty()),
Ok(Some(bac)) => {
let substs = self.tcx.erase_regions(uv.substs);
let bac = bac.subst(self.tcx, substs);
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index cd0f7e8da..76931ceaa 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -6,7 +6,7 @@ use rustc_span::Span;
use rustc_target::abi::FieldIdx;
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
-pub enum PointerCast {
+pub enum PointerCoercion {
/// Go from a fn-item type to a fn-pointer type.
ReifyFnPointer,
@@ -99,7 +99,7 @@ pub enum Adjust<'tcx> {
/// Take the address and produce either a `&` or `*` pointer.
Borrow(AutoBorrow<'tcx>),
- Pointer(PointerCast),
+ Pointer(PointerCoercion),
/// Cast into a dyn* object.
DynStar,
@@ -132,7 +132,7 @@ impl<'tcx> OverloadedDeref<'tcx> {
.find(|m| m.kind == ty::AssocKind::Fn)
.unwrap()
.def_id;
- tcx.mk_fn_def(method_def_id, [source])
+ Ty::new_fn_def(tcx, method_def_id, [source])
}
}
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 7c5c030c2..e067d2a98 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -573,7 +573,7 @@ impl<'tcx> AdtDef<'tcx> {
/// Due to normalization being eager, this applies even if
/// the associated type is behind a pointer (e.g., issue #31299).
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> {
- ty::EarlyBinder(tcx.adt_sized_constraint(self.did()))
+ ty::EarlyBinder::bind(tcx.adt_sized_constraint(self.did()))
}
}
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index 090b76932..cce609c26 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -48,7 +48,7 @@ impl AssocItem {
///
/// [`type_of`]: crate::ty::TyCtxt::type_of
pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness {
- tcx.impl_defaultness(self.def_id)
+ tcx.defaultness(self.def_id)
}
#[inline]
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index be7b2b7ec..bc9273745 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -427,6 +427,8 @@ pub enum BorrowKind {
/// immutable, but not aliasable. This solves the problem. For
/// simplicity, we don't give users the way to express this
/// borrow, it's just used when translating closures.
+ ///
+ /// FIXME: Rename this to indicate the borrow is actually not immutable.
UniqueImmBorrow,
/// Data is mutable and not aliasable.
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 7fc75674d..6adbb44a1 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -128,6 +128,12 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx>
}
}
+impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Clause<'tcx> {
+ fn encode(&self, e: &mut E) {
+ self.as_predicate().encode(e);
+ }
+}
+
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Region<'tcx> {
fn encode(&self, e: &mut E) {
self.kind().encode(e);
@@ -241,6 +247,13 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx>
}
}
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Clause<'tcx> {
+ fn decode(decoder: &mut D) -> ty::Clause<'tcx> {
+ let pred: ty::Predicate<'tcx> = Decodable::decode(decoder);
+ pred.expect_clause()
+ }
+}
+
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for SubstsRef<'tcx> {
fn decode(decoder: &mut D) -> Self {
let len = decoder.read_usize();
@@ -264,7 +277,7 @@ 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_from_kind(Decodable::decode(decoder))
+ ty::Region::new_from_kind(decoder.interner(), Decodable::decode(decoder))
}
}
@@ -331,7 +344,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> {
fn decode(decoder: &mut D) -> Self {
let consts: ty::ConstData<'tcx> = Decodable::decode(decoder);
- decoder.interner().mk_const(consts.kind, consts.ty)
+ decoder.interner().mk_ct_from_kind(consts.kind, consts.ty)
}
}
@@ -355,16 +368,6 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AdtDef<'tcx> {
}
}
-impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
- for [(ty::Predicate<'tcx>, Span)]
-{
- fn decode(decoder: &mut D) -> &'tcx Self {
- decoder.interner().arena.alloc_from_iter(
- (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(),
- )
- }
-}
-
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] {
fn decode(decoder: &mut D) -> &'tcx Self {
decoder.interner().arena.alloc_from_iter(
@@ -393,11 +396,11 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty
}
}
-impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Predicate<'tcx>> {
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Clause<'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)),
+ decoder.interner().mk_clauses_from_iter(
+ (0..len).map::<ty::Clause<'tcx>, _>(|_| Decodable::decode(decoder)),
)
}
}
@@ -421,7 +424,7 @@ impl_decodable_via_ref! {
&'tcx mir::BorrowCheckResult<'tcx>,
&'tcx mir::coverage::CodeRegion,
&'tcx ty::List<ty::BoundVariableKind>,
- &'tcx ty::List<ty::Predicate<'tcx>>,
+ &'tcx ty::List<ty::Clause<'tcx>>,
&'tcx ty::List<FieldIdx>,
}
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 1a4bd1481..1cbfe99f8 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,7 +1,8 @@
use crate::middle::resolve_bound_vars as rbv;
-use crate::mir::interpret::LitToConstInput;
-use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
+use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar};
+use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
use rustc_data_structures::intern::Interned;
+use rustc_error_messages::MultiSpan;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
@@ -13,8 +14,13 @@ mod valtree;
pub use int::*;
pub use kind::*;
+use rustc_span::ErrorGuaranteed;
+use rustc_span::DUMMY_SP;
+use rustc_target::abi::Size;
pub use valtree::*;
+use super::sty::ConstKind;
+
/// Use this rather than `ConstData`, whenever possible.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
#[rustc_pass_by_value]
@@ -30,6 +36,16 @@ pub struct ConstData<'tcx> {
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(ConstData<'_>, 40);
+enum EvalMode {
+ Typeck,
+ Mir,
+}
+
+enum EvalResult<'tcx> {
+ ValTree(ty::ValTree<'tcx>),
+ ConstVal(ConstValue<'tcx>),
+}
+
impl<'tcx> Const<'tcx> {
#[inline]
pub fn ty(self) -> Ty<'tcx> {
@@ -38,7 +54,98 @@ impl<'tcx> Const<'tcx> {
#[inline]
pub fn kind(self) -> ConstKind<'tcx> {
- self.0.kind
+ self.0.kind.clone()
+ }
+
+ #[inline]
+ pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ tcx.mk_ct_from_kind(kind, ty)
+ }
+
+ #[inline]
+ pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Param(param), ty)
+ }
+
+ #[inline]
+ pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)), ty)
+ }
+
+ #[inline]
+ pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)), ty)
+ }
+
+ #[inline]
+ pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Infer(infer), ty)
+ }
+
+ #[inline]
+ pub fn new_bound(
+ tcx: TyCtxt<'tcx>,
+ debruijn: ty::DebruijnIndex,
+ var: ty::BoundVar,
+ ty: Ty<'tcx>,
+ ) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Bound(debruijn, var), ty)
+ }
+
+ #[inline]
+ pub fn new_placeholder(
+ tcx: TyCtxt<'tcx>,
+ placeholder: ty::PlaceholderConst<'tcx>,
+ ty: Ty<'tcx>,
+ ) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty)
+ }
+
+ #[inline]
+ pub fn new_unevaluated(
+ tcx: TyCtxt<'tcx>,
+ uv: ty::UnevaluatedConst<'tcx>,
+ ty: Ty<'tcx>,
+ ) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Unevaluated(uv), ty)
+ }
+
+ #[inline]
+ pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Value(val), ty)
+ }
+
+ #[inline]
+ pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Expr(expr), ty)
+ }
+
+ #[inline]
+ pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Error(e), ty)
+ }
+
+ /// Like [Ty::new_error] but for constants.
+ #[track_caller]
+ pub fn new_misc_error(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new_error_with_message(
+ tcx,
+ ty,
+ DUMMY_SP,
+ "ty::ConstKind::Error constructed but no error reported",
+ )
+ }
+
+ /// Like [Ty::new_error_with_message] but for constants.
+ #[track_caller]
+ pub fn new_error_with_message<S: Into<MultiSpan>>(
+ tcx: TyCtxt<'tcx>,
+ ty: Ty<'tcx>,
+ span: S,
+ msg: &'static str,
+ ) -> Const<'tcx> {
+ let reported = tcx.sess.delay_span_bug(span, msg);
+ Const::new_error(tcx, reported, ty)
}
/// Literals and const generic parameters are eagerly converted to a constant, everything else
@@ -60,7 +167,8 @@ impl<'tcx> Const<'tcx> {
match Self::try_eval_lit_or_param(tcx, ty, expr) {
Some(v) => v,
- None => tcx.mk_const(
+ None => ty::Const::new_unevaluated(
+ tcx,
ty::UnevaluatedConst {
def: def.to_def_id(),
substs: InternalSubsts::identity_for_item(tcx, def.to_def_id()),
@@ -126,13 +234,19 @@ impl<'tcx> Const<'tcx> {
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
let name = tcx.item_name(def_id);
- Some(tcx.mk_const(ty::ParamConst::new(index, name), param_ty))
+ Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty))
+ }
+ Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
+ Some(ty::Const::new_bound(
+ tcx,
+ debruijn,
+ ty::BoundVar::from_u32(index),
+ param_ty,
+ ))
+ }
+ Some(rbv::ResolvedArg::Error(guar)) => {
+ Some(ty::Const::new_error(tcx, guar, param_ty))
}
- Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
- ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
- param_ty,
- )),
- Some(rbv::ResolvedArg::Error(guar)) => Some(tcx.const_error(param_ty, guar)),
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
}
}
@@ -155,7 +269,8 @@ impl<'tcx> Const<'tcx> {
.layout_of(ty)
.unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
.size;
- tcx.mk_const(
+ ty::Const::new_value(
+ tcx,
ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()),
ty.value,
)
@@ -164,7 +279,7 @@ impl<'tcx> Const<'tcx> {
#[inline]
/// Creates an interned zst constant.
pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
- tcx.mk_const(ty::ValTree::zst(), ty)
+ ty::Const::new_value(tcx, ty::ValTree::zst(), ty)
}
#[inline]
@@ -192,12 +307,12 @@ impl<'tcx> Const<'tcx> {
assert_eq!(self.ty(), ty);
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
// if `ty` does not depend on generic parameters, use an empty param_env
- self.kind().eval(tcx, param_env).try_to_bits(size)
+ self.eval(tcx, param_env).try_to_bits(size)
}
#[inline]
pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
- self.kind().eval(tcx, param_env).try_to_bool()
+ self.eval(tcx, param_env).try_to_bool()
}
#[inline]
@@ -206,17 +321,17 @@ impl<'tcx> Const<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
) -> Option<u64> {
- self.kind().eval(tcx, param_env).try_to_target_usize(tcx)
+ self.eval(tcx, param_env).try_to_target_usize(tcx)
}
#[inline]
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
/// unevaluated constant.
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
- if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
+ if let Some(val) = self.try_eval_for_typeck(tcx, param_env) {
match val {
- Ok(val) => tcx.mk_const(val, self.ty()),
- Err(guar) => tcx.const_error(self.ty(), guar),
+ Ok(val) => ty::Const::new_value(tcx, val, self.ty()),
+ Err(guar) => ty::Const::new_error(tcx, guar, self.ty()),
}
} else {
// Either the constant isn't evaluatable or ValTree creation failed.
@@ -238,6 +353,138 @@ impl<'tcx> Const<'tcx> {
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
}
+ #[inline]
+ /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
+ /// return `None`.
+ // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
+ pub fn try_eval_for_mir(
+ self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
+ match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
+ Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
+ Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
+ Some(Err(e)) => Some(Err(e)),
+ None => None,
+ }
+ }
+
+ #[inline]
+ /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
+ /// return `None`.
+ // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
+ pub fn try_eval_for_typeck(
+ self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
+ match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
+ Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
+ Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
+ Some(Err(e)) => Some(Err(e)),
+ None => None,
+ }
+ }
+
+ #[inline]
+ fn try_eval_inner(
+ self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ eval_mode: EvalMode,
+ ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
+ assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
+ if let ConstKind::Unevaluated(unevaluated) = self.kind() {
+ use crate::mir::interpret::ErrorHandled;
+
+ // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
+ // also does later, but we want to do it before checking for
+ // inference variables.
+ // 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.
+
+ // 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, unevaluated).has_non_region_infer() {
+ tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
+ def: unevaluated.def,
+ substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
+ })
+ } else {
+ tcx.erase_regions(param_env)
+ .with_reveal_all_normalized(tcx)
+ .and(tcx.erase_regions(unevaluated))
+ };
+
+ // FIXME(eddyb) maybe the `const_eval_*` methods should take
+ // `ty::ParamEnvAnd` instead of having them separate.
+ let (param_env, unevaluated) = param_env_and.into_parts();
+ // try to resolve e.g. associated constants to their definition on an impl, and then
+ // evaluate the const.
+ match eval_mode {
+ EvalMode::Typeck => {
+ match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
+ // NOTE(eddyb) `val` contains no lifetimes/types/consts,
+ // and we use the original type, so nothing from `substs`
+ // (which may be identity substs, see above),
+ // can leak through `val` into the const we return.
+ Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
+ Err(ErrorHandled::TooGeneric) => None,
+ Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
+ }
+ }
+ EvalMode::Mir => {
+ match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
+ // NOTE(eddyb) `val` contains no lifetimes/types/consts,
+ // and we use the original type, so nothing from `substs`
+ // (which may be identity substs, see above),
+ // can leak through `val` into the const we return.
+ Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
+ Err(ErrorHandled::TooGeneric) => None,
+ Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
+ }
+ }
+ }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
+ if let ConstKind::Value(val) = self.kind() { Some(val) } else { None }
+ }
+
+ #[inline]
+ pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
+ self.try_to_value()?.try_to_scalar()
+ }
+
+ #[inline]
+ pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
+ self.try_to_value()?.try_to_scalar_int()
+ }
+
+ #[inline]
+ pub fn try_to_bits(self, size: Size) -> Option<u128> {
+ self.try_to_scalar_int()?.to_bits(size).ok()
+ }
+
+ #[inline]
+ pub fn try_to_bool(self) -> Option<bool> {
+ self.try_to_scalar_int()?.try_into().ok()
+ }
+
+ #[inline]
+ pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
+ self.try_to_value()?.try_to_target_usize(tcx)
+ }
+
pub fn is_ct_infer(self) -> bool {
matches!(self.kind(), ty::ConstKind::Infer(_))
}
@@ -254,5 +501,5 @@ pub fn const_param_default(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBind
"`const_param_default` expected a generic parameter with a constant"
),
};
- ty::EarlyBinder(Const::from_anon_const(tcx, default_def_id))
+ ty::EarlyBinder::bind(Const::from_anon_const(tcx, default_def_id))
}
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index d1dbc531e..1e43fab45 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -1,5 +1,6 @@
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::Float;
+use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_target::abi::Size;
use std::fmt;
@@ -113,6 +114,14 @@ impl std::fmt::Debug for ConstInt {
}
}
+impl IntoDiagnosticArg for ConstInt {
+ // FIXME this simply uses the Debug impl, but we could probably do better by converting both
+ // to an inherent method that returns `Cow`.
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(format!("{self:?}").into())
+ }
+}
+
/// The raw bytes of a simple value.
///
/// This is a packed struct in order to allow this type to be optimally embedded in enums
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 1dd4f8a24..a6bf74911 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,17 +1,11 @@
use super::Const;
use crate::mir;
-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, TypeVisitableExt};
+use crate::ty::subst::SubstsRef;
+use crate::ty::{self, List, Ty};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
-use rustc_target::abi::Size;
-
-use super::ScalarInt;
/// An unevaluated (potentially generic) constant used in the type-system.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
@@ -41,45 +35,6 @@ impl<'tcx> UnevaluatedConst<'tcx> {
}
}
-/// Represents a constant in Rust.
-#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
-#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
-#[derive(derive_more::From)]
-pub enum ConstKind<'tcx> {
- /// A const generic parameter.
- Param(ty::ParamConst),
-
- /// Infer the value of the const.
- Infer(InferConst<'tcx>),
-
- /// Bound const variable, used only when preparing a trait query.
- Bound(ty::DebruijnIndex, ty::BoundVar),
-
- /// A placeholder const - universally quantified higher-ranked const.
- Placeholder(ty::PlaceholderConst<'tcx>),
-
- /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
- /// variants when the code is monomorphic enough for that.
- Unevaluated(UnevaluatedConst<'tcx>),
-
- /// Used to hold computed value.
- Value(ty::ValTree<'tcx>),
-
- /// A placeholder for a const which could not be computed; this is
- /// propagated to avoid useless error messages.
- #[from(ignore)]
- Error(ErrorGuaranteed),
-
- /// Expr which contains an expression which has partially evaluated items.
- Expr(Expr<'tcx>),
-}
-
-impl<'tcx> From<ty::ConstVid<'tcx>> for ConstKind<'tcx> {
- fn from(const_vid: ty::ConstVid<'tcx>) -> Self {
- InferConst::Var(const_vid).into()
- }
-}
-
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
pub enum Expr<'tcx> {
@@ -93,39 +48,7 @@ pub enum Expr<'tcx> {
static_assert_size!(Expr<'_>, 24);
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(ConstKind<'_>, 32);
-
-impl<'tcx> ConstKind<'tcx> {
- #[inline]
- pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
- if let ConstKind::Value(val) = self { Some(val) } else { None }
- }
-
- #[inline]
- pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
- self.try_to_value()?.try_to_scalar()
- }
-
- #[inline]
- pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
- self.try_to_value()?.try_to_scalar_int()
- }
-
- #[inline]
- pub fn try_to_bits(self, size: Size) -> Option<u128> {
- self.try_to_scalar_int()?.to_bits(size).ok()
- }
-
- #[inline]
- pub fn try_to_bool(self) -> Option<bool> {
- self.try_to_scalar_int()?.try_into().ok()
- }
-
- #[inline]
- pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
- self.try_to_value()?.try_to_target_usize(tcx)
- }
-}
+static_assert_size!(super::ConstKind<'_>, 32);
/// An inference variable for a const, for use in const generics.
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
@@ -144,124 +67,3 @@ impl<CTX> HashStable<CTX> for InferConst<'_> {
}
}
}
-
-enum EvalMode {
- Typeck,
- Mir,
-}
-
-enum EvalResult<'tcx> {
- ValTree(ty::ValTree<'tcx>),
- ConstVal(ConstValue<'tcx>),
-}
-
-impl<'tcx> ConstKind<'tcx> {
- #[inline]
- /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
- /// unevaluated constant.
- pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
- self.try_eval_for_typeck(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value)
- }
-
- #[inline]
- /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
- /// return `None`.
- // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
- pub fn try_eval_for_mir(
- self,
- tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
- ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
- match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
- Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
- Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
- Some(Err(e)) => Some(Err(e)),
- None => None,
- }
- }
-
- #[inline]
- /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
- /// return `None`.
- // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
- pub fn try_eval_for_typeck(
- self,
- tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
- ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
- match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
- Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
- Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
- Some(Err(e)) => Some(Err(e)),
- None => None,
- }
- }
-
- #[inline]
- fn try_eval_inner(
- self,
- tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
- eval_mode: EvalMode,
- ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
- assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
- if let ConstKind::Unevaluated(unevaluated) = self {
- use crate::mir::interpret::ErrorHandled;
-
- // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
- // also does later, but we want to do it before checking for
- // inference variables.
- // 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.
-
- // 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, unevaluated).has_non_region_infer() {
- tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
- def: unevaluated.def,
- substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
- })
- } else {
- tcx.erase_regions(param_env)
- .with_reveal_all_normalized(tcx)
- .and(tcx.erase_regions(unevaluated))
- };
-
- // FIXME(eddyb) maybe the `const_eval_*` methods should take
- // `ty::ParamEnvAnd` instead of having them separate.
- let (param_env, unevaluated) = param_env_and.into_parts();
- // try to resolve e.g. associated constants to their definition on an impl, and then
- // evaluate the const.
- match eval_mode {
- EvalMode::Typeck => {
- match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
- // NOTE(eddyb) `val` contains no lifetimes/types/consts,
- // and we use the original type, so nothing from `substs`
- // (which may be identity substs, see above),
- // can leak through `val` into the const we return.
- Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
- Err(ErrorHandled::TooGeneric) => None,
- Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
- }
- }
- EvalMode::Mir => {
- match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
- // NOTE(eddyb) `val` contains no lifetimes/types/consts,
- // and we use the original type, so nothing from `substs`
- // (which may be identity substs, see above),
- // can leak through `val` into the const we return.
- Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
- Err(ErrorHandled::TooGeneric) => None,
- Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
- }
- }
- }
- } else {
- None
- }
- }
-}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 2bde55bc4..035e978f6 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -25,10 +25,10 @@ use crate::traits::solve::{
ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
};
use crate::ty::{
- self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
- GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
- PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
- TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
+ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind,
+ ImplPolarity, InferTy, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig,
+ Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind,
+ TyVid, TypeAndMut, Visibility,
};
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
use rustc_ast::{self as ast, attr};
@@ -70,10 +70,9 @@ use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}
use rustc_target::spec::abi;
use rustc_type_ir::sty::TyKind::*;
use rustc_type_ir::WithCachedTypeInfo;
-use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags};
+use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
use std::any::Any;
-use std::assert_matches::debug_assert_matches;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::fmt;
@@ -82,8 +81,6 @@ use std::iter;
use std::mem;
use std::ops::{Bound, Deref};
-const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
-
#[allow(rustc::usage_of_ty_tykind)]
impl<'tcx> Interner for TyCtxt<'tcx> {
type AdtDef = ty::AdtDef<'tcx>;
@@ -110,11 +107,29 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type PredicateKind = ty::PredicateKind<'tcx>;
type AllocId = crate::mir::interpret::AllocId;
+ type InferConst = ty::InferConst<'tcx>;
+ type AliasConst = ty::UnevaluatedConst<'tcx>;
+ type ParamConst = ty::ParamConst;
+ type BoundConst = ty::BoundVar;
+ type PlaceholderConst = ty::PlaceholderConst<'tcx>;
+ type ValueConst = ty::ValTree<'tcx>;
+ type ExprConst = ty::Expr<'tcx>;
+
type EarlyBoundRegion = ty::EarlyBoundRegion;
type BoundRegion = ty::BoundRegion;
type FreeRegion = ty::FreeRegion;
type RegionVid = ty::RegionVid;
type PlaceholderRegion = ty::PlaceholderRegion;
+
+ fn ty_and_mut_to_parts(
+ TypeAndMut { ty, mutbl }: TypeAndMut<'tcx>,
+ ) -> (Self::Ty, Self::Mutability) {
+ (ty, mutbl)
+ }
+
+ fn mutability_is_mut(mutbl: Self::Mutability) -> bool {
+ mutbl.is_mut()
+ }
}
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
@@ -133,7 +148,7 @@ pub struct CtxtInterners<'tcx> {
region: InternedSet<'tcx, RegionKind<'tcx>>,
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
- predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
+ clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
const_: InternedSet<'tcx, ConstData<'tcx>>,
@@ -158,7 +173,7 @@ impl<'tcx> CtxtInterners<'tcx> {
poly_existential_predicates: Default::default(),
canonical_var_infos: Default::default(),
predicate: Default::default(),
- predicates: Default::default(),
+ clauses: Default::default(),
projs: Default::default(),
place_elems: Default::default(),
const_: Default::default(),
@@ -312,6 +327,8 @@ pub struct CommonLifetimes<'tcx> {
pub struct CommonConsts<'tcx> {
pub unit: Const<'tcx>,
+ pub true_: Const<'tcx>,
+ pub false_: Const<'tcx>,
}
impl<'tcx> CommonTypes<'tcx> {
@@ -409,6 +426,14 @@ impl<'tcx> CommonConsts<'tcx> {
kind: ty::ConstKind::Value(ty::ValTree::zst()),
ty: types.unit,
}),
+ true_: mk_const(ty::ConstData {
+ kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE)),
+ ty: types.bool,
+ }),
+ false_: mk_const(ty::ConstData {
+ kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE)),
+ ty: types.bool,
+ }),
}
}
}
@@ -470,6 +495,17 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
/// [rustc dev guide] for more details.
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
+///
+/// An implementation detail: `TyCtxt` is a wrapper type for [GlobalCtxt],
+/// which is the struct that actually holds all the data. `TyCtxt` derefs to
+/// `GlobalCtxt`, and in practice `TyCtxt` is passed around everywhere, and all
+/// operations are done via `TyCtxt`. A `TyCtxt` is obtained for a `GlobalCtxt`
+/// by calling `enter` with a closure `f`. That function creates both the
+/// `TyCtxt`, and an `ImplicitCtxt` around it that is put into TLS. Within `f`:
+/// - The `ImplicitCtxt` is available implicitly via TLS.
+/// - The `TyCtxt` is available explicitly via the `tcx` parameter, and also
+/// implicitly within the `ImplicitCtxt`. Explicit access is preferred when
+/// possible.
#[derive(Copy, Clone)]
#[rustc_diagnostic_item = "TyCtxt"]
#[rustc_pass_by_value]
@@ -485,6 +521,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> {
}
}
+/// See [TyCtxt] for details about this type.
pub struct GlobalCtxt<'tcx> {
pub arena: &'tcx WorkerLocal<Arena<'tcx>>,
pub hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
@@ -689,82 +726,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
- #[track_caller]
- 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_misc(self) -> Ty<'tcx> {
- self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported")
- }
-
- /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
- /// ensure it gets used.
- #[track_caller]
- pub fn ty_error_with_message<S: Into<MultiSpan>>(
- self,
- span: S,
- msg: impl Into<DiagnosticMessage>,
- ) -> Ty<'tcx> {
- let reported = self.sess.delay_span_bug(span, msg);
- 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`
- #[track_caller]
- pub fn const_error(self, ty: Ty<'tcx>, reported: ErrorGuaranteed) -> Const<'tcx> {
- self.mk_const(ty::ConstKind::Error(reported), ty)
- }
-
- /// Like [TyCtxt::ty_error] but for constants.
- #[track_caller]
- pub fn const_error_misc(self, ty: Ty<'tcx>) -> Const<'tcx> {
- self.const_error_with_message(
- ty,
- DUMMY_SP,
- "ty::ConstKind::Error constructed but no error reported",
- )
- }
-
- /// Like [TyCtxt::ty_error_with_message] but for constants.
- #[track_caller]
- pub fn const_error_with_message<S: Into<MultiSpan>>(
- self,
- ty: Ty<'tcx>,
- span: S,
- msg: &str,
- ) -> Const<'tcx> {
- let reported = self.sess.delay_span_bug(span, msg);
- self.mk_const(ty::ConstKind::Error(reported), ty)
- }
-
pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
self.sess.consider_optimizing(|| self.crate_name(LOCAL_CRATE), msg)
}
@@ -1019,15 +980,6 @@ impl<'tcx> TyCtxt<'tcx> {
self.query_system.on_disk_cache.as_ref().map_or(Ok(0), |c| c.serialize(self, encoder))
}
- /// If `true`, we should use lazy normalization for constants, otherwise
- /// we still evaluate them eagerly.
- #[inline]
- pub fn lazy_normalization(self) -> bool {
- let features = self.features();
- // Note: We only use lazy normalization for generic const expressions.
- features.generic_const_exprs
- }
-
#[inline]
pub fn local_crate_exports_generics(self) -> bool {
debug_assert!(self.sess.opts.share_generics());
@@ -1167,7 +1119,8 @@ impl<'tcx> TyCtxt<'tcx> {
/// Returns `&'static core::panic::Location<'static>`.
pub fn caller_location_ty(self) -> Ty<'tcx> {
- self.mk_imm_ref(
+ Ty::new_imm_ref(
+ self,
self.lifetimes.re_static,
self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
.subst(self, self.mk_substs(&[self.lifetimes.re_static.into()])),
@@ -1192,14 +1145,6 @@ impl<'tcx> TyCtxt<'tcx> {
self.limits(()).move_size_limit
}
- pub fn const_eval_limit(self) -> 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 {
iter::once(LOCAL_CRATE)
.chain(self.crates(()).iter().copied())
@@ -1210,6 +1155,12 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
self.visibility(def_id).expect_local()
}
+
+ /// Returns the origin of the opaque type `def_id`.
+ #[instrument(skip(self), level = "trace", ret)]
+ pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin {
+ self.hir().expect_item(def_id).expect_opaque_ty().origin
+ }
}
/// A trait implemented for all `X<'a>` types that can be safely and
@@ -1272,10 +1223,11 @@ nop_lift! {region; Region<'a> => Region<'tcx>}
nop_lift! {const_; Const<'a> => Const<'tcx>}
nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
+nop_lift! {predicate; Clause<'a> => Clause<'tcx>}
nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>}
nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>}
-nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
+nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>}
nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
nop_list_lift! {projs; ProjectionKind => ProjectionKind}
nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
@@ -1515,9 +1467,9 @@ 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.
+// crate only, and have a corresponding `mk_` function.
direct_interners! {
- region: intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
+ region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>,
const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>,
@@ -1553,7 +1505,7 @@ slice_interners!(
type_lists: pub mk_type_list(Ty<'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>),
+ clauses: intern_clauses(Clause<'tcx>),
projs: pub mk_projs(ProjectionKind),
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
@@ -1566,7 +1518,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// unsafe.
pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
assert_eq!(sig.unsafety(), hir::Unsafety::Normal);
- self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }))
+ Ty::new_fn_ptr(
+ self,
+ sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }),
+ )
}
/// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
@@ -1585,7 +1540,7 @@ impl<'tcx> TyCtxt<'tcx> {
let future_trait = self.require_lang_item(LangItem::Future, None);
self.explicit_item_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| {
- let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else {
+ let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else {
return false;
};
trait_predicate.trait_ref.def_id == future_trait
@@ -1608,9 +1563,7 @@ impl<'tcx> TyCtxt<'tcx> {
let generic_predicates = self.super_predicates_of(trait_did);
for (predicate, _) in generic_predicates.predicates {
- if let ty::PredicateKind::Clause(ty::Clause::Trait(data)) =
- predicate.kind().skip_binder()
- {
+ if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() {
if set.insert(data.def_id()) {
stack.push(data.def_id());
}
@@ -1642,18 +1595,6 @@ impl<'tcx> TyCtxt<'tcx> {
})
}
- // Avoid this in favour of more specific `mk_*` methods, where possible.
- #[allow(rustc::usage_of_ty_tykind)]
- #[inline]
- pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> {
- self.interners.intern_ty(
- st,
- self.sess,
- // This is only used to create a stable hashing context.
- &self.untracked,
- )
- }
-
#[inline]
pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
self.interners.intern_predicate(
@@ -1673,174 +1614,6 @@ impl<'tcx> TyCtxt<'tcx> {
if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
}
- pub fn mk_mach_int(self, tm: IntTy) -> Ty<'tcx> {
- match tm {
- IntTy::Isize => self.types.isize,
- IntTy::I8 => self.types.i8,
- IntTy::I16 => self.types.i16,
- IntTy::I32 => self.types.i32,
- IntTy::I64 => self.types.i64,
- IntTy::I128 => self.types.i128,
- }
- }
-
- pub fn mk_mach_uint(self, tm: UintTy) -> Ty<'tcx> {
- match tm {
- UintTy::Usize => self.types.usize,
- UintTy::U8 => self.types.u8,
- UintTy::U16 => self.types.u16,
- UintTy::U32 => self.types.u32,
- UintTy::U64 => self.types.u64,
- UintTy::U128 => self.types.u128,
- }
- }
-
- pub fn mk_mach_float(self, tm: FloatTy) -> Ty<'tcx> {
- match tm {
- FloatTy::F32 => self.types.f32,
- FloatTy::F64 => self.types.f64,
- }
- }
-
- #[inline]
- pub fn mk_static_str(self) -> Ty<'tcx> {
- self.mk_imm_ref(self.lifetimes.re_static, self.types.str_)
- }
-
- #[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_from_kind(Adt(def, substs))
- }
-
- #[inline]
- pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> {
- self.mk_ty_from_kind(Foreign(def_id))
- }
-
- fn mk_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
- let adt_def = self.adt_def(wrapper_def_id);
- let substs =
- InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind {
- GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
- GenericParamDefKind::Type { has_default, .. } => {
- if param.index == 0 {
- ty_param.into()
- } else {
- assert!(has_default);
- self.type_of(param.def_id).subst(self, substs).into()
- }
- }
- });
- self.mk_ty_from_kind(Adt(adt_def, substs))
- }
-
- #[inline]
- pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- let def_id = self.require_lang_item(LangItem::OwnedBox, None);
- self.mk_generic_adt(def_id, ty)
- }
-
- #[inline]
- pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
- let def_id = self.lang_items().get(item)?;
- Some(self.mk_generic_adt(def_id, ty))
- }
-
- #[inline]
- pub fn mk_diagnostic_item(self, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
- let def_id = self.get_diagnostic_item(name)?;
- Some(self.mk_generic_adt(def_id, ty))
- }
-
- #[inline]
- pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- let def_id = self.require_lang_item(LangItem::MaybeUninit, None);
- self.mk_generic_adt(def_id, ty)
- }
-
- #[inline]
- pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
- self.mk_ty_from_kind(RawPtr(tm))
- }
-
- #[inline]
- pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
- self.mk_ty_from_kind(Ref(r, tm.ty, tm.mutbl))
- }
-
- #[inline]
- pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
- }
-
- #[inline]
- pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Not })
- }
-
- #[inline]
- pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Mut })
- }
-
- #[inline]
- pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not })
- }
-
- #[inline]
- pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
- 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_from_kind(Slice(ty))
- }
-
- #[inline]
- 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_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]
- pub fn mk_unit(self) -> Ty<'tcx> {
- self.types.unit
- }
-
- #[inline]
- pub fn mk_diverging_default(self) -> Ty<'tcx> {
- if self.features().never_type_fallback { self.types.never } else { self.types.unit }
- }
-
- #[inline]
- pub fn mk_fn_def(
- self,
- def_id: DefId,
- substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
- ) -> Ty<'tcx> {
- let substs = self.check_and_mk_substs(def_id, substs);
- self.mk_ty_from_kind(FnDef(def_id, substs))
- }
-
#[inline(always)]
pub(crate) fn check_and_mk_substs(
self,
@@ -1872,222 +1645,36 @@ impl<'tcx> TyCtxt<'tcx> {
}
#[inline]
- pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
- self.mk_ty_from_kind(FnPtr(fty))
- }
-
- #[inline]
- pub fn mk_dynamic(
- self,
- obj: &'tcx List<PolyExistentialPredicate<'tcx>>,
- reg: ty::Region<'tcx>,
- repr: DynKind,
- ) -> Ty<'tcx> {
- self.mk_ty_from_kind(Dynamic(obj, reg, repr))
- }
-
- #[inline]
- pub fn mk_projection(
- self,
- item_def_id: DefId,
- substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
- ) -> Ty<'tcx> {
- 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_from_kind(Closure(closure_id, closure_substs))
- }
-
- #[inline]
- pub fn mk_generator(
- self,
- id: DefId,
- generator_substs: SubstsRef<'tcx>,
- movability: hir::Movability,
- ) -> Ty<'tcx> {
- 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_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.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_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.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_from_kind(Infer(IntVar(v)))
- }
-
- #[inline]
- pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> {
- 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_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))))
+ pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ self.intern_const(ty::ConstData { kind, ty })
}
+ // Avoid this in favour of more specific `Ty::new_*` methods, where possible.
+ #[allow(rustc::usage_of_ty_tykind)]
#[inline]
- pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> {
- self.mk_ty_from_kind(Param(ParamTy { index, name }))
+ pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> {
+ self.interners.intern_ty(
+ st,
+ self.sess,
+ // This is only used to create a stable hashing context.
+ &self.untracked,
+ )
}
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
match param.kind {
GenericParamDefKind::Lifetime => {
- 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)
- .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> {
- debug_assert_matches!(
- (kind, self.def_kind(alias_ty.def_id)),
- (ty::Opaque, DefKind::OpaqueTy)
- | (ty::Projection | ty::Inherent, DefKind::AssocTy)
- | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder)
- );
- 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_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(None) } = bound_region
- && let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
- && let Some(re) = inner.get(var.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::Region::new_early_bound(self, param.to_early_bound_region_data()).into()
}
- 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),
+ GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(),
+ GenericParamDefKind::Const { .. } => ty::Const::new_param(
+ self,
+ ParamConst { index: param.index, name: param.name },
+ self.type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ )
+ .into(),
}
}
@@ -2146,11 +1733,11 @@ impl<'tcx> TyCtxt<'tcx> {
self.intern_poly_existential_predicates(eps)
}
- pub fn mk_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
+ pub fn mk_clauses(self, clauses: &[Clause<'tcx>]) -> &'tcx List<Clause<'tcx>> {
// FIXME consider asking the input slice to be sorted to avoid
// re-interning permutations, in which case that would be asserted
// here.
- self.intern_predicates(preds)
+ self.intern_clauses(clauses)
}
pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
@@ -2196,12 +1783,12 @@ impl<'tcx> TyCtxt<'tcx> {
T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs))
}
- pub fn mk_predicates_from_iter<I, T>(self, iter: I) -> T::Output
+ pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output
where
I: Iterator<Item = T>,
- T: CollectAndApply<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>,
+ T: CollectAndApply<Clause<'tcx>, &'tcx List<Clause<'tcx>>>,
{
- T::collect_and_apply(iter, |xs| self.mk_predicates(xs))
+ T::collect_and_apply(iter, |xs| self.mk_clauses(xs))
}
pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output
@@ -2403,10 +1990,18 @@ impl<'tcx> TyCtxt<'tcx> {
self.opt_local_def_id_to_hir_id(local_def_id).unwrap()
}
- pub fn trait_solver_next(self) -> bool {
+ pub fn next_trait_solver_globally(self) -> bool {
self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
}
+ pub fn next_trait_solver_in_coherence(self) -> bool {
+ matches!(
+ self.sess.opts.unstable_opts.trait_solver,
+ rustc_session::config::TraitSolver::Next
+ | rustc_session::config::TraitSolver::NextCoherence
+ )
+ }
+
pub fn lower_impl_trait_in_trait_to_assoc_ty(self) -> bool {
self.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
}
@@ -2433,21 +2028,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
-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_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
- /// ensure it gets used.
- #[track_caller]
- pub fn ty_error_with_message(self, msg: impl Into<DiagnosticMessage>) -> Ty<'tcx> {
- self.tcx.ty_error_with_message(self.span, msg)
- }
-}
-
/// Parameter attributes that can only be determined by examining the body of a function instead
/// of just its signature.
///
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 6a29063b8..a0b17c374 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -1,5 +1,6 @@
//! Diagnostics related methods for `Ty`.
+use std::borrow::Cow;
use std::ops::ControlFlow;
use crate::ty::{
@@ -13,8 +14,8 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnostic
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
-use rustc_hir::WherePredicate;
-use rustc_span::Span;
+use rustc_hir::{PredicateOrigin, WherePredicate};
+use rustc_span::{BytePos, Span};
use rustc_type_ir::sty::TyKind::*;
impl<'tcx> IntoDiagnosticArg for Ty<'tcx> {
@@ -155,10 +156,11 @@ enum SuggestChangingConstraintsMessage<'a> {
RestrictBoundFurther,
RestrictType { ty: &'a str },
RestrictTypeFurther { ty: &'a str },
- RemovingQSized,
+ RemoveMaybeUnsized,
+ ReplaceMaybeUnsizedWithSized,
}
-fn suggest_removing_unsized_bound(
+fn suggest_changing_unsized_bound(
generics: &hir::Generics<'_>,
suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>,
param: &hir::GenericParam<'_>,
@@ -182,12 +184,25 @@ fn suggest_removing_unsized_bound(
if poly.trait_ref.trait_def_id() != def_id {
continue;
}
- let sp = generics.span_for_bound_removal(where_pos, pos);
- suggestions.push((
- sp,
- String::new(),
- SuggestChangingConstraintsMessage::RemovingQSized,
- ));
+ if predicate.origin == PredicateOrigin::ImplTrait && predicate.bounds.len() == 1 {
+ // For `impl ?Sized` with no other bounds, suggest `impl Sized` instead.
+ let bound_span = bound.span();
+ if bound_span.can_be_used_for_suggestions() {
+ let question_span = bound_span.with_hi(bound_span.lo() + BytePos(1));
+ suggestions.push((
+ question_span,
+ String::new(),
+ SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized,
+ ));
+ }
+ } else {
+ let sp = generics.span_for_bound_removal(where_pos, pos);
+ suggestions.push((
+ sp,
+ String::new(),
+ SuggestChangingConstraintsMessage::RemoveMaybeUnsized,
+ ));
+ }
}
}
}
@@ -236,15 +251,12 @@ pub fn suggest_constraining_type_params<'a>(
{
let mut sized_constraints =
- constraints.drain_filter(|(_, def_id)| *def_id == tcx.lang_items().sized_trait());
- if let Some((constraint, def_id)) = sized_constraints.next() {
+ constraints.extract_if(|(_, def_id)| *def_id == tcx.lang_items().sized_trait());
+ if let Some((_, def_id)) = sized_constraints.next() {
applicability = Applicability::MaybeIncorrect;
- err.span_label(
- param.span,
- format!("this type parameter needs to be `{}`", constraint),
- );
- suggest_removing_unsized_bound(generics, &mut suggestions, param, def_id);
+ err.span_label(param.span, "this type parameter needs to be `Sized`");
+ suggest_changing_unsized_bound(generics, &mut suggestions, param, def_id);
}
}
@@ -384,22 +396,21 @@ pub fn suggest_constraining_type_params<'a>(
if suggestions.len() == 1 {
let (span, suggestion, msg) = suggestions.pop().unwrap();
-
- let s;
let msg = match msg {
SuggestChangingConstraintsMessage::RestrictBoundFurther => {
- "consider further restricting this bound"
+ Cow::from("consider further restricting this bound")
}
SuggestChangingConstraintsMessage::RestrictType { ty } => {
- s = format!("consider restricting type parameter `{}`", ty);
- &s
+ Cow::from(format!("consider restricting type parameter `{}`", ty))
}
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
- s = format!("consider further restricting type parameter `{}`", ty);
- &s
+ Cow::from(format!("consider further restricting type parameter `{}`", ty))
+ }
+ SuggestChangingConstraintsMessage::RemoveMaybeUnsized => {
+ Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`")
}
- SuggestChangingConstraintsMessage::RemovingQSized => {
- "consider removing the `?Sized` bound to make the type parameter `Sized`"
+ SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized => {
+ Cow::from("consider replacing `?Sized` with `Sized`")
}
};
@@ -548,7 +559,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> {
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))
+ Ty::new_fn_ptr(self.tcx, self.tcx.fn_sig(def_id).subst(self.tcx, substs))
}
// FIXME(compiler-errors): We could replace these with infer, I guess.
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 49ab9b79e..c794c3fad 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -45,7 +45,6 @@ pub enum TypeError<'tcx> {
RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>),
- RegionsOverlyPolymorphic(BoundRegionKind, Region<'tcx>),
RegionsPlaceholderMismatch,
Sorts(ExpectedFound<Ty<'tcx>>),
@@ -74,7 +73,6 @@ impl TypeError<'_> {
match self {
TypeError::RegionsDoesNotOutlive(_, _)
| TypeError::RegionsInsufficientlyPolymorphic(_, _)
- | TypeError::RegionsOverlyPolymorphic(_, _)
| TypeError::RegionsPlaceholderMismatch => true,
_ => false,
}
@@ -98,11 +96,6 @@ impl<'tcx> TypeError<'tcx> {
}
}
- let br_string = |br: ty::BoundRegionKind| match br {
- ty::BrNamed(_, name) => format!(" {}", name),
- _ => String::new(),
- };
-
match self {
CyclicTy(_) => "cyclic type of infinite size".into(),
CyclicConst(_) => "encountered a self-referencing constant".into(),
@@ -144,11 +137,6 @@ impl<'tcx> TypeError<'tcx> {
RegionsInsufficientlyPolymorphic(..) => {
"one type is more general than the other".into()
}
- RegionsOverlyPolymorphic(br, _) => format!(
- "expected concrete lifetime, found bound lifetime parameter{}",
- br_string(br)
- )
- .into(),
RegionsPlaceholderMismatch => "one type is more general than the other".into(),
ArgumentSorts(values, _) | Sorts(values) => {
let expected = values.expected.sort_string(tcx);
@@ -228,7 +216,6 @@ impl<'tcx> TypeError<'tcx> {
| FieldMisMatch(..)
| RegionsDoesNotOutlive(..)
| RegionsInsufficientlyPolymorphic(..)
- | RegionsOverlyPolymorphic(..)
| RegionsPlaceholderMismatch
| Traits(_)
| ProjectionMismatched(_)
@@ -313,6 +300,7 @@ impl<'tcx> Ty<'tcx> {
ty::Placeholder(..) => "higher-ranked type".into(),
ty::Bound(..) => "bound type variable".into(),
ty::Alias(ty::Projection | ty::Inherent, _) => "associated type".into(),
+ ty::Alias(ty::Weak, _) => "type alias".into(),
ty::Param(_) => "type parameter".into(),
ty::Alias(ty::Opaque, ..) => "opaque type".into(),
}
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index d64875a9f..ff3917947 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -178,7 +178,7 @@ impl FlagComputation {
&ty::Alias(kind, data) => {
self.add_flags(match kind {
- ty::Projection => TypeFlags::HAS_TY_PROJECTION,
+ ty::Weak | ty::Projection => TypeFlags::HAS_TY_PROJECTION,
ty::Inherent => TypeFlags::HAS_TY_INHERENT,
ty::Opaque => TypeFlags::HAS_TY_OPAQUE,
});
@@ -237,21 +237,24 @@ impl FlagComputation {
fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
match atom {
- ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
self.add_substs(trait_pred.trait_ref.substs);
}
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(a, b))) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
+ a,
+ b,
+ ))) => {
self.add_region(a);
self.add_region(b);
}
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
+ ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
ty,
region,
))) => {
self.add_ty(ty);
self.add_region(region);
}
- ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
self.add_const(ct);
self.add_ty(ty);
}
@@ -263,30 +266,27 @@ impl FlagComputation {
self.add_ty(a);
self.add_ty(b);
}
- ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_ty,
term,
})) => {
self.add_alias_ty(projection_ty);
self.add_term(term);
}
- ty::PredicateKind::WellFormed(arg) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
self.add_substs(slice::from_ref(&arg));
}
ty::PredicateKind::ObjectSafe(_def_id) => {}
ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => {
self.add_substs(substs);
}
- ty::PredicateKind::ConstEvaluatable(uv) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
self.add_const(uv);
}
ty::PredicateKind::ConstEquate(expected, found) => {
self.add_const(expected);
self.add_const(found);
}
- ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
- self.add_ty(ty);
- }
ty::PredicateKind::Ambiguous => {}
ty::PredicateKind::AliasRelate(t1, t2, _) => {
self.add_term(t1);
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 25890eb15..77cf6bee7 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -213,7 +213,7 @@ where
// debruijn index. Then we adjust it to the
// correct depth.
assert_eq!(debruijn1, ty::INNERMOST);
- self.tcx.mk_re_late_bound(debruijn, br)
+ ty::Region::new_late_bound(self.tcx, debruijn, br)
} else {
region
}
@@ -328,7 +328,7 @@ impl<'tcx> TyCtxt<'tcx> {
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.replace_late_bound_regions_uncached(value, |br| {
- self.mk_re_free(all_outlive_scope, br.kind)
+ ty::Region::new_free(self, all_outlive_scope, br.kind)
})
}
@@ -341,16 +341,21 @@ impl<'tcx> TyCtxt<'tcx> {
value,
FnMutDelegate {
regions: &mut |r: ty::BoundRegion| {
- self.mk_re_late_bound(
+ ty::Region::new_late_bound(
+ self,
ty::INNERMOST,
ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
)
},
types: &mut |t: ty::BoundTy| {
- self.mk_bound(ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind })
+ Ty::new_bound(
+ self,
+ 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)
+ ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c), ty)
},
},
)
@@ -383,7 +388,7 @@ impl<'tcx> TyCtxt<'tcx> {
.or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(None)))
.expect_region();
let br = ty::BoundRegion { var, kind };
- self.tcx.mk_re_late_bound(ty::INNERMOST, br)
+ ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br)
}
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
let entry = self.map.entry(bt.var);
@@ -392,14 +397,14 @@ impl<'tcx> TyCtxt<'tcx> {
let kind = entry
.or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon))
.expect_ty();
- self.tcx.mk_bound(ty::INNERMOST, BoundTy { var, kind })
+ Ty::new_bound(self.tcx, 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);
let index = entry.index();
let var = ty::BoundVar::from_usize(index);
let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const();
- self.tcx.mk_const(ty::ConstKind::Bound(ty::INNERMOST, var), ty)
+ ty::Const::new_bound(self.tcx, ty::INNERMOST, var, ty)
}
}
@@ -451,7 +456,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
match *r {
ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
let debruijn = debruijn.shifted_in(self.amount);
- self.tcx.mk_re_late_bound(debruijn, br)
+ ty::Region::new_late_bound(self.tcx, debruijn, br)
}
_ => r,
}
@@ -461,7 +466,7 @@ impl<'tcx> TypeFolder<TyCtxt<'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_bound(debruijn, bound_ty)
+ Ty::new_bound(self.tcx, debruijn, bound_ty)
}
_ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self),
@@ -474,7 +479,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
&& debruijn >= self.current_index
{
let debruijn = debruijn.shifted_in(self.amount);
- self.tcx.mk_const(ty::ConstKind::Bound(debruijn, bound_ct), ct.ty())
+ ty::Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty())
} else {
ct.super_fold_with(self)
}
@@ -492,7 +497,7 @@ pub fn shift_region<'tcx>(
) -> ty::Region<'tcx> {
match *region {
ty::ReLateBound(debruijn, br) if amount > 0 => {
- tcx.mk_re_late_bound(debruijn.shifted_in(amount), br)
+ ty::Region::new_late_bound(tcx, debruijn.shifted_in(amount), br)
}
_ => region,
}
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index b0ffe7829..6c7125c4c 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
-use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt};
+use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum GenericParamDefKind {
@@ -100,11 +100,13 @@ impl GenericParamDef {
preceding_substs: &[ty::GenericArg<'tcx>],
) -> ty::GenericArg<'tcx> {
match &self.kind {
- ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
- ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(),
- ty::GenericParamDefKind::Const { .. } => {
- tcx.const_error_misc(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
- }
+ ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(),
+ ty::GenericParamDefKind::Type { .. } => Ty::new_misc_error(tcx).into(),
+ ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error(
+ tcx,
+ tcx.type_of(self.def_id).subst(tcx, preceding_substs),
+ )
+ .into(),
}
}
}
@@ -133,6 +135,9 @@ pub struct Generics {
pub has_self: bool,
pub has_late_bound_regions: Option<Span>,
+
+ // The index of the host effect when substituted. (i.e. might be index to parent substs)
+ pub host_effect_index: Option<usize>,
}
impl<'tcx> Generics {
@@ -323,7 +328,7 @@ impl<'tcx> Generics {
#[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct GenericPredicates<'tcx> {
pub parent: Option<DefId>,
- pub predicates: &'tcx [(Predicate<'tcx>, Span)],
+ pub predicates: &'tcx [(Clause<'tcx>, Span)],
}
impl<'tcx> GenericPredicates<'tcx> {
@@ -341,9 +346,8 @@ impl<'tcx> GenericPredicates<'tcx> {
&self,
tcx: TyCtxt<'tcx>,
substs: SubstsRef<'tcx>,
- ) -> impl Iterator<Item = (Predicate<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
- {
- EarlyBinder(self.predicates).subst_iter_copied(tcx, substs)
+ ) -> impl Iterator<Item = (Clause<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator {
+ EarlyBinder::bind(self.predicates).subst_iter_copied(tcx, substs)
}
#[instrument(level = "debug", skip(self, tcx))]
@@ -358,7 +362,7 @@ impl<'tcx> GenericPredicates<'tcx> {
}
instantiated
.predicates
- .extend(self.predicates.iter().map(|(p, _)| EarlyBinder(*p).subst(tcx, substs)));
+ .extend(self.predicates.iter().map(|(p, _)| EarlyBinder::bind(*p).subst(tcx, substs)));
instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp));
}
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index ac42d6e05..295cb1464 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -62,7 +62,18 @@ impl<'tcx> InhabitedPredicate<'tcx> {
Some(1..) => Ok(false),
},
Self::NotInModule(id) => in_module(id).map(|in_mod| !in_mod),
- Self::GenericType(_) => Ok(true),
+ // `t` may be a projection, for which `inhabited_predicate` returns a `GenericType`. As
+ // we have a param_env available, we can do better.
+ Self::GenericType(t) => {
+ let normalized_pred = tcx
+ .try_normalize_erasing_regions(param_env, t)
+ .map_or(self, |t| t.inhabited_predicate(tcx));
+ match normalized_pred {
+ // We don't have more information than we started with, so consider inhabited.
+ Self::GenericType(_) => Ok(true),
+ pred => pred.apply_inner(tcx, param_env, in_module),
+ }
+ }
Self::And([a, b]) => try_and(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
Self::Or([a, b]) => try_or(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
}
@@ -158,8 +169,8 @@ impl<'tcx> InhabitedPredicate<'tcx> {
fn subst_opt(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Option<Self> {
match self {
Self::ConstIsZero(c) => {
- let c = ty::EarlyBinder(c).subst(tcx, substs);
- let pred = match c.kind().try_to_target_usize(tcx) {
+ let c = ty::EarlyBinder::bind(c).subst(tcx, substs);
+ let pred = match c.try_to_target_usize(tcx) {
Some(0) => Self::True,
Some(1..) => Self::False,
None => Self::ConstIsZero(c),
@@ -167,7 +178,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
Some(pred)
}
Self::GenericType(t) => {
- Some(ty::EarlyBinder(t).subst(tcx, substs).inhabited_predicate(tcx))
+ Some(ty::EarlyBinder::bind(t).subst(tcx, substs).inhabited_predicate(tcx))
}
Self::And(&[a, b]) => match a.subst_opt(tcx, substs) {
None => b.subst_opt(tcx, substs).map(|b| a.and(tcx, b)),
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 422350284..b92d84152 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -197,7 +197,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_target_usize(tcx) {
+ Array(ty, len) => match len.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 e641d1ef1..ae57e954f 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -410,8 +410,8 @@ impl<'tcx> Instance<'tcx> {
) -> Instance<'tcx> {
match ty::Instance::resolve(tcx, param_env, def_id, substs) {
Ok(Some(instance)) => instance,
- _ => bug!(
- "failed to resolve instance for {}",
+ instance => bug!(
+ "failed to resolve instance for {}: {instance:#?}",
tcx.def_path_str_with_substs(def_id, substs)
),
}
@@ -552,7 +552,7 @@ impl<'tcx> Instance<'tcx> {
tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER);
let def = ty::InstanceDef::ClosureOnceShim { call_once, track_caller };
- let self_ty = tcx.mk_closure(closure_did, substs);
+ let self_ty = Ty::new_closure(tcx, closure_did, substs);
let sig = substs.as_closure().sig();
let sig =
@@ -586,7 +586,7 @@ impl<'tcx> Instance<'tcx> {
if let Some(substs) = self.substs_for_mir_body() {
v.subst(tcx, substs)
} else {
- v.skip_binder()
+ v.subst_identity()
}
}
@@ -680,7 +680,7 @@ fn polymorphize<'tcx>(
if substs == polymorphized_substs {
ty
} else {
- self.tcx.mk_closure(def_id, polymorphized_substs)
+ Ty::new_closure(self.tcx, def_id, polymorphized_substs)
}
}
ty::Generator(def_id, substs, movability) => {
@@ -689,7 +689,7 @@ fn polymorphize<'tcx>(
if substs == polymorphized_substs {
ty
} else {
- self.tcx.mk_generator(def_id, polymorphized_substs, movability)
+ Ty::new_generator(self.tcx, def_id, polymorphized_substs, movability)
}
}
_ => ty.super_fold_with(self),
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index b5a743cfe..d95b05ef7 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,8 +1,9 @@
-use crate::fluent_generated as fluent;
+use crate::error::UnsupportedFnAbi;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::query::TyCtxtAt;
use crate::ty::normalize_erasing_regions::NormalizationError;
-use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::{self, ConstKind, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
+use rustc_error_messages::DiagnosticMessage;
use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
@@ -14,7 +15,7 @@ use rustc_target::abi::call::FnAbi;
use rustc_target::abi::*;
use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target};
-use std::cmp::{self};
+use std::cmp;
use std::fmt;
use std::num::NonZeroUsize;
use std::ops::Bound;
@@ -132,7 +133,7 @@ impl PrimitiveExt for Primitive {
F32 => tcx.types.f32,
F64 => tcx.types.f64,
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
- Pointer(_) => tcx.mk_mut_ptr(tcx.mk_unit()),
+ Pointer(_) => Ty::new_mut_ptr(tcx, Ty::new_unit(tcx)),
}
}
@@ -214,29 +215,29 @@ pub enum LayoutError<'tcx> {
Cycle,
}
-impl IntoDiagnostic<'_, !> for LayoutError<'_> {
- fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
- let mut diag = handler.struct_fatal("");
+impl<'tcx> LayoutError<'tcx> {
+ pub fn diagnostic_message(&self) -> DiagnosticMessage {
+ use crate::fluent_generated::*;
+ use LayoutError::*;
+ match self {
+ Unknown(_) => middle_unknown_layout,
+ SizeOverflow(_) => middle_values_too_big,
+ NormalizationFailure(_, _) => middle_cannot_be_normalized,
+ Cycle => middle_cycle,
+ }
+ }
+ pub fn into_diagnostic(self) -> crate::error::LayoutError<'tcx> {
+ use crate::error::LayoutError as E;
+ use LayoutError::*;
match self {
- LayoutError::Unknown(ty) => {
- diag.set_arg("ty", ty);
- diag.set_primary_message(fluent::middle_unknown_layout);
- }
- LayoutError::SizeOverflow(ty) => {
- diag.set_arg("ty", ty);
- 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(fluent::middle_cannot_be_normalized);
- }
- LayoutError::Cycle => {
- diag.set_primary_message(fluent::middle_cycle);
+ Unknown(ty) => E::Unknown { ty },
+ SizeOverflow(ty) => E::Overflow { ty },
+ NormalizationFailure(ty, e) => {
+ E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() }
}
+ Cycle => E::Cycle,
}
- diag
}
}
@@ -309,7 +310,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- ) -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
+ ) -> Result<SizeSkeleton<'tcx>, &'tcx LayoutError<'tcx>> {
debug_assert!(!ty.has_non_region_infer());
// First try computing a static layout.
@@ -317,7 +318,13 @@ impl<'tcx> SizeSkeleton<'tcx> {
Ok(layout) => {
return Ok(SizeSkeleton::Known(layout.size));
}
- Err(err) => err,
+ Err(err @ LayoutError::Unknown(_)) => err,
+ // We can't extract SizeSkeleton info from other layout errors
+ Err(
+ e @ LayoutError::Cycle
+ | e @ LayoutError::SizeOverflow(_)
+ | e @ LayoutError::NormalizationFailure(..),
+ ) => return Err(e),
};
match *ty.kind() {
@@ -330,11 +337,8 @@ impl<'tcx> SizeSkeleton<'tcx> {
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
}
_ => bug!(
- "SizeSkeleton::compute({}): layout errored ({}), yet \
- tail `{}` is not a type parameter or a projection",
- ty,
- err,
- tail
+ "SizeSkeleton::compute({ty}): layout errored ({err:?}), yet \
+ tail `{tail}` is not a type parameter or a projection",
),
}
}
@@ -349,13 +353,13 @@ impl<'tcx> SizeSkeleton<'tcx> {
let size = s
.bytes()
.checked_mul(c)
- .ok_or_else(|| LayoutError::SizeOverflow(ty))?;
+ .ok_or_else(|| &*tcx.arena.alloc(LayoutError::SizeOverflow(ty)))?;
return Ok(SizeSkeleton::Known(Size::from_bytes(size)));
}
let len = tcx.expand_abstract_consts(len);
let prev = ty::Const::from_target_usize(tcx, s.bytes());
let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else {
- return Err(LayoutError::SizeOverflow(ty));
+ return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
};
Ok(SizeSkeleton::Generic(gen_size))
}
@@ -363,7 +367,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
SizeSkeleton::Generic(g) => {
let len = tcx.expand_abstract_consts(len);
let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else {
- return Err(LayoutError::SizeOverflow(ty));
+ return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
};
Ok(SizeSkeleton::Generic(gen_size))
}
@@ -476,13 +480,11 @@ fn mul_sorted_consts<'tcx>(
b: ty::Const<'tcx>,
) -> Option<ty::Const<'tcx>> {
use crate::mir::BinOp::Mul;
- use ty::ConstKind::Expr;
- use ty::Expr::Binop;
let mut work = vec![a, b];
let mut done = vec![];
while let Some(n) = work.pop() {
- if let Expr(Binop(Mul, l, r)) = n.kind() {
+ if let ConstKind::Expr(ty::Expr::Binop(Mul, l, r)) = n.kind() {
work.push(l);
work.push(r)
} else {
@@ -513,7 +515,7 @@ fn mul_sorted_consts<'tcx>(
done.sort_unstable();
// create a single tree from the buffer
- done.into_iter().reduce(|acc, n| tcx.mk_const(Expr(Binop(Mul, n, acc)), n.ty()))
+ done.into_iter().reduce(|acc, n| ty::Const::new_expr(tcx, ty::Expr::Binop(Mul, n, acc), n.ty()))
}
pub trait HasTyCtxt<'tcx>: HasDataLayout {
@@ -668,7 +670,7 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
MaybeResult::from(
tcx.layout_of(self.param_env().and(ty))
- .map_err(|err| self.handle_layout_err(err, span, ty)),
+ .map_err(|err| self.handle_layout_err(*err, span, ty)),
)
}
}
@@ -676,16 +678,21 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
impl<'tcx, C: LayoutOfHelpers<'tcx>> LayoutOf<'tcx> for C {}
impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
- type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+ type LayoutOfResult = Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>>;
#[inline]
- fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
- err
+ fn handle_layout_err(
+ &self,
+ err: LayoutError<'tcx>,
+ _: Span,
+ _: Ty<'tcx>,
+ ) -> &'tcx LayoutError<'tcx> {
+ self.tcx.arena.alloc(err)
}
}
impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> {
- type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+ type LayoutOfResult = Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>>;
#[inline]
fn layout_tcx_at_span(&self) -> Span {
@@ -693,8 +700,13 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> {
}
#[inline]
- fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
- err
+ fn handle_layout_err(
+ &self,
+ err: LayoutError<'tcx>,
+ _: Span,
+ _: Ty<'tcx>,
+ ) -> &'tcx LayoutError<'tcx> {
+ self.tcx.arena.alloc(err)
}
}
@@ -798,11 +810,11 @@ where
// (which may have no non-DST form), and will work as long
// as the `Abi` or `FieldsShape` is checked by users.
if i == 0 {
- let nil = tcx.mk_unit();
+ let nil = Ty::new_unit(tcx);
let unit_ptr_ty = if this.ty.is_unsafe_ptr() {
- tcx.mk_mut_ptr(nil)
+ Ty::new_mut_ptr(tcx, nil)
} else {
- tcx.mk_mut_ref(tcx.lifetimes.re_static, nil)
+ Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, nil)
};
// NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing
@@ -815,7 +827,11 @@ where
}
let mk_dyn_vtable = || {
- tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3))
+ Ty::new_imm_ref(
+ tcx,
+ tcx.lifetimes.re_static,
+ Ty::new_array(tcx, tcx.types.usize, 3),
+ )
/* FIXME: use actual fn pointers
Warning: naively computing the number of entries in the
vtable by counting the methods on the trait + methods on
@@ -824,9 +840,9 @@ where
Increase this counter if you tried to implement this but
failed to do it without duplicating a lot of code from
other places in the compiler: 2
- tcx.mk_tup(&[
- tcx.mk_array(tcx.types.usize, 3),
- tcx.mk_array(Option<fn()>),
+ Ty::new_tup(tcx,&[
+ Ty::new_array(tcx,tcx.types.usize, 3),
+ Ty::new_array(tcx,Option<fn()>),
])
*/
};
@@ -838,7 +854,7 @@ where
{
let metadata = tcx.normalize_erasing_regions(
cx.param_env(),
- tcx.mk_projection(metadata_def_id, [pointee]),
+ Ty::new_projection(tcx,metadata_def_id, [pointee]),
);
// Map `Metadata = DynMetadata<dyn Trait>` back to a vtable, since it
@@ -913,15 +929,14 @@ where
ty::Dynamic(_, _, ty::DynStar) => {
if i == 0 {
- TyMaybeWithLayout::Ty(tcx.mk_mut_ptr(tcx.types.unit))
+ TyMaybeWithLayout::Ty(Ty::new_mut_ptr(tcx, tcx.types.unit))
} else if i == 1 {
// FIXME(dyn-star) same FIXME as above applies here too
- TyMaybeWithLayout::Ty(
- tcx.mk_imm_ref(
- tcx.lifetimes.re_static,
- tcx.mk_array(tcx.types.usize, 3),
- ),
- )
+ TyMaybeWithLayout::Ty(Ty::new_imm_ref(
+ tcx,
+ tcx.lifetimes.re_static,
+ Ty::new_array(tcx, tcx.types.usize, 3),
+ ))
} else {
bug!("no field {i} on dyn*")
}
@@ -940,12 +955,8 @@ where
TyMaybeWithLayout::Ty(field_ty) => {
cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| {
bug!(
- "failed to get layout for `{}`: {},\n\
- despite it being a field (#{}) of an existing layout: {:#?}",
- field_ty,
- e,
- i,
- this
+ "failed to get layout for `{field_ty}`: {e:?},\n\
+ despite it being a field (#{i}) of an existing layout: {this:#?}",
)
})
}
@@ -970,10 +981,8 @@ where
})
}
ty::FnPtr(fn_sig) if offset.bytes() == 0 => {
- tcx.layout_of(param_env.and(tcx.mk_fn_ptr(fn_sig))).ok().map(|layout| PointeeInfo {
- size: layout.size,
- align: layout.align.abi,
- safe: None,
+ tcx.layout_of(param_env.and(Ty::new_fn_ptr(tcx, fn_sig))).ok().map(|layout| {
+ PointeeInfo { size: layout.size, align: layout.align.abi, safe: None }
})
}
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
@@ -1101,12 +1110,11 @@ where
///
/// This takes two primary parameters:
///
-/// * `codegen_fn_attr_flags` - these are flags calculated as part of the
-/// codegen attrs for a defined function. For function pointers this set of
-/// flags is the empty set. This is only applicable for Rust-defined
-/// functions, and generally isn't needed except for small optimizations where
-/// we try to say a function which otherwise might look like it could unwind
-/// doesn't actually unwind (such as for intrinsics and such).
+/// * `fn_def_id` - the `DefId` of the function. If this is provided then we can
+/// determine more precisely if the function can unwind. If this is not provided
+/// then we will only infer whether the function can unwind or not based on the
+/// ABI of the function. For example, a function marked with `#[rustc_nounwind]`
+/// is known to not unwind even if it's using Rust ABI.
///
/// * `abi` - this is the ABI that the function is defined with. This is the
/// primary factor for determining whether a function can unwind or not.
@@ -1138,11 +1146,6 @@ where
/// aborts the process.
/// * This affects whether functions have the LLVM `nounwind` attribute, which
/// affects various optimizations and codegen.
-///
-/// FIXME: this is actually buggy with respect to Rust functions. Rust functions
-/// compiled with `-Cpanic=unwind` and referenced from another crate compiled
-/// with `-Cpanic=abort` will look like they can't unwind when in fact they
-/// might (from a foreign exception or similar).
#[inline]
#[tracing::instrument(level = "debug", skip(tcx))]
pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
@@ -1250,33 +1253,18 @@ pub enum FnAbiError<'tcx> {
AdjustForForeignAbi(call::AdjustForForeignAbiError),
}
-impl<'tcx> From<LayoutError<'tcx>> for FnAbiError<'tcx> {
- fn from(err: LayoutError<'tcx>) -> Self {
- Self::Layout(err)
- }
-}
-
-impl From<call::AdjustForForeignAbiError> for FnAbiError<'_> {
- fn from(err: call::AdjustForForeignAbiError) -> Self {
- Self::AdjustForForeignAbi(err)
- }
-}
-
-impl<'tcx> fmt::Display for FnAbiError<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl<'a, 'b> IntoDiagnostic<'a, !> for FnAbiError<'b> {
+ fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
match self {
- Self::Layout(err) => err.fmt(f),
- Self::AdjustForForeignAbi(err) => err.fmt(f),
+ Self::Layout(e) => e.into_diagnostic().into_diagnostic(handler),
+ Self::AdjustForForeignAbi(call::AdjustForForeignAbiError::Unsupported {
+ arch,
+ abi,
+ }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(handler),
}
}
}
-impl IntoDiagnostic<'_, !> for FnAbiError<'_> {
- fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
- handler.struct_fatal(self.to_string())
- }
-}
-
// FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not
// just for error handling.
#[derive(Debug)]
@@ -1324,7 +1312,7 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
let tcx = self.tcx().at(span);
MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err(
- |err| self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
+ |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
))
}
@@ -1351,7 +1339,11 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
// However, we don't do this early in order to avoid calling
// `def_span` unconditionally (which may have a perf penalty).
let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
- self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args })
+ self.handle_fn_abi_err(
+ *err,
+ span,
+ FnAbiRequest::OfInstance { instance, extra_args },
+ )
}),
)
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a8d0dca37..aa8bfd317 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -53,7 +53,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ExpnId, ExpnKind, Span};
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions};
-use rustc_type_ir::WithCachedTypeInfo;
pub use subst::*;
pub use vtable::*;
@@ -67,6 +66,10 @@ use std::{fmt, str};
pub use crate::ty::diagnostics::*;
pub use rustc_type_ir::AliasKind::*;
+pub use rustc_type_ir::ConstKind::{
+ Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt,
+ Placeholder as PlaceholderCt, Unevaluated, Value,
+};
pub use rustc_type_ir::DynKind::*;
pub use rustc_type_ir::InferTy::*;
pub use rustc_type_ir::RegionKind::*;
@@ -82,7 +85,7 @@ pub use self::closure::{
CAPTURE_STRUCT_LOCAL,
};
pub use self::consts::{
- Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
+ Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
};
pub use self::context::{
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
@@ -94,7 +97,7 @@ pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::BoundRegionKind::*;
pub use self::sty::{
AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
- BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
+ BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstKind, ConstVid,
EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
@@ -145,6 +148,7 @@ mod opaque_types;
mod parameterized;
mod rvalue_scopes;
mod structural_impls;
+#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
mod sty;
mod typeck_results;
@@ -456,6 +460,11 @@ impl ty::EarlyBoundRegion {
}
}
+/// A statement that can be proven by a trait solver. This includes things that may
+/// show up in where clauses, such as trait predicates and projection predicates,
+/// and also things that are emitted as part of type checking such as `ObjectSafe`
+/// predicate which is emitted when a type is coerced to a trait object.
+///
/// Use this rather than `PredicateKind`, whenever possible.
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
@@ -487,11 +496,11 @@ impl<'tcx> Predicate<'tcx> {
let kind = self
.kind()
.map_bound(|kind| match kind {
- PredicateKind::Clause(Clause::Trait(TraitPredicate {
+ PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
trait_ref,
constness,
polarity,
- })) => Some(PredicateKind::Clause(Clause::Trait(TraitPredicate {
+ })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
trait_ref,
constness,
polarity: polarity.flip()?,
@@ -505,10 +514,10 @@ impl<'tcx> Predicate<'tcx> {
}
pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self {
- if let PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder()
+ if let PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder()
&& constness != BoundConstness::NotConst
{
- self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(Clause::Trait(TraitPredicate {
+ self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
trait_ref,
constness: BoundConstness::NotConst,
polarity,
@@ -520,10 +529,10 @@ impl<'tcx> Predicate<'tcx> {
#[instrument(level = "debug", skip(tcx), ret)]
pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool {
match self.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
tcx.trait_is_coinductive(data.def_id())
}
- ty::PredicateKind::WellFormed(_) => true,
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => true,
_ => false,
}
}
@@ -536,21 +545,20 @@ impl<'tcx> Predicate<'tcx> {
#[inline]
pub fn allow_normalization(self) -> bool {
match self.kind().skip_binder() {
- PredicateKind::WellFormed(_) => false,
- PredicateKind::Clause(Clause::Trait(_))
- | PredicateKind::Clause(Clause::RegionOutlives(_))
- | PredicateKind::Clause(Clause::TypeOutlives(_))
- | PredicateKind::Clause(Clause::Projection(_))
- | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ PredicateKind::Clause(ClauseKind::WellFormed(_)) => false,
+ PredicateKind::Clause(ClauseKind::Trait(_))
+ | PredicateKind::Clause(ClauseKind::RegionOutlives(_))
+ | PredicateKind::Clause(ClauseKind::TypeOutlives(_))
+ | PredicateKind::Clause(ClauseKind::Projection(_))
+ | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::ObjectSafe(_)
| PredicateKind::ClosureKind(_, _, _)
| PredicateKind::Subtype(_)
| PredicateKind::Coerce(_)
- | PredicateKind::ConstEvaluatable(_)
+ | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
| PredicateKind::ConstEquate(_, _)
- | PredicateKind::Ambiguous
- | PredicateKind::TypeWellFormedFromEnv(_) => true,
+ | PredicateKind::Ambiguous => true,
}
}
}
@@ -561,11 +569,77 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
}
}
+impl rustc_errors::IntoDiagnosticArg for Clause<'_> {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
+ }
+}
+
+/// A subset of predicates which can be assumed by the trait solver. They show up in
+/// an item's where clauses, hence the name `Clause`, and may either be user-written
+/// (such as traits) or may be inserted during lowering.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
+#[rustc_pass_by_value]
+pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>);
+
+impl<'tcx> Clause<'tcx> {
+ pub fn as_predicate(self) -> Predicate<'tcx> {
+ Predicate(self.0)
+ }
+
+ pub fn kind(self) -> Binder<'tcx, ClauseKind<'tcx>> {
+ self.0.internee.map_bound(|kind| match kind {
+ PredicateKind::Clause(clause) => clause,
+ _ => unreachable!(),
+ })
+ }
+
+ pub fn as_trait_clause(self) -> Option<Binder<'tcx, TraitPredicate<'tcx>>> {
+ let clause = self.kind();
+ if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() {
+ Some(clause.rebind(trait_clause))
+ } else {
+ None
+ }
+ }
+
+ pub fn as_projection_clause(self) -> Option<Binder<'tcx, ProjectionPredicate<'tcx>>> {
+ let clause = self.kind();
+ if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() {
+ Some(clause.rebind(projection_clause))
+ } else {
+ None
+ }
+ }
+
+ pub fn as_type_outlives_clause(self) -> Option<Binder<'tcx, TypeOutlivesPredicate<'tcx>>> {
+ let clause = self.kind();
+ if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() {
+ Some(clause.rebind(o))
+ } else {
+ None
+ }
+ }
+
+ pub fn as_region_outlives_clause(self) -> Option<Binder<'tcx, RegionOutlivesPredicate<'tcx>>> {
+ let clause = self.kind();
+ if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() {
+ Some(clause.rebind(o))
+ } else {
+ None
+ }
+ }
+
+ pub fn without_const(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ self.as_predicate().without_const(tcx).expect_clause()
+ }
+}
+
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
/// A clause is something that can appear in where bounds or be inferred
/// by implied bounds.
-pub enum Clause<'tcx> {
+pub enum ClauseKind<'tcx> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
/// would be the type parameters.
@@ -584,16 +658,19 @@ pub enum Clause<'tcx> {
/// Ensures that a const generic argument to a parameter `const N: u8`
/// is of type `u8`.
ConstArgHasType(Const<'tcx>, Ty<'tcx>),
+
+ /// No syntax: `T` well-formed.
+ WellFormed(GenericArg<'tcx>),
+
+ /// Constant initializer must evaluate successfully.
+ ConstEvaluatable(ty::Const<'tcx>),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub enum PredicateKind<'tcx> {
/// Prove a clause
- Clause(Clause<'tcx>),
-
- /// No syntax: `T` well-formed.
- WellFormed(GenericArg<'tcx>),
+ Clause(ClauseKind<'tcx>),
/// Trait must be object-safe.
ObjectSafe(DefId),
@@ -620,22 +697,14 @@ pub enum PredicateKind<'tcx> {
/// logic.
Coerce(CoercePredicate<'tcx>),
- /// Constant initializer must evaluate successfully.
- ConstEvaluatable(ty::Const<'tcx>),
-
/// Constants must be equal. The first component is the const that is expected.
ConstEquate(Const<'tcx>, Const<'tcx>),
- /// Represents a type found in the environment that we can use for implied bounds.
- ///
- /// Only used for Chalk.
- TypeWellFormedFromEnv(Ty<'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.
+ /// Separate from `ClauseKind::Projection` which is used for normalization in new solver.
/// This predicate requires two terms to be equal to eachother.
///
/// Only used for new solver
@@ -672,7 +741,7 @@ pub struct CratePredicatesMap<'tcx> {
pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
}
-impl<'tcx> Predicate<'tcx> {
+impl<'tcx> Clause<'tcx> {
/// Performs a substitution suitable for going from a
/// poly-trait-ref to supertraits that must hold if that
/// poly-trait-ref holds. This is slightly different from a normal
@@ -682,7 +751,7 @@ impl<'tcx> Predicate<'tcx> {
self,
tcx: TyCtxt<'tcx>,
trait_ref: &ty::PolyTraitRef<'tcx>,
- ) -> Predicate<'tcx> {
+ ) -> Clause<'tcx> {
// The interaction between HRTB and supertraits is not entirely
// obvious. Let me walk you (and myself) through an example.
//
@@ -764,11 +833,17 @@ impl<'tcx> Predicate<'tcx> {
let shifted_pred =
tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
// 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
- let new = EarlyBinder(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
+ let new = EarlyBinder::bind(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
// 3) ['x] + ['b] -> ['x, 'b]
let 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))
+
+ // FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here?
+ tcx.reuse_or_mk_predicate(
+ self.as_predicate(),
+ ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
+ )
+ .expect_clause()
}
}
@@ -1189,13 +1264,41 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
}
}
-impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self)))
}
}
+impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause))
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ self.as_predicate()
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause()
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause()
+ }
+}
+
impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
@@ -1203,6 +1306,29 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
}
}
+impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> {
+ self.without_const()
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ let p: Predicate<'tcx> = self.to_predicate(tcx);
+ p.expect_clause()
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ let p: Predicate<'tcx> = self.to_predicate(tcx);
+ p.expect_clause()
+ }
+}
+
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
@@ -1211,6 +1337,14 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
}
}
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
+ pred.to_predicate(tcx)
+ }
+}
+
impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
@@ -1236,31 +1370,45 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitPredicate<'tcx>
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx)
+ self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx)
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> {
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ let p: Predicate<'tcx> = self.to_predicate(tcx);
+ p.expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx)
+ self.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx)
+ self.map_bound(|p| PredicateKind::Clause(ClauseKind::TypeOutlives(p))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx)
+ self.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).to_predicate(tcx)
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ let p: Predicate<'tcx> = self.to_predicate(tcx);
+ p.expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx)
+ PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx)
}
}
@@ -1268,63 +1416,76 @@ impl<'tcx> Predicate<'tcx> {
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
- PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)),
- PredicateKind::Clause(Clause::Projection(..))
- | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
+ PredicateKind::Clause(ClauseKind::Projection(..))
+ | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
- | PredicateKind::Clause(Clause::RegionOutlives(..))
- | PredicateKind::WellFormed(..)
+ | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
+ | PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
- | PredicateKind::Clause(Clause::TypeOutlives(..))
- | PredicateKind::ConstEvaluatable(..)
+ | PredicateKind::Clause(ClauseKind::TypeOutlives(..))
+ | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
- | PredicateKind::Ambiguous
- | PredicateKind::TypeWellFormedFromEnv(..) => None,
+ | PredicateKind::Ambiguous => None,
}
}
pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
- PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)),
- PredicateKind::Clause(Clause::Trait(..))
- | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
+ PredicateKind::Clause(ClauseKind::Trait(..))
+ | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
- | PredicateKind::Clause(Clause::RegionOutlives(..))
- | PredicateKind::WellFormed(..)
+ | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
+ | PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
- | PredicateKind::Clause(Clause::TypeOutlives(..))
- | PredicateKind::ConstEvaluatable(..)
+ | PredicateKind::Clause(ClauseKind::TypeOutlives(..))
+ | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
- | PredicateKind::Ambiguous
- | PredicateKind::TypeWellFormedFromEnv(..) => None,
+ | PredicateKind::Ambiguous => None,
}
}
pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
let predicate = self.kind();
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::Clause(ClauseKind::TypeOutlives(data)) => Some(predicate.rebind(data)),
+ PredicateKind::Clause(ClauseKind::Trait(..))
+ | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
+ | PredicateKind::Clause(ClauseKind::Projection(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
- | PredicateKind::Clause(Clause::RegionOutlives(..))
- | PredicateKind::WellFormed(..)
+ | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
+ | PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
- | PredicateKind::ConstEvaluatable(..)
+ | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
- | PredicateKind::Ambiguous
- | PredicateKind::TypeWellFormedFromEnv(..) => None,
+ | PredicateKind::Ambiguous => None,
+ }
+ }
+
+ /// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`.
+ pub fn as_clause(self) -> Option<Clause<'tcx>> {
+ match self.kind().skip_binder() {
+ PredicateKind::Clause(..) => Some(self.expect_clause()),
+ _ => None,
+ }
+ }
+
+ /// Assert that the predicate is a clause.
+ pub fn expect_clause(self) -> Clause<'tcx> {
+ match self.kind().skip_binder() {
+ PredicateKind::Clause(..) => Clause(self.0),
+ _ => bug!("{self} is not a clause"),
}
}
}
@@ -1350,7 +1511,7 @@ impl<'tcx> Predicate<'tcx> {
/// [usize:Bar<isize>]]`.
#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct InstantiatedPredicates<'tcx> {
- pub predicates: Vec<Predicate<'tcx>>,
+ pub predicates: Vec<Clause<'tcx>>,
pub spans: Vec<Span>,
}
@@ -1369,9 +1530,9 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
}
impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
- type Item = (Predicate<'tcx>, Span);
+ type Item = (Clause<'tcx>, Span);
- type IntoIter = std::iter::Zip<std::vec::IntoIter<Predicate<'tcx>>, std::vec::IntoIter<Span>>;
+ type IntoIter = std::iter::Zip<std::vec::IntoIter<Clause<'tcx>>, std::vec::IntoIter<Span>>;
fn into_iter(self) -> Self::IntoIter {
debug_assert_eq!(self.predicates.len(), self.spans.len());
@@ -1380,10 +1541,10 @@ impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
}
impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> {
- type Item = (Predicate<'tcx>, Span);
+ type Item = (Clause<'tcx>, Span);
type IntoIter = std::iter::Zip<
- std::iter::Copied<std::slice::Iter<'a, Predicate<'tcx>>>,
+ std::iter::Copied<std::slice::Iter<'a, Clause<'tcx>>>,
std::iter::Copied<std::slice::Iter<'a, Span>>,
>;
@@ -1496,7 +1657,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
/// identified by both a universe, as well as a name residing within that universe. Distinct bound
/// regions/types/consts within the same universe simply have an unknown relationship to one
/// another.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(HashStable, TyEncodable, TyDecodable)]
pub struct Placeholder<T> {
pub universe: UniverseIndex,
@@ -1533,7 +1694,7 @@ pub struct ParamEnv<'tcx> {
/// want `Reveal::All`.
///
/// Note: This is packed, use the reveal() method to access it.
- packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, ParamTag, true>,
+ packed: CopyTaggedPtr<&'tcx List<Clause<'tcx>>, ParamTag, true>,
}
#[derive(Copy, Clone)]
@@ -1599,7 +1760,7 @@ impl<'tcx> ParamEnv<'tcx> {
}
#[inline]
- pub fn caller_bounds(self) -> &'tcx List<Predicate<'tcx>> {
+ pub fn caller_bounds(self) -> &'tcx List<Clause<'tcx>> {
self.packed.pointer()
}
@@ -1633,7 +1794,7 @@ impl<'tcx> ParamEnv<'tcx> {
/// Construct a trait environment with the given set of predicates.
#[inline]
pub fn new(
- caller_bounds: &'tcx List<Predicate<'tcx>>,
+ caller_bounds: &'tcx List<Clause<'tcx>>,
reveal: Reveal,
constness: hir::Constness,
) -> Self {
@@ -1874,6 +2035,22 @@ impl VariantDef {
&self.fields[FieldIdx::from_u32(0)]
}
+
+ /// Returns the last field in this variant, if present.
+ #[inline]
+ pub fn tail_opt(&self) -> Option<&FieldDef> {
+ self.fields.raw.last()
+ }
+
+ /// Returns the last field in this variant.
+ ///
+ /// # Panics
+ ///
+ /// Panics, if the variant has no fields.
+ #[inline]
+ pub fn tail(&self) -> &FieldDef {
+ self.tail_opt().expect("expected unsized ADT to have a tail field")
+ }
}
impl PartialEq for VariantDef {
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 1b336b7bf..b10921eff 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -141,7 +141,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
)
.emit();
- self.interner().mk_re_error(e)
+ ty::Region::new_error(self.interner(), e)
}
}
}
@@ -150,17 +150,17 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
match *ty.kind() {
ty::Closure(def_id, substs) => {
let substs = self.fold_closure_substs(def_id, substs);
- self.tcx.mk_closure(def_id, substs)
+ Ty::new_closure(self.tcx, def_id, substs)
}
ty::Generator(def_id, substs, movability) => {
let substs = self.fold_closure_substs(def_id, substs);
- self.tcx.mk_generator(def_id, substs, movability)
+ Ty::new_generator(self.tcx, 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::new_generator_witness_mir(self.tcx, def_id, substs)
}
ty::Param(param) => {
@@ -186,7 +186,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
.emit();
}
- self.interner().ty_error_misc()
+ Ty::new_misc_error(self.tcx)
}
}
}
@@ -216,7 +216,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
})
.emit_unless(self.ignore_errors);
- self.interner().const_error(ct.ty(), guar)
+ ty::Const::new_error(self.tcx, guar, ct.ty())
}
}
}
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index a2e77d9cd..cc2b26a5e 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -73,6 +73,7 @@ trivially_parameterized_over_tcx! {
ty::fast_reject::SimplifiedType,
rustc_ast::Attribute,
rustc_ast::DelimArgs,
+ rustc_ast::expand::StrippedCfgItem<rustc_hir::def_id::DefIndex>,
rustc_attr::ConstStability,
rustc_attr::DefaultBodyStability,
rustc_attr::Deprecation,
@@ -128,5 +129,6 @@ parameterized_over_tcx! {
ty::Const,
ty::Predicate,
ty::Clause,
+ ty::ClauseKind,
ty::GeneratorDiagnosticData,
}
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 64e7480e6..2de0a3f75 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -123,7 +123,7 @@ pub trait Printer<'tcx>: Sized {
impl_trait_ref.map(|i| i.subst(self.tcx(), substs)),
)
} else {
- (self_ty.0, impl_trait_ref.map(|i| i.0))
+ (self_ty.subst_identity(), impl_trait_ref.map(|i| i.subst_identity()))
};
self.print_impl_path(def_id, substs, self_ty, impl_trait_ref)
}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index d6c88ea96..96cf36eb9 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -94,6 +94,10 @@ macro_rules! define_helper {
$tl.with(|c| c.set(self.0))
}
}
+
+ pub fn $name() -> bool {
+ $tl.with(|c| c.get())
+ }
)+
}
}
@@ -184,7 +188,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_re_var(vid), number)
+ self.highlighting_region(ty::Region::new_var(self.tcx, vid), number)
}
/// Returns `Some(n)` with the number to use for the given region, if any.
@@ -676,7 +680,7 @@ pub trait PrettyPrinter<'tcx>:
p!(")")
}
ty::FnDef(def_id, substs) => {
- if NO_QUERIES.with(|q| q.get()) {
+ if with_no_queries() {
p!(print_def_path(def_id, substs));
} else {
let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
@@ -685,29 +689,30 @@ pub trait PrettyPrinter<'tcx>:
}
ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
ty::Infer(infer_ty) => {
- let verbose = self.should_print_verbose();
+ if self.should_print_verbose() {
+ p!(write("{:?}", ty.kind()));
+ return Ok(self);
+ }
+
if let ty::TyVar(ty_vid) = infer_ty {
if let Some(name) = self.ty_infer_name(ty_vid) {
p!(write("{}", name))
} else {
- if verbose {
- p!(write("{:?}", infer_ty))
- } else {
- p!(write("{}", infer_ty))
- }
+ p!(write("{}", infer_ty))
}
} else {
- if verbose { p!(write("{:?}", infer_ty)) } else { p!(write("{}", infer_ty)) }
+ p!(write("{}", infer_ty))
}
}
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 => debug_bound_var(&mut self, debruijn, bound_ty.var)?,
+ ty::BoundTyKind::Anon => {
+ rustc_type_ir::debug_bound_var(&mut self, debruijn, bound_ty.var)?
+ }
ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() {
- true if debruijn == ty::INNERMOST => p!(write("^{}", s)),
- true => p!(write("^{}_{}", debruijn.index(), s)),
- false => p!(write("{}", s)),
+ true => p!(write("{:?}", ty.kind())),
+ false => p!(write("{s}")),
},
},
ty::Adt(def, substs) => {
@@ -730,8 +735,8 @@ pub trait PrettyPrinter<'tcx>:
ty::Foreign(def_id) => {
p!(print_def_path(def_id, &[]));
}
- ty::Alias(ty::Projection | ty::Inherent, ref data) => {
- if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
+ ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ref data) => {
+ if !(self.should_print_verbose() || with_no_queries())
&& self.tcx().is_impl_trait_in_trait(data.def_id)
{
return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
@@ -740,10 +745,11 @@ pub trait PrettyPrinter<'tcx>:
}
}
ty::Placeholder(placeholder) => match placeholder.bound.kind {
- ty::BoundTyKind::Anon => {
- debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound.var)?;
- }
- ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
+ ty::BoundTyKind::Anon => p!(write("{placeholder:?}")),
+ ty::BoundTyKind::Param(_, name) => match self.should_print_verbose() {
+ true => p!(write("{:?}", ty.kind())),
+ false => p!(write("{name}")),
+ },
},
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
// We use verbose printing in 'NO_QUERIES' mode, to
@@ -777,7 +783,7 @@ pub trait PrettyPrinter<'tcx>:
return Ok(self);
}
_ => {
- if NO_QUERIES.with(|q| q.get()) {
+ if with_no_queries() {
p!(print_def_path(def_id, &[]));
return Ok(self);
} else {
@@ -926,7 +932,7 @@ pub trait PrettyPrinter<'tcx>:
let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
+ ty::ClauseKind::Trait(pred) => {
let trait_ref = bound_predicate.rebind(pred.trait_ref);
// Don't print + Sized, but rather + ?Sized if absent.
@@ -937,7 +943,7 @@ pub trait PrettyPrinter<'tcx>:
self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits);
}
- ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
+ ty::ClauseKind::Projection(pred) => {
let proj_ref = bound_predicate.rebind(pred);
let trait_ref = proj_ref.required_poly_trait_ref(tcx);
@@ -951,7 +957,7 @@ pub trait PrettyPrinter<'tcx>:
&mut fn_traits,
);
}
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => {
+ ty::ClauseKind::TypeOutlives(outlives) => {
lifetimes.push(outlives.1);
}
_ => {}
@@ -1222,7 +1228,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_fresh_ty(0);
+ let dummy_cx = Ty::new_fresh(cx.tcx(), 0);
let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
let args = cx
@@ -1372,11 +1378,9 @@ pub trait PrettyPrinter<'tcx>:
}
ty::ConstKind::Bound(debruijn, bound_var) => {
- debug_bound_var(&mut self, debruijn, bound_var)?
+ rustc_type_ir::debug_bound_var(&mut self, debruijn, bound_var)?
}
- ty::ConstKind::Placeholder(placeholder) => {
- debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound)?;
- },
+ ty::ConstKind::Placeholder(placeholder) => p!(write("{placeholder:?}")),
// FIXME(generic_const_exprs):
// write out some legible representation of an abstract const?
ty::ConstKind::Expr(_) => p!("{{const expr}}"),
@@ -1389,11 +1393,12 @@ pub trait PrettyPrinter<'tcx>:
self,
scalar: Scalar,
ty: Ty<'tcx>,
- print_ty: bool,
) -> Result<Self::Const, Self::Error> {
match scalar {
- Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty),
- Scalar::Int(int) => self.pretty_print_const_scalar_int(int, ty, print_ty),
+ Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty),
+ Scalar::Int(int) => {
+ self.pretty_print_const_scalar_int(int, ty, /* print_ty */ true)
+ }
}
}
@@ -1401,7 +1406,6 @@ pub trait PrettyPrinter<'tcx>:
mut self,
ptr: Pointer,
ty: Ty<'tcx>,
- print_ty: bool,
) -> Result<Self::Const, Self::Error> {
define_scoped_cx!(self);
@@ -1455,7 +1459,7 @@ pub trait PrettyPrinter<'tcx>:
_ => {}
}
// Any pointer values not covered by a branch above
- self = self.pretty_print_const_pointer(ptr, ty, print_ty)?;
+ self = self.pretty_print_const_pointer(ptr, ty)?;
Ok(self)
}
@@ -1523,24 +1527,18 @@ pub trait PrettyPrinter<'tcx>:
/// This is overridden for MIR printing because we only want to hide alloc ids from users, not
/// from MIR where it is actually useful.
fn pretty_print_const_pointer<Prov: Provenance>(
- mut self,
+ self,
_: Pointer<Prov>,
ty: Ty<'tcx>,
- print_ty: bool,
) -> Result<Self::Const, Self::Error> {
- if print_ty {
- self.typed_value(
- |mut this| {
- this.write_str("&_")?;
- Ok(this)
- },
- |this| this.print_type(ty),
- ": ",
- )
- } else {
- self.write_str("&_")?;
- Ok(self)
- }
+ self.typed_value(
+ |mut this| {
+ this.write_str("&_")?;
+ Ok(this)
+ },
+ |this| this.print_type(ty),
+ ": ",
+ )
}
fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const, Self::Error> {
@@ -1597,7 +1595,8 @@ pub trait PrettyPrinter<'tcx>:
}
// Aggregates, printed as array/tuple/struct/variant construction syntax.
(ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
- let contents = self.tcx().destructure_const(self.tcx().mk_const(valtree, ty));
+ let contents =
+ self.tcx().destructure_const(ty::Const::new_value(self.tcx(), valtree, ty));
let fields = contents.fields.iter().copied();
match *ty.kind() {
ty::Array(..) => {
@@ -1746,7 +1745,8 @@ impl DerefMut for FmtPrinter<'_, '_> {
impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, ns: Namespace) -> Self {
- Self::new_with_limit(tcx, ns, tcx.type_length_limit())
+ let limit = if with_no_queries() { Limit::new(1048576) } else { tcx.type_length_limit() };
+ Self::new_with_limit(tcx, ns, limit)
}
pub fn new_with_limit(tcx: TyCtxt<'tcx>, ns: Namespace, type_length_limit: Limit) -> Self {
@@ -2150,7 +2150,6 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
self,
p: Pointer<Prov>,
ty: Ty<'tcx>,
- print_ty: bool,
) -> Result<Self::Const, Self::Error> {
let print = |mut this: Self| {
define_scoped_cx!(this);
@@ -2161,11 +2160,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
}
Ok(this)
};
- if print_ty {
- self.typed_value(print, |this| this.print_type(ty), ": ")
- } else {
- print(self)
- }
+ self.typed_value(print, |this| this.print_type(ty), ": ")
}
}
@@ -2303,7 +2298,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
};
if let ty::ReLateBound(debruijn1, br) = *region {
assert_eq!(debruijn1, ty::INNERMOST);
- self.tcx.mk_re_late_bound(self.current_index, br)
+ ty::Region::new_late_bound(self.tcx, self.current_index, br)
} else {
region
}
@@ -2415,7 +2410,8 @@ 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_re_late_bound(
+ return ty::Region::new_late_bound(
+ tcx,
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
);
@@ -2430,7 +2426,8 @@ 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_re_late_bound(
+ return ty::Region::new_late_bound(
+ tcx,
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
);
@@ -2443,7 +2440,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = br.kind;
- return tcx.mk_re_late_bound(
+ return ty::Region::new_late_bound(
+ tcx,
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
);
@@ -2458,7 +2456,11 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
start_or_continue(&mut self, "for<", ", ");
do_continue(&mut self, name);
}
- tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })
+ ty::Region::new_late_bound(
+ tcx,
+ ty::INNERMOST,
+ ty::BoundRegion { var: br.var, kind },
+ )
};
let mut folder = RegionFolder {
tcx,
@@ -2734,7 +2736,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_fresh_ty(0);
+ let dummy_self = Ty::new_fresh(cx.tcx(),0);
let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
p!(print(trait_ref.print_only_trait_path()))
}
@@ -2857,20 +2859,35 @@ define_print_and_forward_display! {
p!(print(binder))
}
+ ty::Clause<'tcx> {
+ p!(print(self.kind()))
+ }
+
+ ty::ClauseKind<'tcx> {
+ match *self {
+ ty::ClauseKind::Trait(ref data) => {
+ p!(print(data))
+ }
+ ty::ClauseKind::RegionOutlives(predicate) => p!(print(predicate)),
+ ty::ClauseKind::TypeOutlives(predicate) => p!(print(predicate)),
+ ty::ClauseKind::Projection(predicate) => p!(print(predicate)),
+ ty::ClauseKind::ConstArgHasType(ct, ty) => {
+ p!("the constant `", print(ct), "` has type `", print(ty), "`")
+ },
+ ty::ClauseKind::WellFormed(arg) => p!(print(arg), " well-formed"),
+ ty::ClauseKind::ConstEvaluatable(ct) => {
+ p!("the constant `", print(ct), "` can be evaluated")
+ }
+ }
+ }
+
ty::PredicateKind<'tcx> {
match *self {
- ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => {
+ ty::PredicateKind::Clause(data) => {
p!(print(data))
}
ty::PredicateKind::Subtype(predicate) => p!(print(predicate)),
ty::PredicateKind::Coerce(predicate) => p!(print(predicate)),
- 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")
}
@@ -2879,15 +2896,9 @@ define_print_and_forward_display! {
print_value_path(closure_def_id, &[]),
write("` implements the trait `{}`", kind)
),
- ty::PredicateKind::ConstEvaluatable(ct) => {
- p!("the constant `", print(ct), "` can be evaluated")
- }
ty::PredicateKind::ConstEquate(c1, c2) => {
p!("the constant `", print(c1), "` equals `", print(c2), "`")
}
- ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
- p!("the type `", print(ty), "` is found in the environment")
- }
ty::PredicateKind::Ambiguous => p!("ambiguous"),
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
}
@@ -2980,7 +2991,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
///
/// The implementation uses similar import discovery logic to that of 'use' suggestions.
///
-/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths`].
+/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`].
fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
let mut map: FxHashMap<DefId, Symbol> = FxHashMap::default();
@@ -3065,27 +3076,3 @@ pub struct OpaqueFnEntry<'tcx> {
fn_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
return_ty: Option<ty::Binder<'tcx, Term<'tcx>>>,
}
-
-pub fn debug_bound_var<T: std::fmt::Write>(
- fmt: &mut T,
- debruijn: ty::DebruijnIndex,
- var: ty::BoundVar,
-) -> Result<(), std::fmt::Error> {
- if debruijn == ty::INNERMOST {
- write!(fmt, "^{}", var.index())
- } else {
- write!(fmt, "^{}_{}", debruijn.index(), var.index())
- }
-}
-
-pub fn debug_placeholder_var<T: std::fmt::Write>(
- fmt: &mut T,
- universe: ty::UniverseIndex,
- bound: ty::BoundVar,
-) -> Result<(), std::fmt::Error> {
- if universe == ty::UniverseIndex::ROOT {
- write!(fmt, "!{}", bound.index())
- } else {
- write!(fmt, "!{}_{}", universe.index(), bound.index())
- }
-}
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 3bbe6a23b..5741832c9 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -391,13 +391,13 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> {
/// Relates `a` and `b` structurally, calling the relation for all nested values.
/// Any semantic equality, e.g. of projections, and inference variables have to be
/// handled by the caller.
+#[instrument(level = "trace", skip(relation), ret)]
pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
a: Ty<'tcx>,
b: Ty<'tcx>,
) -> RelateResult<'tcx, Ty<'tcx>> {
let tcx = relation.tcx();
- debug!("structurally_relate_tys: a={:?} b={:?}", a, b);
match (a.kind(), b.kind()) {
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
// The caller should handle these cases!
@@ -408,7 +408,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
bug!("bound types encountered in structurally_relate_tys")
}
- (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)),
+ (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(tcx, guar)),
(&ty::Never, _)
| (&ty::Char, _)
@@ -428,10 +428,10 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
(&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def => {
let substs = relation.relate_item_substs(a_def.did(), a_substs, b_substs)?;
- Ok(tcx.mk_adt(a_def, substs))
+ Ok(Ty::new_adt(tcx, a_def, substs))
}
- (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)),
+ (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(tcx, a_id)),
(&ty::Dynamic(a_obj, a_region, a_repr), &ty::Dynamic(b_obj, b_region, b_repr))
if a_repr == b_repr =>
@@ -439,7 +439,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| {
relation.relate(a_region, b_region)
})?;
- Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr))
+ Ok(Ty::new_dynamic(tcx, relation.relate(a_obj, b_obj)?, region_bound, a_repr))
}
(&ty::Generator(a_id, a_substs, movability), &ty::Generator(b_id, b_substs, _))
@@ -449,7 +449,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
// 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(a_id, substs, movability))
+ Ok(Ty::new_generator(tcx, a_id, substs, movability))
}
(&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => {
@@ -459,7 +459,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
let b_types = b_types.map_bound(GeneratorWitness);
// Then remove the GeneratorWitness for the result
let types = relation.relate(a_types, b_types)?.map_bound(|witness| witness.0);
- Ok(tcx.mk_generator_witness(types))
+ Ok(Ty::new_generator_witness(tcx, types))
}
(&ty::GeneratorWitnessMIR(a_id, a_substs), &ty::GeneratorWitnessMIR(b_id, b_substs))
@@ -469,7 +469,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
// 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))
+ Ok(Ty::new_generator_witness_mir(tcx, a_id, substs))
}
(&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => {
@@ -477,12 +477,12 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
// the (anonymous) type of the same closure expression. So
// all of their regions should be equated.
let substs = relation.relate(a_substs, b_substs)?;
- Ok(tcx.mk_closure(a_id, &substs))
+ Ok(Ty::new_closure(tcx, a_id, &substs))
}
(&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => {
let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?;
- Ok(tcx.mk_ptr(mt))
+ Ok(Ty::new_ptr(tcx, mt))
}
(&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
@@ -490,13 +490,13 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
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)?;
- Ok(tcx.mk_ref(r, mt))
+ Ok(Ty::new_ref(tcx, r, mt))
}
(&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_array_with_const_len(t, sz)),
+ Ok(sz) => Ok(Ty::new_array_with_const_len(tcx, t, sz)),
Err(err) => {
// Check whether the lengths are both concrete/known values,
// but are unequal, for better diagnostics.
@@ -519,12 +519,15 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
(&ty::Slice(a_t), &ty::Slice(b_t)) => {
let t = relation.relate(a_t, b_t)?;
- Ok(tcx.mk_slice(t))
+ Ok(Ty::new_slice(tcx, t))
}
(&ty::Tuple(as_), &ty::Tuple(bs)) => {
if as_.len() == bs.len() {
- Ok(tcx.mk_tup_from_iter(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?)
+ Ok(Ty::new_tup_from_iter(
+ tcx,
+ 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 {
@@ -536,25 +539,16 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
if a_def_id == b_def_id =>
{
let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
- Ok(tcx.mk_fn_def(a_def_id, substs))
+ Ok(Ty::new_fn_def(tcx, a_def_id, substs))
}
(&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => {
let fty = relation.relate(a_fty, b_fty)?;
- Ok(tcx.mk_fn_ptr(fty))
- }
-
- // these two are already handled downstream in case of lazy normalization
- (&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => {
- let projection_ty = relation.relate(a_data, b_data)?;
- Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs))
- }
-
- (&ty::Alias(ty::Inherent, a_data), &ty::Alias(ty::Inherent, b_data)) => {
- let alias_ty = relation.relate(a_data, b_data)?;
- Ok(tcx.mk_alias(ty::Inherent, tcx.mk_alias_ty(alias_ty.def_id, alias_ty.substs)))
+ Ok(Ty::new_fn_ptr(tcx, fty))
}
+ // The substs of opaque types may not all be invariant, so we have
+ // to treat them separately from other aliases.
(
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }),
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }),
@@ -568,7 +562,20 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
b_substs,
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
)?;
- Ok(tcx.mk_opaque(a_def_id, substs))
+ Ok(Ty::new_opaque(tcx, a_def_id, substs))
+ }
+
+ // Alias tend to mostly already be handled downstream due to normalization.
+ (&ty::Alias(a_kind, a_data), &ty::Alias(b_kind, b_data)) => {
+ // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This if can be removed
+ // and the assert uncommented once the new desugaring is stable.
+ if a_kind == b_kind {
+ let alias_ty = relation.relate(a_data, b_data)?;
+ // assert_eq!(a_kind, b_kind);
+ Ok(Ty::new_alias(tcx, a_kind, alias_ty))
+ } else {
+ Err(TypeError::Sorts(expected_found(relation, a, b)))
+ }
}
_ => Err(TypeError::Sorts(expected_found(relation, a, b))),
@@ -589,17 +596,6 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
let tcx = relation.tcx();
- // 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
- // an unnormalized (i.e. unevaluated) const in the param-env.
- // FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants
- // these `eval` calls can be removed.
- if !tcx.features().generic_const_exprs {
- a = a.eval(tcx, relation.param_env());
- b = b.eval(tcx, relation.param_env());
- }
-
if tcx.features().generic_const_exprs {
a = tcx.expand_abstract_consts(a);
b = tcx.expand_abstract_consts(b);
@@ -634,7 +630,11 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
au.substs,
bu.substs,
)?;
- return Ok(tcx.mk_const(ty::UnevaluatedConst { def: au.def, substs }, a.ty()));
+ return Ok(ty::Const::new_unevaluated(
+ tcx,
+ ty::UnevaluatedConst { def: au.def, substs },
+ a.ty(),
+ ));
}
// Before calling relate on exprs, it is necessary to ensure that the nested consts
// have identical types.
@@ -675,8 +675,7 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
}
_ => return Err(TypeError::ConstMismatch(expected_found(r, a, b))),
};
- let kind = ty::ConstKind::Expr(expr);
- return Ok(tcx.mk_const(kind, a.ty()));
+ return Ok(ty::Const::new_expr(tcx, expr, a.ty()));
}
_ => false,
};
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 16cb6c910..7220d133f 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -11,6 +11,7 @@ use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
use rustc_hir::def::Namespace;
use rustc_index::{Idx, IndexVec};
use rustc_target::abi::TyAndLayout;
+use rustc_type_ir::ConstKind;
use std::fmt;
use std::ops::ControlFlow;
@@ -88,7 +89,35 @@ impl fmt::Debug for ty::FreeRegion {
impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output())
+ let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = self;
+
+ write!(f, "{}", unsafety.prefix_str())?;
+ match abi {
+ rustc_target::spec::abi::Abi::Rust => (),
+ abi => write!(f, "extern \"{abi:?}\" ")?,
+ };
+
+ write!(f, "fn(")?;
+ let inputs = self.inputs();
+ match inputs.len() {
+ 0 if *c_variadic => write!(f, "...)")?,
+ 0 => write!(f, ")")?,
+ _ => {
+ for ty in &self.inputs()[0..(self.inputs().len() - 1)] {
+ write!(f, "{ty:?}, ")?;
+ }
+ write!(f, "{:?}", self.inputs().last().unwrap())?;
+ if *c_variadic {
+ write!(f, "...")?;
+ }
+ write!(f, ")")?;
+ }
+ }
+
+ match self.output().kind() {
+ ty::Tuple(list) if list.is_empty() => Ok(()),
+ _ => write!(f, " -> {:?}", self.output()),
+ }
}
}
@@ -145,12 +174,22 @@ 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 {
+ write!(f, "{:?}", self.kind())
+ }
+}
+
+impl<'tcx> fmt::Debug for ty::ClauseKind<'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),
- ty::Clause::Projection(ref pair) => pair.fmt(f),
+ ty::ClauseKind::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"),
+ ty::ClauseKind::Trait(ref a) => a.fmt(f),
+ ty::ClauseKind::RegionOutlives(ref pair) => pair.fmt(f),
+ ty::ClauseKind::TypeOutlives(ref pair) => pair.fmt(f),
+ ty::ClauseKind::Projection(ref pair) => pair.fmt(f),
+ ty::ClauseKind::WellFormed(ref data) => write!(f, "WellFormed({:?})", data),
+ ty::ClauseKind::ConstEvaluatable(ct) => {
+ write!(f, "ConstEvaluatable({ct:?})")
+ }
}
}
}
@@ -161,20 +200,13 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
ty::PredicateKind::Clause(ref a) => a.fmt(f),
ty::PredicateKind::Subtype(ref pair) => pair.fmt(f),
ty::PredicateKind::Coerce(ref pair) => pair.fmt(f),
- ty::PredicateKind::WellFormed(data) => write!(f, "WellFormed({:?})", data),
ty::PredicateKind::ObjectSafe(trait_def_id) => {
write!(f, "ObjectSafe({:?})", trait_def_id)
}
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
}
- ty::PredicateKind::ConstEvaluatable(ct) => {
- write!(f, "ConstEvaluatable({ct:?})")
- }
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
- ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
- write!(f, "TypeWellFormedFromEnv({:?})", ty)
- }
ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"),
ty::PredicateKind::AliasRelate(t1, t2, dir) => {
write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})")
@@ -210,22 +242,21 @@ impl<'tcx> fmt::Debug for ty::Const<'tcx> {
}
}
-impl<'tcx> fmt::Debug for ty::ConstKind<'tcx> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- use ty::ConstKind::*;
- match self {
- Param(param) => write!(f, "{param:?}"),
- Infer(var) => write!(f, "{var:?}"),
- Bound(debruijn, var) => ty::print::debug_bound_var(f, *debruijn, *var),
- Placeholder(placeholder) => {
- ty::print::debug_placeholder_var(f, placeholder.universe, placeholder.bound)
- }
- Unevaluated(uv) => {
- f.debug_tuple("Unevaluated").field(&uv.substs).field(&uv.def).finish()
- }
- Value(valtree) => write!(f, "{valtree:?}"),
- Error(_) => write!(f, "[const error]"),
- Expr(expr) => write!(f, "{expr:?}"),
+impl fmt::Debug for ty::BoundTy {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self.kind {
+ ty::BoundTyKind::Anon => write!(f, "{:?}", self.var),
+ ty::BoundTyKind::Param(_, sym) => write!(f, "{sym:?}"),
+ }
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for ty::Placeholder<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if self.universe == ty::UniverseIndex::ROOT {
+ write!(f, "!{:?}", self.bound)
+ } else {
+ write!(f, "!{}_{:?}", self.universe.index(), self.bound)
}
}
}
@@ -294,13 +325,14 @@ TrivialTypeTraversalAndLiftImpls! {
crate::ty::AliasRelationDirection,
crate::ty::Placeholder<crate::ty::BoundRegion>,
crate::ty::Placeholder<crate::ty::BoundTy>,
+ crate::ty::Placeholder<ty::BoundVar>,
crate::ty::ClosureKind,
crate::ty::FreeRegion,
crate::ty::InferTy,
crate::ty::IntVarValue,
crate::ty::ParamConst,
crate::ty::ParamTy,
- crate::ty::adjustment::PointerCast,
+ crate::ty::adjustment::PointerCoercion,
crate::ty::RegionVid,
crate::ty::UniverseIndex,
crate::ty::Variance,
@@ -310,7 +342,6 @@ TrivialTypeTraversalAndLiftImpls! {
interpret::Scalar,
rustc_target::abi::Size,
ty::BoundVar,
- ty::Placeholder<ty::BoundVar>,
}
TrivialTypeTraversalAndLiftImpls! {
@@ -609,12 +640,28 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
}
}
+// FIXME(clause): This is wonky
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ Ok(folder.try_fold_predicate(self.as_predicate())?.expect_clause())
+ }
+}
+
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)
}
}
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ visitor.visit_predicate(self.as_predicate())
+ }
+}
+
impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
@@ -634,12 +681,12 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
}
}
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Predicate<'tcx>> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Clause<'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))
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v))
}
}
@@ -664,9 +711,20 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
folder: &mut F,
) -> Result<Self, F::Error> {
let ty = self.ty().try_fold_with(folder)?;
- let kind = self.kind().try_fold_with(folder)?;
+ let kind = match self.kind() {
+ ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?),
+ ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?),
+ ConstKind::Bound(d, b) => {
+ ConstKind::Bound(d.try_fold_with(folder)?, b.try_fold_with(folder)?)
+ }
+ ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?),
+ ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?),
+ ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?),
+ ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?),
+ ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
+ };
if ty != self.ty() || kind != self.kind() {
- Ok(folder.interner().mk_const(kind, ty))
+ Ok(folder.interner().mk_ct_from_kind(kind, ty))
} else {
Ok(self)
}
@@ -679,7 +737,19 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
self.ty().visit_with(visitor)?;
- self.kind().visit_with(visitor)
+ match self.kind() {
+ ConstKind::Param(p) => p.visit_with(visitor),
+ ConstKind::Infer(i) => i.visit_with(visitor),
+ ConstKind::Bound(d, b) => {
+ d.visit_with(visitor)?;
+ b.visit_with(visitor)
+ }
+ ConstKind::Placeholder(p) => p.visit_with(visitor),
+ ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
+ ConstKind::Value(v) => v.visit_with(visitor),
+ ConstKind::Error(e) => e.visit_with(visitor),
+ ConstKind::Expr(e) => e.visit_with(visitor),
+ }
}
}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index e6d51c4ec..94746fbdc 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -15,16 +15,18 @@ use hir::def::DefKind;
use polonius_engine::Atom;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::intern::Interned;
-use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
+use rustc_error_messages::DiagnosticMessage;
+use rustc_errors::{DiagnosticArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::LangItem;
use rustc_index::Idx;
use rustc_macros::HashStable;
use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
use rustc_target::spec::abi::{self, Abi};
+use std::assert_matches::debug_assert_matches;
use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt;
@@ -33,13 +35,17 @@ use std::ops::{ControlFlow, Deref, Range};
use ty::util::IntTypeExt;
use rustc_type_ir::sty::TyKind::*;
-use rustc_type_ir::RegionKind as IrRegionKind;
use rustc_type_ir::TyKind as IrTyKind;
+use rustc_type_ir::{CollectAndApply, ConstKind as IrConstKind};
+use rustc_type_ir::{DynKind, RegionKind as IrRegionKind};
+
+use super::GenericParamDefKind;
// Re-export the `TyKind` from `rustc_type_ir` here for convenience
#[rustc_diagnostic_item = "TyKind"]
pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>;
pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>;
+pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
@@ -568,7 +574,7 @@ impl<'tcx> GeneratorSubsts<'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].ty).subst(tcx, self.substs)
+ ty::EarlyBinder::bind(layout.field_tys[*field].ty).subst(tcx, self.substs)
})
})
}
@@ -715,7 +721,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
/// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`),
/// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self`
/// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example).
- pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> {
+ pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> {
use crate::ty::ToPredicate;
match self.skip_binder() {
ExistentialPredicate::Trait(tr) => {
@@ -1007,7 +1013,10 @@ impl BoundVariableKind {
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(HashStable, Lift)]
-pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>);
+pub struct Binder<'tcx, T> {
+ value: T,
+ bound_vars: &'tcx List<BoundVariableKind>,
+}
impl<'tcx, T> Binder<'tcx, T>
where
@@ -1023,15 +1032,15 @@ where
!value.has_escaping_bound_vars(),
"`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
);
- Binder(value, ty::List::empty())
+ Binder { value, bound_vars: ty::List::empty() }
}
- pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
+ pub fn bind_with_vars(value: T, bound_vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
if cfg!(debug_assertions) {
- let mut validator = ValidateBoundVars::new(vars);
+ let mut validator = ValidateBoundVars::new(bound_vars);
value.visit_with(&mut validator);
}
- Binder(value, vars)
+ Binder { value, bound_vars }
}
}
@@ -1053,30 +1062,30 @@ impl<'tcx, T> Binder<'tcx, T> {
/// - comparing the self type of a PolyTraitRef to see if it is equal to
/// a type parameter `X`, since the type `X` does not reference any regions
pub fn skip_binder(self) -> T {
- self.0
+ self.value
}
pub fn bound_vars(&self) -> &'tcx List<BoundVariableKind> {
- self.1
+ self.bound_vars
}
pub fn as_ref(&self) -> Binder<'tcx, &T> {
- Binder(&self.0, self.1)
+ Binder { value: &self.value, bound_vars: self.bound_vars }
}
pub fn as_deref(&self) -> Binder<'tcx, &T::Target>
where
T: Deref,
{
- Binder(&self.0, self.1)
+ Binder { value: &self.value, bound_vars: self.bound_vars }
}
pub fn map_bound_ref_unchecked<F, U>(&self, f: F) -> Binder<'tcx, U>
where
F: FnOnce(&T) -> U,
{
- let value = f(&self.0);
- Binder(value, self.1)
+ let value = f(&self.value);
+ Binder { value, bound_vars: self.bound_vars }
}
pub fn map_bound_ref<F, U: TypeVisitable<TyCtxt<'tcx>>>(&self, f: F) -> Binder<'tcx, U>
@@ -1090,12 +1099,13 @@ impl<'tcx, T> Binder<'tcx, T> {
where
F: FnOnce(T) -> U,
{
- let value = f(self.0);
+ let Binder { value, bound_vars } = self;
+ let value = f(value);
if cfg!(debug_assertions) {
- let mut validator = ValidateBoundVars::new(self.1);
+ let mut validator = ValidateBoundVars::new(bound_vars);
value.visit_with(&mut validator);
}
- Binder(value, self.1)
+ Binder { value, bound_vars }
}
pub fn try_map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>, E>(
@@ -1105,12 +1115,13 @@ impl<'tcx, T> Binder<'tcx, T> {
where
F: FnOnce(T) -> Result<U, E>,
{
- let value = f(self.0)?;
+ let Binder { value, bound_vars } = self;
+ let value = f(value)?;
if cfg!(debug_assertions) {
- let mut validator = ValidateBoundVars::new(self.1);
+ let mut validator = ValidateBoundVars::new(bound_vars);
value.visit_with(&mut validator);
}
- Ok(Binder(value, self.1))
+ Ok(Binder { value, bound_vars })
}
/// Wraps a `value` in a binder, using the same bound variables as the
@@ -1126,11 +1137,7 @@ impl<'tcx, T> Binder<'tcx, T> {
where
U: TypeVisitable<TyCtxt<'tcx>>,
{
- if cfg!(debug_assertions) {
- let mut validator = ValidateBoundVars::new(self.bound_vars());
- value.visit_with(&mut validator);
- }
- Binder(value, self.1)
+ Binder::bind_with_vars(value, self.bound_vars)
}
/// Unwraps and returns the value within, but only if it contains
@@ -1147,7 +1154,7 @@ impl<'tcx, T> Binder<'tcx, T> {
where
T: TypeVisitable<TyCtxt<'tcx>>,
{
- if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
+ if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
}
/// Splits the contents into two things that share the same binder
@@ -1160,22 +1167,23 @@ impl<'tcx, T> Binder<'tcx, T> {
where
F: FnOnce(T) -> (U, V),
{
- let (u, v) = f(self.0);
- (Binder(u, self.1), Binder(v, self.1))
+ let Binder { value, bound_vars } = self;
+ let (u, v) = f(value);
+ (Binder { value: u, bound_vars }, Binder { value: v, bound_vars })
}
}
impl<'tcx, T> Binder<'tcx, Option<T>> {
pub fn transpose(self) -> Option<Binder<'tcx, T>> {
- let bound_vars = self.1;
- self.0.map(|v| Binder(v, bound_vars))
+ let Binder { value, bound_vars } = self;
+ value.map(|value| Binder { value, bound_vars })
}
}
impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> {
- let bound_vars = self.1;
- self.0.into_iter().map(|v| Binder(v, bound_vars))
+ let Binder { value, bound_vars } = self;
+ value.into_iter().map(|value| Binder { value, bound_vars })
}
}
@@ -1184,7 +1192,7 @@ where
T: IntoDiagnosticArg,
{
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- self.0.into_diagnostic_arg()
+ self.value.into_diagnostic_arg()
}
}
@@ -1231,12 +1239,13 @@ impl<'tcx> AliasTy<'tcx> {
DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent,
DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection,
DefKind::OpaqueTy => ty::Opaque,
+ DefKind::TyAlias => ty::Weak,
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
}
}
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- tcx.mk_alias(self.kind(tcx), self)
+ Ty::new_alias(tcx, self.kind(tcx), self)
}
}
@@ -1427,7 +1436,7 @@ impl<'tcx> ParamTy {
#[inline]
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- tcx.mk_ty_param(self.index, self.name)
+ Ty::new_param(tcx, self.index, self.name)
}
pub fn span_from_generics(&self, tcx: TyCtxt<'tcx>, item_with_generics: DefId) -> Span {
@@ -1459,6 +1468,103 @@ impl ParamConst {
#[rustc_pass_by_value]
pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>);
+impl<'tcx> Region<'tcx> {
+ #[inline]
+ pub fn new_early_bound(
+ tcx: TyCtxt<'tcx>,
+ early_bound_region: ty::EarlyBoundRegion,
+ ) -> Region<'tcx> {
+ tcx.intern_region(ty::ReEarlyBound(early_bound_region))
+ }
+
+ #[inline]
+ pub fn new_late_bound(
+ tcx: TyCtxt<'tcx>,
+ debruijn: ty::DebruijnIndex,
+ bound_region: ty::BoundRegion,
+ ) -> Region<'tcx> {
+ // Use a pre-interned one when possible.
+ if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region
+ && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize())
+ && let Some(re) = inner.get(var.as_usize()).copied()
+ {
+ re
+ } else {
+ tcx.intern_region(ty::ReLateBound(debruijn, bound_region))
+ }
+ }
+
+ #[inline]
+ pub fn new_free(
+ tcx: TyCtxt<'tcx>,
+ scope: DefId,
+ bound_region: ty::BoundRegionKind,
+ ) -> Region<'tcx> {
+ tcx.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
+ }
+
+ #[inline]
+ pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::RegionVid) -> Region<'tcx> {
+ // Use a pre-interned one when possible.
+ tcx.lifetimes
+ .re_vars
+ .get(v.as_usize())
+ .copied()
+ .unwrap_or_else(|| tcx.intern_region(ty::ReVar(v)))
+ }
+
+ #[inline]
+ pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderRegion) -> Region<'tcx> {
+ tcx.intern_region(ty::RePlaceholder(placeholder))
+ }
+
+ /// Constructs a `RegionKind::ReError` region.
+ #[track_caller]
+ pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Region<'tcx> {
+ tcx.intern_region(ty::ReError(reported))
+ }
+
+ /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` to ensure it
+ /// gets used.
+ #[track_caller]
+ pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> {
+ Region::new_error_with_message(
+ tcx,
+ DUMMY_SP,
+ "RegionKind::ReError constructed but no error reported",
+ )
+ }
+
+ /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` with the given
+ /// `msg` to ensure it gets used.
+ #[track_caller]
+ pub fn new_error_with_message<S: Into<MultiSpan>>(
+ tcx: TyCtxt<'tcx>,
+ span: S,
+ msg: &'static str,
+ ) -> Region<'tcx> {
+ let reported = tcx.sess.delay_span_bug(span, msg);
+ Region::new_error(tcx, reported)
+ }
+
+ /// Avoid this in favour of more specific `new_*` methods, where possible,
+ /// to avoid the cost of the `match`.
+ pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
+ match kind {
+ ty::ReEarlyBound(region) => Region::new_early_bound(tcx, region),
+ ty::ReLateBound(debruijn, region) => Region::new_late_bound(tcx, debruijn, region),
+ ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
+ Region::new_free(tcx, scope, bound_region)
+ }
+ ty::ReStatic => tcx.lifetimes.re_static,
+ ty::ReVar(vid) => Region::new_var(tcx, vid),
+ ty::RePlaceholder(region) => Region::new_placeholder(tcx, region),
+ ty::ReErased => tcx.lifetimes.re_erased,
+ ty::ReError(reported) => Region::new_error(tcx, reported),
+ }
+ }
+}
+
impl<'tcx> Deref for Region<'tcx> {
type Target = RegionKind<'tcx>;
@@ -1484,7 +1590,7 @@ pub struct EarlyBoundRegion {
impl fmt::Debug for EarlyBoundRegion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}, {}", self.index, self.name)
+ write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name)
}
}
@@ -1511,10 +1617,11 @@ impl Atom for RegionVid {
rustc_index::newtype_index! {
#[derive(HashStable)]
+ #[debug_format = "{}"]
pub struct BoundVar {}
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub struct BoundTy {
pub var: BoundVar,
@@ -1770,6 +1877,390 @@ impl<'tcx> Region<'tcx> {
}
}
+/// Constructors for `Ty`
+impl<'tcx> Ty<'tcx> {
+ // Avoid this in favour of more specific `new_*` methods, where possible.
+ #[allow(rustc::usage_of_ty_tykind)]
+ #[inline]
+ pub fn new(tcx: TyCtxt<'tcx>, st: TyKind<'tcx>) -> Ty<'tcx> {
+ tcx.mk_ty_from_kind(st)
+ }
+
+ #[inline]
+ pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Ty<'tcx> {
+ Ty::new(tcx, TyKind::Infer(infer))
+ }
+
+ #[inline]
+ pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::TyVid) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ tcx.types
+ .ty_vars
+ .get(v.as_usize())
+ .copied()
+ .unwrap_or_else(|| Ty::new(tcx, Infer(TyVar(v))))
+ }
+
+ #[inline]
+ pub fn new_int_var(tcx: TyCtxt<'tcx>, v: ty::IntVid) -> Ty<'tcx> {
+ Ty::new_infer(tcx, IntVar(v))
+ }
+
+ #[inline]
+ pub fn new_float_var(tcx: TyCtxt<'tcx>, v: ty::FloatVid) -> Ty<'tcx> {
+ Ty::new_infer(tcx, FloatVar(v))
+ }
+
+ #[inline]
+ pub fn new_fresh(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ tcx.types
+ .fresh_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshTy(n)))
+ }
+
+ #[inline]
+ pub fn new_fresh_int(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ tcx.types
+ .fresh_int_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshIntTy(n)))
+ }
+
+ #[inline]
+ pub fn new_fresh_float(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ tcx.types
+ .fresh_float_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshFloatTy(n)))
+ }
+
+ #[inline]
+ pub fn new_param(tcx: TyCtxt<'tcx>, index: u32, name: Symbol) -> Ty<'tcx> {
+ tcx.mk_ty_from_kind(Param(ParamTy { index, name }))
+ }
+
+ #[inline]
+ pub fn new_bound(
+ tcx: TyCtxt<'tcx>,
+ index: ty::DebruijnIndex,
+ bound_ty: ty::BoundTy,
+ ) -> Ty<'tcx> {
+ Ty::new(tcx, Bound(index, bound_ty))
+ }
+
+ #[inline]
+ pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType) -> Ty<'tcx> {
+ Ty::new(tcx, Placeholder(placeholder))
+ }
+
+ #[inline]
+ pub fn new_alias(
+ tcx: TyCtxt<'tcx>,
+ kind: ty::AliasKind,
+ alias_ty: ty::AliasTy<'tcx>,
+ ) -> Ty<'tcx> {
+ debug_assert_matches!(
+ (kind, tcx.def_kind(alias_ty.def_id)),
+ (ty::Opaque, DefKind::OpaqueTy)
+ | (ty::Projection | ty::Inherent, DefKind::AssocTy)
+ | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder)
+ | (ty::Weak, DefKind::TyAlias)
+ );
+ Ty::new(tcx, Alias(kind, alias_ty))
+ }
+
+ #[inline]
+ pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
+ Ty::new_alias(tcx, ty::Opaque, tcx.mk_alias_ty(def_id, substs))
+ }
+
+ /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
+ pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Ty<'tcx> {
+ Ty::new(tcx, Error(reported))
+ }
+
+ /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
+ #[track_caller]
+ pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ Ty::new_error_with_message(tcx, DUMMY_SP, "TyKind::Error constructed but no error reported")
+ }
+
+ /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
+ /// ensure it gets used.
+ #[track_caller]
+ pub fn new_error_with_message<S: Into<MultiSpan>>(
+ tcx: TyCtxt<'tcx>,
+ span: S,
+ msg: impl Into<DiagnosticMessage>,
+ ) -> Ty<'tcx> {
+ let reported = tcx.sess.delay_span_bug(span, msg);
+ Ty::new(tcx, Error(reported))
+ }
+
+ #[inline]
+ pub fn new_int(tcx: TyCtxt<'tcx>, i: ty::IntTy) -> Ty<'tcx> {
+ use ty::IntTy::*;
+ match i {
+ Isize => tcx.types.isize,
+ I8 => tcx.types.i8,
+ I16 => tcx.types.i16,
+ I32 => tcx.types.i32,
+ I64 => tcx.types.i64,
+ I128 => tcx.types.i128,
+ }
+ }
+
+ #[inline]
+ pub fn new_uint(tcx: TyCtxt<'tcx>, ui: ty::UintTy) -> Ty<'tcx> {
+ use ty::UintTy::*;
+ match ui {
+ Usize => tcx.types.usize,
+ U8 => tcx.types.u8,
+ U16 => tcx.types.u16,
+ U32 => tcx.types.u32,
+ U64 => tcx.types.u64,
+ U128 => tcx.types.u128,
+ }
+ }
+
+ #[inline]
+ pub fn new_float(tcx: TyCtxt<'tcx>, f: ty::FloatTy) -> Ty<'tcx> {
+ use ty::FloatTy::*;
+ match f {
+ F32 => tcx.types.f32,
+ F64 => tcx.types.f64,
+ }
+ }
+
+ #[inline]
+ pub fn new_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
+ Ty::new(tcx, Ref(r, tm.ty, tm.mutbl))
+ }
+
+ #[inline]
+ pub fn new_mut_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
+ }
+
+ #[inline]
+ pub fn new_imm_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Not })
+ }
+
+ #[inline]
+ pub fn new_ptr(tcx: TyCtxt<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
+ Ty::new(tcx, RawPtr(tm))
+ }
+
+ #[inline]
+ pub fn new_mut_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
+ }
+
+ #[inline]
+ pub fn new_imm_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Not })
+ }
+
+ #[inline]
+ pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
+ Ty::new(tcx, Adt(def, substs))
+ }
+
+ #[inline]
+ pub fn new_foreign(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
+ Ty::new(tcx, Foreign(def_id))
+ }
+
+ #[inline]
+ pub fn new_array(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
+ Ty::new(tcx, Array(ty, ty::Const::from_target_usize(tcx, n)))
+ }
+
+ #[inline]
+ pub fn new_array_with_const_len(
+ tcx: TyCtxt<'tcx>,
+ ty: Ty<'tcx>,
+ ct: ty::Const<'tcx>,
+ ) -> Ty<'tcx> {
+ Ty::new(tcx, Array(ty, ct))
+ }
+
+ #[inline]
+ pub fn new_slice(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ Ty::new(tcx, Slice(ty))
+ }
+
+ #[inline]
+ pub fn new_tup(tcx: TyCtxt<'tcx>, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
+ if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(&ts))) }
+ }
+
+ pub fn new_tup_from_iter<I, T>(tcx: TyCtxt<'tcx>, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>,
+ {
+ T::collect_and_apply(iter, |ts| Ty::new_tup(tcx, ts))
+ }
+
+ #[inline]
+ pub fn new_fn_def(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+ ) -> Ty<'tcx> {
+ let substs = tcx.check_and_mk_substs(def_id, substs);
+ Ty::new(tcx, FnDef(def_id, substs))
+ }
+
+ #[inline]
+ pub fn new_fn_ptr(tcx: TyCtxt<'tcx>, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
+ Ty::new(tcx, FnPtr(fty))
+ }
+
+ #[inline]
+ pub fn new_dynamic(
+ tcx: TyCtxt<'tcx>,
+ obj: &'tcx List<PolyExistentialPredicate<'tcx>>,
+ reg: ty::Region<'tcx>,
+ repr: DynKind,
+ ) -> Ty<'tcx> {
+ Ty::new(tcx, Dynamic(obj, reg, repr))
+ }
+
+ #[inline]
+ pub fn new_projection(
+ tcx: TyCtxt<'tcx>,
+ item_def_id: DefId,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+ ) -> Ty<'tcx> {
+ Ty::new_alias(tcx, ty::Projection, tcx.mk_alias_ty(item_def_id, substs))
+ }
+
+ #[inline]
+ pub fn new_closure(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+ closure_substs: SubstsRef<'tcx>,
+ ) -> Ty<'tcx> {
+ debug_assert_eq!(
+ closure_substs.len(),
+ tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3,
+ "closure constructed with incorrect substitutions"
+ );
+ Ty::new(tcx, Closure(def_id, closure_substs))
+ }
+
+ #[inline]
+ pub fn new_generator(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+ generator_substs: SubstsRef<'tcx>,
+ movability: hir::Movability,
+ ) -> Ty<'tcx> {
+ debug_assert_eq!(
+ generator_substs.len(),
+ tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5,
+ "generator constructed with incorrect number of substitutions"
+ );
+ Ty::new(tcx, Generator(def_id, generator_substs, movability))
+ }
+
+ #[inline]
+ pub fn new_generator_witness(
+ tcx: TyCtxt<'tcx>,
+ types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>,
+ ) -> Ty<'tcx> {
+ Ty::new(tcx, GeneratorWitness(types))
+ }
+
+ #[inline]
+ pub fn new_generator_witness_mir(
+ tcx: TyCtxt<'tcx>,
+ id: DefId,
+ substs: SubstsRef<'tcx>,
+ ) -> Ty<'tcx> {
+ Ty::new(tcx, GeneratorWitnessMIR(id, substs))
+ }
+
+ // misc
+
+ #[inline]
+ pub fn new_unit(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ tcx.types.unit
+ }
+
+ #[inline]
+ pub fn new_static_str(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_)
+ }
+
+ #[inline]
+ pub fn new_diverging_default(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ if tcx.features().never_type_fallback { tcx.types.never } else { tcx.types.unit }
+ }
+
+ // lang and diagnostic tys
+
+ fn new_generic_adt(tcx: TyCtxt<'tcx>, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
+ let adt_def = tcx.adt_def(wrapper_def_id);
+ let substs =
+ InternalSubsts::for_item(tcx, wrapper_def_id, |param, substs| match param.kind {
+ GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
+ GenericParamDefKind::Type { has_default, .. } => {
+ if param.index == 0 {
+ ty_param.into()
+ } else {
+ assert!(has_default);
+ tcx.type_of(param.def_id).subst(tcx, substs).into()
+ }
+ }
+ });
+ Ty::new(tcx, Adt(adt_def, substs))
+ }
+
+ #[inline]
+ pub fn new_lang_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
+ let def_id = tcx.lang_items().get(item)?;
+ Some(Ty::new_generic_adt(tcx, def_id, ty))
+ }
+
+ #[inline]
+ pub fn new_diagnostic_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
+ let def_id = tcx.get_diagnostic_item(name)?;
+ Some(Ty::new_generic_adt(tcx, def_id, ty))
+ }
+
+ #[inline]
+ pub fn new_box(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ let def_id = tcx.require_lang_item(LangItem::OwnedBox, None);
+ Ty::new_generic_adt(tcx, def_id, ty)
+ }
+
+ #[inline]
+ pub fn new_maybe_uninit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ let def_id = tcx.require_lang_item(LangItem::MaybeUninit, None);
+ Ty::new_generic_adt(tcx, def_id, ty)
+ }
+
+ /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes.
+ pub fn new_task_context(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ let context_did = tcx.require_lang_item(LangItem::Context, None);
+ let context_adt_ref = tcx.adt_def(context_did);
+ let context_substs = tcx.mk_substs(&[tcx.lifetimes.re_erased.into()]);
+ let context_ty = Ty::new_adt(tcx, context_adt_ref, context_substs);
+ Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, context_ty)
+ }
+}
+
/// Type utilities
impl<'tcx> Ty<'tcx> {
#[inline(always)]
@@ -2213,7 +2704,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.mk_substs(&[self.into()]))
+ Ty::new_projection(tcx, assoc_items[0], tcx.mk_substs(&[self.into()]))
}
ty::Bool
@@ -2366,7 +2857,7 @@ impl<'tcx> Ty<'tcx> {
ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)),
- ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
+ ty::Adt(def, _substs) => def.sized_constraint(tcx).skip_binder().is_empty(),
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 43f95635a..4d5f5b865 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -11,6 +11,7 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_serialize::{self, Decodable, Encodable};
+use rustc_span::sym;
use rustc_type_ir::WithCachedTypeInfo;
use smallvec::SmallVec;
@@ -451,6 +452,10 @@ impl<'tcx> InternalSubsts<'tcx> {
pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> {
tcx.mk_substs_from_iter(self.iter().take(generics.count()))
}
+
+ pub fn host_effect_param(&'tcx self) -> Option<ty::Const<'tcx>> {
+ self.consts().rfind(|x| matches!(x.kind(), ty::ConstKind::Param(p) if p.name == sym::host))
+ }
}
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> {
@@ -538,15 +543,21 @@ impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx
/// [`subst_identity`](EarlyBinder::subst_identity) or [`skip_binder`](EarlyBinder::skip_binder).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Encodable, Decodable, HashStable)]
-pub struct EarlyBinder<T>(pub T);
+pub struct EarlyBinder<T> {
+ value: T,
+}
/// For early binders, you should first call `subst` before using any visitors.
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 bind(value: T) -> EarlyBinder<T> {
+ EarlyBinder { value }
+ }
+
pub fn as_ref(&self) -> EarlyBinder<&T> {
- EarlyBinder(&self.0)
+ EarlyBinder { value: &self.value }
}
pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U>
@@ -560,20 +571,20 @@ impl<T> EarlyBinder<T> {
where
F: FnOnce(T) -> U,
{
- let value = f(self.0);
- EarlyBinder(value)
+ let value = f(self.value);
+ EarlyBinder { value }
}
pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E>
where
F: FnOnce(T) -> Result<U, E>,
{
- let value = f(self.0)?;
- Ok(EarlyBinder(value))
+ let value = f(self.value)?;
+ Ok(EarlyBinder { value })
}
pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
- EarlyBinder(value)
+ EarlyBinder { value }
}
/// Skips the binder and returns the "bound" value.
@@ -582,22 +593,26 @@ impl<T> EarlyBinder<T> {
/// arguments of an `FnSig`). Otherwise, consider using
/// [`subst_identity`](EarlyBinder::subst_identity).
///
+ /// To skip the binder on `x: &EarlyBinder<T>` to obtain `&T`, leverage
+ /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`.
+ ///
/// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is
/// the analogous operation on [`super::Binder`].
pub fn skip_binder(self) -> T {
- self.0
+ self.value
}
}
impl<T> EarlyBinder<Option<T>> {
pub fn transpose(self) -> Option<EarlyBinder<T>> {
- self.0.map(|v| EarlyBinder(v))
+ self.value.map(|value| EarlyBinder { value })
}
}
impl<T, U> EarlyBinder<(T, U)> {
pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) {
- (EarlyBinder(self.0.0), EarlyBinder(self.0.1))
+ let EarlyBinder { value: (lhs, rhs) } = self;
+ (EarlyBinder { value: lhs }, EarlyBinder { value: rhs })
}
}
@@ -610,13 +625,13 @@ where
tcx: TyCtxt<'tcx>,
substs: &'s [GenericArg<'tcx>],
) -> SubstIter<'s, 'tcx, I> {
- SubstIter { it: self.0.into_iter(), tcx, substs }
+ SubstIter { it: self.value.into_iter(), tcx, substs }
}
/// Similar to [`subst_identity`](EarlyBinder::subst_identity),
/// but on an iterator of `TypeFoldable` values.
pub fn subst_identity_iter(self) -> I::IntoIter {
- self.0.into_iter()
+ self.value.into_iter()
}
}
@@ -633,7 +648,7 @@ where
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
- Some(EarlyBinder(self.it.next()?).subst(self.tcx, self.substs))
+ Some(EarlyBinder { value: self.it.next()? }.subst(self.tcx, self.substs))
}
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -647,7 +662,7 @@ where
I::Item: TypeFoldable<TyCtxt<'tcx>>,
{
fn next_back(&mut self) -> Option<Self::Item> {
- Some(EarlyBinder(self.it.next_back()?).subst(self.tcx, self.substs))
+ Some(EarlyBinder { value: self.it.next_back()? }.subst(self.tcx, self.substs))
}
}
@@ -668,13 +683,13 @@ where
tcx: TyCtxt<'tcx>,
substs: &'s [GenericArg<'tcx>],
) -> SubstIterCopied<'s, 'tcx, I> {
- SubstIterCopied { it: self.0.into_iter(), tcx, substs }
+ SubstIterCopied { it: self.value.into_iter(), tcx, substs }
}
/// Similar to [`subst_identity`](EarlyBinder::subst_identity),
/// but on an iterator of values that deref to a `TypeFoldable`.
pub fn subst_identity_iter_copied(self) -> impl Iterator<Item = <I::Item as Deref>::Target> {
- self.0.into_iter().map(|v| *v)
+ self.value.into_iter().map(|v| *v)
}
}
@@ -692,7 +707,7 @@ where
type Item = <I::Item as Deref>::Target;
fn next(&mut self) -> Option<Self::Item> {
- Some(EarlyBinder(*self.it.next()?).subst(self.tcx, self.substs))
+ self.it.next().map(|value| EarlyBinder { value: *value }.subst(self.tcx, self.substs))
}
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -707,7 +722,7 @@ where
<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))
+ self.it.next_back().map(|value| EarlyBinder { value: *value }.subst(self.tcx, self.substs))
}
}
@@ -725,7 +740,7 @@ pub struct EarlyBinderIter<T> {
impl<T: IntoIterator> EarlyBinder<T> {
pub fn transpose_iter(self) -> EarlyBinderIter<T::IntoIter> {
- EarlyBinderIter { t: self.0.into_iter() }
+ EarlyBinderIter { t: self.value.into_iter() }
}
}
@@ -733,7 +748,7 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> {
type Item = EarlyBinder<T::Item>;
fn next(&mut self) -> Option<Self::Item> {
- self.t.next().map(|i| EarlyBinder(i))
+ self.t.next().map(|value| EarlyBinder { value })
}
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -744,7 +759,7 @@ impl<T: Iterator> Iterator for EarlyBinderIter<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)
+ self.value.fold_with(&mut folder)
}
/// Makes the identity substitution `T0 => T0, ..., TN => TN`.
@@ -756,12 +771,12 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> {
/// - Inside of the body of `foo`, we treat `T` as a placeholder by calling
/// `subst_identity` to discharge the `EarlyBinder`.
pub fn subst_identity(self) -> T {
- self.0
+ self.value
}
/// Returns the inner value, but only if it contains no bound vars.
pub fn no_bound_vars(self) -> Option<T> {
- if !self.0.has_param() { Some(self.0) } else { None }
+ if !self.value.has_param() { Some(self.value) } else { None }
}
}
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index e61037e5e..98c70e330 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -52,6 +52,16 @@ pub struct TraitDef {
/// List of functions from `#[rustc_must_implement_one_of]` attribute one of which
/// must be implemented.
pub must_implement_one_of: Option<Box<[Ident]>>,
+
+ /// Whether to add a builtin `dyn Trait: Trait` implementation.
+ /// This is enabled for all traits except ones marked with
+ /// `#[rustc_deny_explicit_impl(implement_via_object = false)]`.
+ pub implement_via_object: bool,
+
+ /// Whether a trait is fully built-in, and any implementation is disallowed.
+ /// This only applies to built-in traits, and is marked via
+ /// `#[rustc_deny_explicit_impl(implement_via_object = ...)]`.
+ pub deny_explicit_impl: bool,
}
/// Whether this trait is treated specially by the standard library
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index e04dbbff9..8cbffa148 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -155,11 +155,7 @@ pub struct TypeckResults<'tcx> {
/// We also store the type here, so that the compiler can use it as a hint
/// for figuring out hidden types, even if they are only set in dead code
/// (which doesn't show up in MIR).
- ///
- /// These types are mapped back to the opaque's identity substitutions
- /// (with erased regions), which is why we don't associated substs with any
- /// of these usages.
- pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
+ pub concrete_opaque_types: FxIndexMap<ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>>,
/// Tracks the minimum captures required for a closure;
/// see `MinCaptureInformationMap` for more details.
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index ba0513563..e2e4a2dbd 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1,7 +1,6 @@
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use crate::mir;
use crate::query::Providers;
use crate::ty::layout::IntegerExt;
use crate::ty::{
@@ -11,13 +10,12 @@ use crate::ty::{
use crate::ty::{GenericArgKind, SubstsRef};
use rustc_apfloat::Float as _;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_index::bit_set::GrowableBitSet;
-use rustc_index::{Idx, IndexVec};
use rustc_macros::HashStable;
use rustc_session::Limit;
use rustc_span::sym;
@@ -129,7 +127,7 @@ impl IntTypeExt for IntegerType {
impl<'tcx> TyCtxt<'tcx> {
/// Creates a hash of the type `Ty` which will be the same no matter what crate
/// context it's calculated within. This is used by the `type_id` intrinsic.
- pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash64 {
+ pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash128 {
// We want the type_id be independent of the types free regions, so we
// erase them. The erase_regions() call will also anonymize bound
// regions, which is desirable too.
@@ -173,18 +171,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
- if let ty::Adt(def, substs) = *ty.kind() {
- for field in def.all_fields() {
- let field_ty = field.ty(self, substs);
- if let ty::Error(_) = field_ty.kind() {
- return true;
- }
- }
- }
- false
- }
-
/// Attempts to returns the deeply last field of nested structures, but
/// does not apply any normalization in its search. Returns the same type
/// if input `ty` is not a structure at all.
@@ -237,14 +223,14 @@ impl<'tcx> TyCtxt<'tcx> {
};
let reported =
self.sess.emit_err(crate::error::RecursionLimitReached { ty, suggested_limit });
- return self.ty_error(reported);
+ return Ty::new_error(self, reported);
}
match *ty.kind() {
ty::Adt(def, substs) => {
if !def.is_struct() {
break;
}
- match def.non_enum_variant().fields.raw.last() {
+ match def.non_enum_variant().tail_opt() {
Some(field) => {
f();
ty = field.ty(self, substs);
@@ -318,7 +304,7 @@ impl<'tcx> TyCtxt<'tcx> {
(&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
if a_def == b_def && a_def.is_struct() =>
{
- if let Some(f) = a_def.non_enum_variant().fields.raw.last() {
+ if let Some(f) = a_def.non_enum_variant().tail_opt() {
a = f.ty(self, a_substs);
b = f.ty(self, b_substs);
} else {
@@ -624,12 +610,12 @@ impl<'tcx> TyCtxt<'tcx> {
closure_substs: SubstsRef<'tcx>,
env_region: ty::Region<'tcx>,
) -> Option<Ty<'tcx>> {
- let closure_ty = self.mk_closure(closure_def_id, closure_substs);
+ let closure_ty = Ty::new_closure(self, 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(env_region, closure_ty),
- ty::ClosureKind::FnMut => self.mk_mut_ref(env_region, closure_ty),
+ ty::ClosureKind::Fn => Ty::new_imm_ref(self, env_region, closure_ty),
+ ty::ClosureKind::FnMut => Ty::new_mut_ref(self, env_region, closure_ty),
ty::ClosureKind::FnOnce => closure_ty,
};
Some(env_ty)
@@ -670,12 +656,12 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn thread_local_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
let static_ty = self.type_of(def_id).subst_identity();
if self.is_mutable_static(def_id) {
- self.mk_mut_ptr(static_ty)
+ Ty::new_mut_ptr(self, static_ty)
} else if self.is_foreign_item(def_id) {
- self.mk_imm_ptr(static_ty)
+ Ty::new_imm_ptr(self, static_ty)
} else {
// FIXME: These things don't *really* have 'static lifetime.
- self.mk_imm_ref(self.lifetimes.re_static, static_ty)
+ Ty::new_imm_ref(self, self.lifetimes.re_static, static_ty)
}
}
@@ -690,11 +676,11 @@ impl<'tcx> TyCtxt<'tcx> {
// 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`.
if self.is_mutable_static(def_id) {
- self.mk_mut_ptr(static_ty)
+ Ty::new_mut_ptr(self, static_ty)
} else if self.is_foreign_item(def_id) {
- self.mk_imm_ptr(static_ty)
+ Ty::new_imm_ptr(self, static_ty)
} else {
- self.mk_imm_ref(self.lifetimes.re_erased, static_ty)
+ Ty::new_imm_ref(self, self.lifetimes.re_erased, static_ty)
}
}
@@ -709,7 +695,7 @@ impl<'tcx> TyCtxt<'tcx> {
.as_ref()
.map_or_else(|| [].iter(), |l| l.field_tys.iter())
.filter(|decl| !decl.ignore_for_traits)
- .map(|decl| ty::EarlyBinder(decl.ty))
+ .map(|decl| ty::EarlyBinder::bind(decl.ty))
}
/// Normalizes all opaque types in the given value, replacing them
@@ -750,80 +736,6 @@ impl<'tcx> TyCtxt<'tcx> {
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
}
- /// Returns names of captured upvars for closures and generators.
- ///
- /// Here are some examples:
- /// - `name__field1__field2` when the upvar is captured by value.
- /// - `_ref__name__field` when the upvar is captured by reference.
- ///
- /// For generators this only contains upvars that are shared by all states.
- pub fn closure_saved_names_of_captured_variables(
- self,
- def_id: DefId,
- ) -> SmallVec<[String; 16]> {
- let body = self.optimized_mir(def_id);
-
- body.var_debug_info
- .iter()
- .filter_map(|var| {
- let is_ref = match var.value {
- mir::VarDebugInfoContents::Place(place)
- if place.local == mir::Local::new(1) =>
- {
- // The projection is either `[.., Field, Deref]` or `[.., Field]`. It
- // implies whether the variable is captured by value or by reference.
- matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
- }
- _ => return None,
- };
- let prefix = if is_ref { "_ref__" } else { "" };
- Some(prefix.to_owned() + var.name.as_str())
- })
- .collect()
- }
-
- // FIXME(eddyb) maybe precompute this? Right now it's computed once
- // per generator monomorphization, but it doesn't depend on substs.
- pub fn generator_layout_and_saved_local_names(
- self,
- def_id: DefId,
- ) -> (
- &'tcx ty::GeneratorLayout<'tcx>,
- IndexVec<mir::GeneratorSavedLocal, Option<rustc_span::Symbol>>,
- ) {
- let tcx = self;
- let body = tcx.optimized_mir(def_id);
- let generator_layout = body.generator_layout().unwrap();
- let mut generator_saved_local_names =
- IndexVec::from_elem(None, &generator_layout.field_tys);
-
- let state_arg = mir::Local::new(1);
- for var in &body.var_debug_info {
- let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
- if place.local != state_arg {
- continue;
- }
- match place.projection[..] {
- [
- // Deref of the `Pin<&mut Self>` state argument.
- mir::ProjectionElem::Field(..),
- mir::ProjectionElem::Deref,
- // Field of a variant of the state.
- mir::ProjectionElem::Downcast(_, variant),
- mir::ProjectionElem::Field(field, _),
- ] => {
- let name = &mut generator_saved_local_names
- [generator_layout.variant_fields[variant][field]];
- if name.is_none() {
- name.replace(var.name);
- }
- }
- _ => {}
- }
- }
- (generator_layout, generator_saved_local_names)
- }
-
/// 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)
@@ -857,6 +769,26 @@ impl<'tcx> TyCtxt<'tcx> {
_ => def_kind.article(),
}
}
+
+ /// Return `true` if the supplied `CrateNum` is "user-visible," meaning either a [public]
+ /// dependency, or a [direct] private dependency. This is used to decide whether the crate can
+ /// be shown in `impl` suggestions.
+ ///
+ /// [public]: TyCtxt::is_private_dep
+ /// [direct]: rustc_session::cstore::ExternCrate::is_direct
+ pub fn is_user_visible_dep(self, key: CrateNum) -> bool {
+ // | Private | Direct | Visible | |
+ // |---------|--------|---------|--------------------|
+ // | Yes | Yes | Yes | !true || true |
+ // | No | Yes | Yes | !false || true |
+ // | Yes | No | No | !true || false |
+ // | No | No | Yes | !false || false |
+ !self.is_private_dep(key)
+ // If `extern_crate` is `None`, then the crate was injected (e.g., by the allocator).
+ // Treat that kind of crate as "indirect", since it's an implementation detail of
+ // the language.
+ || self.extern_crate(key.as_def_id()).map_or(false, |e| e.is_direct())
+ }
}
struct OpaqueTypeExpander<'tcx> {
@@ -922,7 +854,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
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);
+ let expanded_ty = Ty::new_generator_witness_mir(self.tcx, def_id, substs);
self.expanded_cache.insert((def_id, substs), expanded_ty);
expanded_ty
}
@@ -964,7 +896,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
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
+ && let ty::ClauseKind::Projection(projection_pred) = clause
{
p.kind()
.rebind(ty::ProjectionPredicate {
@@ -1374,7 +1306,7 @@ pub fn needs_drop_components<'tcx>(
ty::Array(elem_ty, size) => {
match needs_drop_components(*elem_ty, target_layout) {
Ok(v) if v.is_empty() => Ok(v),
- res => match size.kind().try_to_bits(target_layout.pointer_size) {
+ res => match size.try_to_bits(target_layout.pointer_size) {
// Arrays of size zero don't need drop, even if their element
// type does.
Some(0) => Ok(SmallVec::new()),
@@ -1487,8 +1419,8 @@ pub struct AlwaysRequiresDrop;
/// with their underlying types.
pub fn reveal_opaque_types_in_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
- val: &'tcx ty::List<ty::Predicate<'tcx>>,
-) -> &'tcx ty::List<ty::Predicate<'tcx>> {
+ val: &'tcx ty::List<ty::Clause<'tcx>>,
+) -> &'tcx ty::List<ty::Clause<'tcx>> {
let mut visitor = OpaqueTypeExpander {
seen_opaque_tys: FxHashSet::default(),
expanded_cache: FxHashMap::default(),
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index b9b1cd73a..443791d0a 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -73,7 +73,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
let ptr_align = tcx.data_layout.pointer_align.abi;
let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
- let mut vtable = Allocation::uninit(vtable_size, ptr_align, /* panic_on_fail */ true).unwrap();
+ let mut vtable = Allocation::uninit(vtable_size, ptr_align);
// No need to do any alignment checks on the memory accesses below, because we know the
// allocation is correctly aligned as we created it above. Also we're only offsetting by
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index c62c33d4d..b0961d917 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -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_misc()) }
+ unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(Ty::new_misc_error(tcx)) }
}
}
@@ -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_misc();
+ let err = Ty::new_misc_error(tcx);
let arity = if let Some(frame) = stack.get(0)
&& frame.query.dep_kind == DepKind::fn_sig
@@ -96,19 +96,22 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Representability {
impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<Ty<'_>> {
fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self {
- ty::EarlyBinder(Ty::from_cycle_error(tcx, cycle))
+ ty::EarlyBinder::bind(Ty::from_cycle_error(tcx, cycle))
}
}
impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>> {
fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> Self {
- ty::EarlyBinder(ty::Binder::from_cycle_error(tcx, cycle))
+ ty::EarlyBinder::bind(ty::Binder::from_cycle_error(tcx, cycle))
}
}
-impl<'tcx, T> Value<TyCtxt<'tcx>, DepKind> for Result<T, ty::layout::LayoutError<'_>> {
+impl<'tcx, T> Value<TyCtxt<'tcx>, DepKind> for Result<T, &'_ ty::layout::LayoutError<'_>> {
fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo<DepKind>]) -> Self {
- Err(ty::layout::LayoutError::Cycle)
+ // tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under
+ // min_specialization. Since this is an error path anyways, leaking doesn't matter (and really,
+ // tcx.arena.alloc is pretty much equal to leaking).
+ Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle)))
}
}