summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_infer
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_infer')
-rw-r--r--compiler/rustc_infer/Cargo.toml1
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs4
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs15
-rw-r--r--compiler/rustc_infer/src/infer/at.rs17
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs271
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs9
-rw-r--r--compiler/rustc_infer/src/infer/canonical/substitute.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs293
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs20
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs5
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs5
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs10
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs20
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs7
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs40
-rw-r--r--compiler/rustc_infer/src/infer/free_regions.rs16
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs6
-rw-r--r--compiler/rustc_infer/src/infer/fudge.rs4
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs60
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs167
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs18
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/table.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs22
-rw-r--r--compiler/rustc_infer/src/infer/outlives/env.rs4
-rw-r--r--compiler/rustc_infer/src/infer/outlives/for_liveness.rs7
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs30
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs29
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs27
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs46
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs4
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs16
-rw-r--r--compiler/rustc_infer/src/infer/relate/combine.rs (renamed from compiler/rustc_infer/src/infer/combine.rs)121
-rw-r--r--compiler/rustc_infer/src/infer/relate/equate.rs (renamed from compiler/rustc_infer/src/infer/equate.rs)16
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs (renamed from compiler/rustc_infer/src/infer/generalize.rs)93
-rw-r--r--compiler/rustc_infer/src/infer/relate/glb.rs (renamed from compiler/rustc_infer/src/infer/glb.rs)19
-rw-r--r--compiler/rustc_infer/src/infer/relate/higher_ranked.rs (renamed from compiler/rustc_infer/src/infer/higher_ranked/mod.rs)2
-rw-r--r--compiler/rustc_infer/src/infer/relate/lattice.rs (renamed from compiler/rustc_infer/src/infer/lattice.rs)6
-rw-r--r--compiler/rustc_infer/src/infer/relate/lub.rs (renamed from compiler/rustc_infer/src/infer/lub.rs)15
-rw-r--r--compiler/rustc_infer/src/infer/relate/mod.rs12
-rw-r--r--compiler/rustc_infer/src/infer/relate/nll.rs (renamed from compiler/rustc_infer/src/infer/nll_relate/mod.rs)33
-rw-r--r--compiler/rustc_infer/src/infer/relate/sub.rs (renamed from compiler/rustc_infer/src/infer/sub.rs)12
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs84
-rw-r--r--compiler/rustc_infer/src/infer/type_variable.rs92
-rw-r--r--compiler/rustc_infer/src/infer/undo_log.rs6
-rw-r--r--compiler/rustc_infer/src/lib.rs11
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs13
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs2
-rw-r--r--compiler/rustc_infer/src/traits/util.rs82
53 files changed, 965 insertions, 849 deletions
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 00251a192..73a02a431 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -15,7 +15,6 @@ rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
-rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 3ff1a5c0c..a0768fc71 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -363,9 +363,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
return false;
};
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(anon_reg.def_id);
-
- let node = self.tcx.hir().get(hir_id);
+ let node = self.tcx.hir_node_by_def_id(anon_reg.def_id);
let is_impl = matches!(&node, hir::Node::ImplItem(_));
let generics = match node {
hir::Node::Item(&hir::Item {
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 57bc14ebc..68bf36a16 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -1,6 +1,6 @@
use crate::fluent_generated as fluent;
use crate::infer::error_reporting::nice_region_error::find_anon_type;
-use rustc_errors::{self, AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage};
+use rustc_errors::{AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::{symbol::kw, Span};
@@ -17,7 +17,7 @@ impl<'a> DescriptionCtx<'a> {
alt_span: Option<Span>,
) -> Option<Self> {
let (span, kind, arg) = match *region {
- ty::ReEarlyBound(ref br) => {
+ ty::ReEarlyParam(ref br) => {
let scope = region.free_region_binding_scope(tcx).expect_local();
let span = if let Some(param) =
tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
@@ -32,7 +32,7 @@ impl<'a> DescriptionCtx<'a> {
(Some(span), "as_defined_anon", String::new())
}
}
- ty::ReFree(ref fr) => {
+ ty::ReLateParam(ref fr) => {
if !fr.bound_region.is_named()
&& let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region)
{
@@ -70,11 +70,14 @@ impl<'a> DescriptionCtx<'a> {
ty::RePlaceholder(_) | ty::ReError(_) => return None,
// FIXME(#13998) RePlaceholder should probably print like
- // ReFree rather than dumping Debug output on the user.
+ // ReLateParam rather than dumping Debug output on the user.
//
// We shouldn't really be having unification failures with ReVar
- // and ReLateBound though.
- ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
+ // and ReBound though.
+ //
+ // FIXME(@lcnr): figure out why we have to handle `ReBound`
+ // here, this feels somewhat off.
+ ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => {
(alt_span, "revar", format!("{region:?}"))
}
};
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 2797d0797..09313cd97 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -65,8 +65,15 @@ impl<'tcx> InferCtxt<'tcx> {
/// Forks the inference context, creating a new inference context with the same inference
/// variables in the same state. This can be used to "branch off" many tests from the same
- /// common state. Used in coherence.
+ /// common state.
pub fn fork(&self) -> Self {
+ self.fork_with_intercrate(self.intercrate)
+ }
+
+ /// Forks the inference context, creating a new inference context with the same inference
+ /// variables in the same state, except possibly changing the intercrate mode. This can be
+ /// used to "branch off" many tests from the same common state. Used in negative coherence.
+ pub fn fork_with_intercrate(&self, intercrate: bool) -> Self {
Self {
tcx: self.tcx,
defining_use_anchor: self.defining_use_anchor,
@@ -81,7 +88,7 @@ impl<'tcx> InferCtxt<'tcx> {
tainted_by_errors: self.tainted_by_errors.clone(),
err_count_on_creation: self.err_count_on_creation,
universe: self.universe.clone(),
- intercrate: self.intercrate,
+ intercrate,
next_trait_solver: self.next_trait_solver,
}
}
@@ -441,7 +448,11 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
- values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
+ values: PolyTraitRefs(ExpectedFound::new(
+ a_is_expected,
+ ty::Binder::dummy(a),
+ ty::Binder::dummy(b),
+ )),
}
}
}
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 0e2f9ba70..5b00ef422 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -9,11 +9,9 @@ use crate::infer::canonical::{
Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, OriginalQueryValues,
};
use crate::infer::InferCtxt;
-use rustc_middle::ty::flags::FlagComputation;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::GenericArg;
use rustc_middle::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
-use std::sync::atomic::Ordering;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::Idx;
@@ -37,40 +35,13 @@ impl<'tcx> InferCtxt<'tcx> {
/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#canonicalizing-the-query
pub fn canonicalize_query<V>(
&self,
- value: V,
- query_state: &mut OriginalQueryValues<'tcx>,
- ) -> Canonical<'tcx, V>
- where
- V: TypeFoldable<TyCtxt<'tcx>>,
- {
- self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed);
-
- Canonicalizer::canonicalize(value, self, self.tcx, &CanonicalizeAllFreeRegions, query_state)
- }
-
- /// Like [Self::canonicalize_query], but preserves distinct universes. For
- /// example, canonicalizing `&'?0: Trait<'?1>`, where `'?0` is in `U1` and
- /// `'?1` is in `U3` would be canonicalized to have `?0` in `U1` and `'?1`
- /// in `U2`.
- ///
- /// This is used for Chalk integration.
- pub fn canonicalize_query_preserving_universes<V>(
- &self,
- value: V,
+ value: ty::ParamEnvAnd<'tcx, V>,
query_state: &mut OriginalQueryValues<'tcx>,
- ) -> Canonical<'tcx, V>
+ ) -> Canonical<'tcx, ty::ParamEnvAnd<'tcx, V>>
where
V: TypeFoldable<TyCtxt<'tcx>>,
{
- self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed);
-
- Canonicalizer::canonicalize(
- value,
- self,
- self.tcx,
- &CanonicalizeAllFreeRegionsPreservingUniverses,
- query_state,
- )
+ self.canonicalize_query_with_mode(value, query_state, &CanonicalizeAllFreeRegions)
}
/// Canonicalizes a query *response* `V`. When we canonicalize a
@@ -105,7 +76,7 @@ impl<'tcx> InferCtxt<'tcx> {
let mut query_state = OriginalQueryValues::default();
Canonicalizer::canonicalize(
value,
- self,
+ Some(self),
self.tcx,
&CanonicalizeQueryResponse,
&mut query_state,
@@ -119,7 +90,7 @@ impl<'tcx> InferCtxt<'tcx> {
let mut query_state = OriginalQueryValues::default();
Canonicalizer::canonicalize(
value,
- self,
+ Some(self),
self.tcx,
&CanonicalizeUserTypeAnnotation,
&mut query_state,
@@ -132,21 +103,53 @@ impl<'tcx> InferCtxt<'tcx> {
/// handling of `'static` regions (e.g. trait evaluation).
pub fn canonicalize_query_keep_static<V>(
&self,
- value: V,
+ value: ty::ParamEnvAnd<'tcx, V>,
query_state: &mut OriginalQueryValues<'tcx>,
- ) -> Canonical<'tcx, V>
+ ) -> Canonical<'tcx, ty::ParamEnvAnd<'tcx, V>>
+ where
+ V: TypeFoldable<TyCtxt<'tcx>>,
+ {
+ self.canonicalize_query_with_mode(
+ value,
+ query_state,
+ &CanonicalizeFreeRegionsOtherThanStatic,
+ )
+ }
+
+ fn canonicalize_query_with_mode<V>(
+ &self,
+ value: ty::ParamEnvAnd<'tcx, V>,
+ query_state: &mut OriginalQueryValues<'tcx>,
+ canonicalize_region_mode: &dyn CanonicalizeMode,
+ ) -> Canonical<'tcx, ty::ParamEnvAnd<'tcx, V>>
where
V: TypeFoldable<TyCtxt<'tcx>>,
{
- self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed);
+ let (param_env, value) = value.into_parts();
+ let base = self.tcx.canonical_param_env_cache.get_or_insert(
+ self.tcx,
+ param_env,
+ query_state,
+ |tcx, param_env, query_state| {
+ Canonicalizer::canonicalize(
+ param_env,
+ None,
+ tcx,
+ &CanonicalizeFreeRegionsOtherThanStatic,
+ query_state,
+ )
+ },
+ );
- Canonicalizer::canonicalize(
+ Canonicalizer::canonicalize_with_base(
+ base,
value,
- self,
+ Some(self),
self.tcx,
- &CanonicalizeFreeRegionsOtherThanStatic,
+ canonicalize_region_mode,
query_state,
)
+ .unchecked_map(|(param_env, value)| param_env.and(value))
}
}
@@ -176,10 +179,24 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
fn canonicalize_free_region<'tcx>(
&self,
canonicalizer: &mut Canonicalizer<'_, 'tcx>,
- r: ty::Region<'tcx>,
+ mut r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
+ let infcx = canonicalizer.infcx.unwrap();
+
+ if let ty::ReVar(vid) = *r {
+ r = infcx
+ .inner
+ .borrow_mut()
+ .unwrap_region_constraints()
+ .opportunistic_resolve_var(canonicalizer.tcx, vid);
+ debug!(
+ "canonical: region var found with vid {vid:?}, \
+ opportunistically resolved to {r:?}",
+ );
+ };
+
match *r {
- ty::ReFree(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyBound(..) => r,
+ ty::ReLateParam(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyParam(..) => r,
ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region(
CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderRegion(placeholder) },
@@ -187,7 +204,8 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
),
ty::ReVar(vid) => {
- let universe = canonicalizer.region_var_universe(vid);
+ let universe =
+ infcx.inner.borrow_mut().unwrap_region_constraints().var_universe(vid);
canonicalizer.canonical_var_for_region(
CanonicalVarInfo { kind: CanonicalVarKind::Region(universe) },
r,
@@ -202,8 +220,8 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
//
// rust-lang/rust#57464: `impl Trait` can leak local
// scopes (in manner violating typeck). Therefore, use
- // `delay_span_bug` to allow type error over an ICE.
- canonicalizer.tcx.sess.delay_span_bug(
+ // `span_delayed_bug` to allow type error over an ICE.
+ canonicalizer.tcx.sess.span_delayed_bug(
rustc_span::DUMMY_SP,
format!("unexpected region in query response: `{r:?}`"),
);
@@ -230,9 +248,13 @@ impl CanonicalizeMode for CanonicalizeUserTypeAnnotation {
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
match *r {
- ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReErased | ty::ReStatic | ty::ReError(_) => r,
+ ty::ReEarlyParam(_)
+ | ty::ReLateParam(_)
+ | ty::ReErased
+ | ty::ReStatic
+ | ty::ReError(_) => r,
ty::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r),
- ty::RePlaceholder(..) | ty::ReLateBound(..) => {
+ ty::RePlaceholder(..) | ty::ReBound(..) => {
// We only expect region names that the user can type.
bug!("unexpected region in query response: `{:?}`", r)
}
@@ -268,30 +290,6 @@ impl CanonicalizeMode for CanonicalizeAllFreeRegions {
}
}
-struct CanonicalizeAllFreeRegionsPreservingUniverses;
-
-impl CanonicalizeMode for CanonicalizeAllFreeRegionsPreservingUniverses {
- fn canonicalize_free_region<'tcx>(
- &self,
- canonicalizer: &mut Canonicalizer<'_, 'tcx>,
- r: ty::Region<'tcx>,
- ) -> ty::Region<'tcx> {
- let universe = canonicalizer.infcx.universe_of_region(r);
- canonicalizer.canonical_var_for_region(
- CanonicalVarInfo { kind: CanonicalVarKind::Region(universe) },
- r,
- )
- }
-
- fn any(&self) -> bool {
- true
- }
-
- fn preserve_universes(&self) -> bool {
- true
- }
-}
-
struct CanonicalizeFreeRegionsOtherThanStatic;
impl CanonicalizeMode for CanonicalizeFreeRegionsOtherThanStatic {
@@ -313,7 +311,8 @@ impl CanonicalizeMode for CanonicalizeFreeRegionsOtherThanStatic {
}
struct Canonicalizer<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'tcx>,
+ /// Set to `None` to disable the resolution of inference variables.
+ infcx: Option<&'cx InferCtxt<'tcx>>,
tcx: TyCtxt<'tcx>,
variables: SmallVec<[CanonicalVarInfo<'tcx>; 8]>,
query_state: &'cx mut OriginalQueryValues<'tcx>,
@@ -343,7 +342,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
- ty::ReLateBound(index, ..) => {
+ ty::ReBound(index, ..) => {
if index >= self.binder_index {
bug!("escaping late-bound region during canonicalization");
} else {
@@ -351,25 +350,12 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
}
}
- ty::ReVar(vid) => {
- let resolved = self
- .infcx
- .inner
- .borrow_mut()
- .unwrap_region_constraints()
- .opportunistic_resolve_var(self.tcx, vid);
- debug!(
- "canonical: region var found with vid {vid:?}, \
- opportunistically resolved to {resolved:?}",
- );
- self.canonicalize_mode.canonicalize_free_region(self, resolved)
- }
-
ty::ReStatic
- | ty::ReEarlyBound(..)
+ | ty::ReEarlyParam(..)
| ty::ReError(_)
- | ty::ReFree(_)
+ | ty::ReLateParam(_)
| ty::RePlaceholder(..)
+ | ty::ReVar(_)
| ty::ReErased => self.canonicalize_mode.canonicalize_free_region(self, r),
}
}
@@ -380,14 +366,14 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
// We need to canonicalize the *root* of our ty var.
// This is so that our canonical response correctly reflects
// any equated inference vars correctly!
- let root_vid = self.infcx.root_var(vid);
+ let root_vid = self.infcx.unwrap().root_var(vid);
if root_vid != vid {
- t = Ty::new_var(self.infcx.tcx, root_vid);
+ t = Ty::new_var(self.tcx, root_vid);
vid = root_vid;
}
debug!("canonical: type var found with vid {:?}", vid);
- match self.infcx.probe_ty_var(vid) {
+ match self.infcx.unwrap().probe_ty_var(vid) {
// `t` could be a float / int variable; canonicalize that instead.
Ok(t) => {
debug!("(resolved to {:?})", t);
@@ -412,7 +398,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
}
ty::Infer(ty::IntVar(vid)) => {
- let nt = self.infcx.opportunistic_resolve_int_var(vid);
+ let nt = self.infcx.unwrap().opportunistic_resolve_int_var(vid);
if nt != t {
return self.fold_ty(nt);
} else {
@@ -423,7 +409,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
}
}
ty::Infer(ty::FloatVar(vid)) => {
- let nt = self.infcx.opportunistic_resolve_float_var(vid);
+ let nt = self.infcx.unwrap().opportunistic_resolve_float_var(vid);
if nt != t {
return self.fold_ty(nt);
} else {
@@ -494,14 +480,14 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
// We need to canonicalize the *root* of our const var.
// This is so that our canonical response correctly reflects
// any equated inference vars correctly!
- let root_vid = self.infcx.root_const_var(vid);
+ let root_vid = self.infcx.unwrap().root_const_var(vid);
if root_vid != vid {
- ct = ty::Const::new_var(self.infcx.tcx, root_vid, ct.ty());
+ ct = ty::Const::new_var(self.tcx, root_vid, ct.ty());
vid = root_vid;
}
debug!("canonical: const var found with vid {:?}", vid);
- match self.infcx.probe_const_var(vid) {
+ match self.infcx.unwrap().probe_const_var(vid) {
Ok(c) => {
debug!("(resolved to {:?})", c);
return self.fold_const(c);
@@ -522,8 +508,8 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
}
}
ty::ConstKind::Infer(InferConst::EffectVar(vid)) => {
- match self.infcx.probe_effect_var(vid) {
- Some(value) => return self.fold_const(value.as_const(self.infcx.tcx)),
+ match self.infcx.unwrap().probe_effect_var(vid) {
+ Some(value) => return self.fold_const(value.as_const(self.tcx)),
None => {
return self.canonicalize_const_var(
CanonicalVarInfo { kind: CanonicalVarKind::Effect },
@@ -553,8 +539,11 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
_ => {}
}
- let flags = FlagComputation::for_const(ct);
- if flags.intersects(self.needs_canonical_flags) { ct.super_fold_with(self) } else { ct }
+ if ct.flags().intersects(self.needs_canonical_flags) {
+ ct.super_fold_with(self)
+ } else {
+ ct
+ }
}
}
@@ -563,7 +552,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
/// `canonicalize_query` and `canonicalize_response`.
fn canonicalize<V>(
value: V,
- infcx: &InferCtxt<'tcx>,
+ infcx: Option<&InferCtxt<'tcx>>,
tcx: TyCtxt<'tcx>,
canonicalize_region_mode: &dyn CanonicalizeMode,
query_state: &mut OriginalQueryValues<'tcx>,
@@ -571,6 +560,33 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
where
V: TypeFoldable<TyCtxt<'tcx>>,
{
+ let base = Canonical {
+ max_universe: ty::UniverseIndex::ROOT,
+ variables: List::empty(),
+ value: (),
+ };
+ Canonicalizer::canonicalize_with_base(
+ base,
+ value,
+ infcx,
+ tcx,
+ canonicalize_region_mode,
+ query_state,
+ )
+ .unchecked_map(|((), val)| val)
+ }
+
+ fn canonicalize_with_base<U, V>(
+ base: Canonical<'tcx, U>,
+ value: V,
+ infcx: Option<&InferCtxt<'tcx>>,
+ tcx: TyCtxt<'tcx>,
+ canonicalize_region_mode: &dyn CanonicalizeMode,
+ query_state: &mut OriginalQueryValues<'tcx>,
+ ) -> Canonical<'tcx, (U, V)>
+ where
+ V: TypeFoldable<TyCtxt<'tcx>>,
+ {
let needs_canonical_flags = if canonicalize_region_mode.any() {
TypeFlags::HAS_INFER | TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_FREE_REGIONS
} else {
@@ -579,12 +595,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
// Fast path: nothing that needs to be canonicalized.
if !value.has_type_flags(needs_canonical_flags) {
- let canon_value = Canonical {
- max_universe: ty::UniverseIndex::ROOT,
- variables: List::empty(),
- value,
- };
- return canon_value;
+ return base.unchecked_map(|b| (b, value));
}
let mut canonicalizer = Canonicalizer {
@@ -592,11 +603,20 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
tcx,
canonicalize_mode: canonicalize_region_mode,
needs_canonical_flags,
- variables: SmallVec::new(),
+ variables: SmallVec::from_slice(base.variables),
query_state,
indices: FxHashMap::default(),
binder_index: ty::INNERMOST,
};
+ if canonicalizer.query_state.var_values.spilled() {
+ canonicalizer.indices = canonicalizer
+ .query_state
+ .var_values
+ .iter()
+ .enumerate()
+ .map(|(i, &kind)| (kind, BoundVar::new(i)))
+ .collect();
+ }
let out_value = value.fold_with(&mut canonicalizer);
// Once we have canonicalized `out_value`, it should not
@@ -613,7 +633,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
.max()
.unwrap_or(ty::UniverseIndex::ROOT);
- Canonical { max_universe, variables: canonical_variables, value: out_value }
+ Canonical { max_universe, variables: canonical_variables, value: (base.value, out_value) }
}
/// Creates a canonical variable replacing `kind` from the input,
@@ -762,11 +782,6 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
)
}
- /// Returns the universe in which `vid` is defined.
- fn region_var_universe(&self, vid: ty::RegionVid) -> ty::UniverseIndex {
- self.infcx.inner.borrow_mut().unwrap_region_constraints().var_universe(vid)
- }
-
/// Creates a canonical variable (with the given `info`)
/// representing the region `r`; return a region referencing it.
fn canonical_var_for_region(
@@ -776,7 +791,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
) -> ty::Region<'tcx> {
let var = self.canonical_var(info, r.into());
let br = ty::BoundRegion { var, kind: ty::BrAnon };
- ty::Region::new_late_bound(self.interner(), self.binder_index, br)
+ ty::Region::new_bound(self.interner(), self.binder_index, br)
}
/// Given a type variable `ty_var` of the given kind, first check
@@ -784,14 +799,9 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
/// *that*. Otherwise, create a new canonical variable for
/// `ty_var`.
fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo<'tcx>, ty_var: Ty<'tcx>) -> Ty<'tcx> {
- let infcx = self.infcx;
- let bound_to = infcx.shallow_resolve(ty_var);
- if bound_to != ty_var {
- self.fold_ty(bound_to)
- } else {
- let var = self.canonical_var(info, ty_var.into());
- Ty::new_bound(self.tcx, self.binder_index, var.into())
- }
+ debug_assert!(!self.infcx.is_some_and(|infcx| ty_var != infcx.shallow_resolve(ty_var)));
+ let var = self.canonical_var(info, ty_var.into());
+ Ty::new_bound(self.tcx, self.binder_index, var.into())
}
/// Given a type variable `const_var` of the given kind, first check
@@ -803,13 +813,10 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
info: CanonicalVarInfo<'tcx>,
const_var: ty::Const<'tcx>,
) -> ty::Const<'tcx> {
- let infcx = self.infcx;
- let bound_to = infcx.shallow_resolve(const_var);
- if bound_to != const_var {
- self.fold_const(bound_to)
- } else {
- let var = self.canonical_var(info, const_var.into());
- ty::Const::new_bound(self.tcx, self.binder_index, var, self.fold_ty(const_var.ty()))
- }
+ debug_assert!(
+ !self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve(const_var))
+ );
+ let var = self.canonical_var(info, const_var.into());
+ ty::Const::new_bound(self.tcx, self.binder_index, var, self.fold_ty(const_var.ty()))
}
}
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 3c4c4644f..386fdb09b 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -101,7 +101,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// variable, then you'll get a new inference variable; if it is a
/// universally quantified variable, you get a placeholder.
///
- /// FIXME(-Ztrait-solver=next): This is public because it's used by the
+ /// FIXME(-Znext-solver): This is public because it's used by the
/// new trait solver which has a different canonicalization routine.
/// We should somehow deduplicate all of this.
pub fn instantiate_canonical_var(
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index ed1010821..8cca4c623 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -166,10 +166,7 @@ impl<'tcx> InferCtxt<'tcx> {
}
fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
- std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
- .into_iter()
- .map(|(k, v)| (k, v.hidden_type.ty))
- .collect()
+ self.take_opaque_types().into_iter().map(|(k, v)| (k, v.hidden_type.ty)).collect()
}
/// Given the (canonicalized) result to a canonical query,
@@ -460,7 +457,7 @@ impl<'tcx> InferCtxt<'tcx> {
}
GenericArgKind::Lifetime(result_value) => {
// e.g., here `result_value` might be `'?1` in the example above...
- if let ty::ReLateBound(debruijn, br) = *result_value {
+ if let ty::ReBound(debruijn, br) = *result_value {
// ... in which case we would set `canonical_vars[0]` to `Some('static)`.
// We only allow a `ty::INNERMOST` index in substitutions.
@@ -552,7 +549,7 @@ impl<'tcx> InferCtxt<'tcx> {
// `query_response.var_values` after applying the substitution
// `result_subst`.
let substituted_query_response = |index: BoundVar| -> GenericArg<'tcx> {
- query_response.substitute_projected(self.tcx, &result_subst, |v| v.var_values[index])
+ query_response.substitute_projected(self.tcx, result_subst, |v| v.var_values[index])
};
// Unify the original value for each variable with the value
diff --git a/compiler/rustc_infer/src/infer/canonical/substitute.rs b/compiler/rustc_infer/src/infer/canonical/substitute.rs
index f368b30fb..e0b97bb16 100644
--- a/compiler/rustc_infer/src/infer/canonical/substitute.rs
+++ b/compiler/rustc_infer/src/infer/canonical/substitute.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable};
use rustc_middle::ty::GenericArgKind;
use rustc_middle::ty::{self, TyCtxt};
-/// FIXME(-Ztrait-solver=next): This or public because it is shared with the
+/// FIXME(-Znext-solver): This or public because it is shared with the
/// new trait solver implementation. We should deduplicate canonicalization.
pub trait CanonicalExt<'tcx, V> {
/// Instantiate the wrapped value, replacing each canonical value
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 26d071a01..d396c4100 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -131,13 +131,13 @@ pub struct TypeErrCtxt<'a, 'tcx> {
impl Drop for TypeErrCtxt<'_, '_> {
fn drop(&mut self) {
- if let Some(_) = self.infcx.tcx.sess.has_errors_or_delayed_span_bugs() {
+ if let Some(_) = self.infcx.tcx.sess.has_errors_or_span_delayed_bugs() {
// ok, emitted an error.
} else {
self.infcx
.tcx
.sess
- .delay_good_path_bug("used a `TypeErrCtxt` without raising an error or lint");
+ .good_path_delayed_bug("used a `TypeErrCtxt` without raising an error or lint");
}
}
}
@@ -155,7 +155,7 @@ impl TypeErrCtxt<'_, '_> {
impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> {
type Target = InferCtxt<'tcx>;
fn deref(&self) -> &InferCtxt<'tcx> {
- &self.infcx
+ self.infcx
}
}
@@ -168,17 +168,17 @@ pub(super) fn note_and_explain_region<'tcx>(
alt_span: Option<Span>,
) {
let (description, span) = match *region {
- ty::ReEarlyBound(_) | ty::ReFree(_) | ty::RePlaceholder(_) | ty::ReStatic => {
+ ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::RePlaceholder(_) | ty::ReStatic => {
msg_span_from_named_region(tcx, region, alt_span)
}
ty::ReError(_) => return,
// We shouldn't really be having unification failures with ReVar
- // and ReLateBound though.
- ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
- (format!("lifetime `{region}`"), alt_span)
- }
+ // and ReBound though.
+ //
+ // FIXME(@lcnr): Figure out whether this is reachable and if so, why.
+ ty::ReVar(_) | ty::ReBound(..) | ty::ReErased => (format!("lifetime `{region}`"), alt_span),
};
emit_msg_span(err, prefix, description, span, suffix);
@@ -202,7 +202,7 @@ fn msg_span_from_named_region<'tcx>(
alt_span: Option<Span>,
) -> (String, Option<Span>) {
match *region {
- ty::ReEarlyBound(ref br) => {
+ ty::ReEarlyParam(ref br) => {
let scope = region.free_region_binding_scope(tcx).expect_local();
let span = if let Some(param) =
tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
@@ -218,7 +218,7 @@ fn msg_span_from_named_region<'tcx>(
};
(text, Some(span))
}
- ty::ReFree(ref fr) => {
+ ty::ReLateParam(ref fr) => {
if !fr.bound_region.is_named()
&& let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region)
{
@@ -315,7 +315,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
// Explain the region we are capturing.
match *hidden_region {
- ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
+ ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => {
// Assuming regionck succeeded (*), we ought to always be
// capturing *some* region from the fn header, and hence it
// ought to be free. So under normal circumstances, we will go
@@ -517,7 +517,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.tcx
.sess
- .delay_span_bug(self.tcx.def_span(generic_param_scope), "expected region errors")
+ .span_delayed_bug(self.tcx.def_span(generic_param_scope), "expected region errors")
}
// This method goes through all the errors and try to group certain types
@@ -860,7 +860,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.suggest_boxing_for_return_impl_trait(
err,
ret_sp,
- prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s),
+ prior_arms.iter().chain(std::iter::once(&arm_span)).copied(),
);
}
}
@@ -891,7 +891,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
// don't suggest wrapping either blocks in `if .. {} else {}`
let is_empty_arm = |id| {
- let hir::Node::Block(blk) = self.tcx.hir().get(id) else {
+ let hir::Node::Block(blk) = self.tcx.hir_node(id) else {
return false;
};
if blk.expr.is_some() || !blk.stmts.is_empty() {
@@ -1019,8 +1019,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
/// ```
fn cmp_type_arg(
&self,
- mut t1_out: &mut DiagnosticStyledString,
- mut t2_out: &mut DiagnosticStyledString,
+ t1_out: &mut DiagnosticStyledString,
+ t2_out: &mut DiagnosticStyledString,
path: String,
sub: &'tcx [ty::GenericArg<'tcx>],
other_path: String,
@@ -1031,13 +1031,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let sub = self.tcx.mk_args(sub);
for (i, ta) in sub.types().enumerate() {
if ta == other_ty {
- self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, other_ty);
+ self.highlight_outer(t1_out, t2_out, path, sub, i, other_ty);
return Some(());
}
if let ty::Adt(def, _) = ta.kind() {
let path_ = self.tcx.def_path_str(def.did());
if path_ == other_path {
- self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, other_ty);
+ self.highlight_outer(t1_out, t2_out, path, sub, i, other_ty);
return Some(());
}
}
@@ -1181,37 +1181,54 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
debug!("cmp(t1={}, t1.kind={:?}, t2={}, t2.kind={:?})", t1, t1.kind(), t2, t2.kind());
// helper functions
- fn equals<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
- match (a.kind(), b.kind()) {
- (a, b) if *a == *b => true,
- (&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_)))
- | (
- &ty::Infer(ty::InferTy::IntVar(_)),
- &ty::Int(_) | &ty::Infer(ty::InferTy::IntVar(_)),
- )
- | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
- | (
- &ty::Infer(ty::InferTy::FloatVar(_)),
- &ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)),
- ) => true,
- _ => false,
+ let recurse = |t1, t2, values: &mut (DiagnosticStyledString, DiagnosticStyledString)| {
+ let (x1, x2) = self.cmp(t1, t2);
+ (values.0).0.extend(x1.0);
+ (values.1).0.extend(x2.0);
+ };
+
+ fn fmt_region<'tcx>(region: ty::Region<'tcx>) -> String {
+ let mut r = region.to_string();
+ if r == "'_" {
+ r.clear();
+ } else {
+ r.push(' ');
}
+ format!("&{r}")
}
- fn push_ty_ref<'tcx>(
+ fn push_ref<'tcx>(
region: ty::Region<'tcx>,
- ty: Ty<'tcx>,
mutbl: hir::Mutability,
s: &mut DiagnosticStyledString,
) {
- let mut r = region.to_string();
- if r == "'_" {
- r.clear();
+ s.push_highlighted(fmt_region(region));
+ s.push_highlighted(mutbl.prefix_str());
+ }
+
+ fn cmp_ty_refs<'tcx>(
+ r1: ty::Region<'tcx>,
+ mut1: hir::Mutability,
+ r2: ty::Region<'tcx>,
+ mut2: hir::Mutability,
+ ss: &mut (DiagnosticStyledString, DiagnosticStyledString),
+ ) {
+ let (r1, r2) = (fmt_region(r1), fmt_region(r2));
+ if r1 != r2 {
+ ss.0.push_highlighted(r1);
+ ss.1.push_highlighted(r2);
} else {
- r.push(' ');
+ ss.0.push_normal(r1);
+ ss.1.push_normal(r2);
+ }
+
+ if mut1 != mut2 {
+ ss.0.push_highlighted(mut1.prefix_str());
+ ss.1.push_highlighted(mut2.prefix_str());
+ } else {
+ ss.0.push_normal(mut1.prefix_str());
+ ss.1.push_normal(mut2.prefix_str());
}
- s.push_highlighted(format!("&{}{}", r, mutbl.prefix_str()));
- s.push_normal(ty.to_string());
}
// process starts here
@@ -1285,7 +1302,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if lifetimes.0 != lifetimes.1 {
values.0.push_highlighted(l1);
values.1.push_highlighted(l2);
- } else if lifetimes.0.is_late_bound() {
+ } else if lifetimes.0.is_bound() {
values.0.push_normal(l1);
values.1.push_normal(l2);
} else {
@@ -1310,9 +1327,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
values.0.push_normal("_");
values.1.push_normal("_");
} else {
- let (x1, x2) = self.cmp(ta1, ta2);
- (values.0).0.extend(x1.0);
- (values.1).0.extend(x2.0);
+ recurse(ta1, ta2, &mut values);
}
self.push_comma(&mut values.0, &mut values.1, len, i);
}
@@ -1418,27 +1433,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}
- // When finding T != &T, highlight only the borrow
- (&ty::Ref(r1, ref_ty1, mutbl1), _) if equals(ref_ty1, t2) => {
+ // When finding `&T != &T`, compare the references, then recurse into pointee type
+ (&ty::Ref(r1, ref_ty1, mutbl1), &ty::Ref(r2, ref_ty2, mutbl2)) => {
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
- push_ty_ref(r1, ref_ty1, mutbl1, &mut values.0);
- values.1.push_normal(t2.to_string());
+ cmp_ty_refs(r1, mutbl1, r2, mutbl2, &mut values);
+ recurse(ref_ty1, ref_ty2, &mut values);
values
}
- (_, &ty::Ref(r2, ref_ty2, mutbl2)) if equals(t1, ref_ty2) => {
+ // When finding T != &T, highlight the borrow
+ (&ty::Ref(r1, ref_ty1, mutbl1), _) => {
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
- values.0.push_normal(t1.to_string());
- push_ty_ref(r2, ref_ty2, mutbl2, &mut values.1);
+ push_ref(r1, mutbl1, &mut values.0);
+ recurse(ref_ty1, t2, &mut values);
values
}
-
- // When encountering &T != &mut T, highlight only the borrow
- (&ty::Ref(r1, ref_ty1, mutbl1), &ty::Ref(r2, ref_ty2, mutbl2))
- if equals(ref_ty1, ref_ty2) =>
- {
+ (_, &ty::Ref(r2, ref_ty2, mutbl2)) => {
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
- push_ty_ref(r1, ref_ty1, mutbl1, &mut values.0);
- push_ty_ref(r2, ref_ty2, mutbl2, &mut values.1);
+ push_ref(r2, mutbl2, &mut values.1);
+ recurse(t1, ref_ty2, &mut values);
values
}
@@ -1448,9 +1460,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
(DiagnosticStyledString::normal("("), DiagnosticStyledString::normal("("));
let len = args1.len();
for (i, (left, right)) in args1.iter().zip(args2).enumerate() {
- let (x1, x2) = self.cmp(left, right);
- (values.0).0.extend(x1.0);
- (values.1).0.extend(x2.0);
+ recurse(left, right, &mut values);
self.push_comma(&mut values.0, &mut values.1, len, i);
}
if len == 1 {
@@ -1667,9 +1677,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
.report(diag);
(false, Mismatch::Fixed("signature"))
}
- ValuePairs::TraitRefs(_) | ValuePairs::PolyTraitRefs(_) => {
- (false, Mismatch::Fixed("trait"))
- }
+ ValuePairs::PolyTraitRefs(_) => (false, Mismatch::Fixed("trait")),
ValuePairs::Aliases(infer::ExpectedFound { expected, .. }) => {
(false, Mismatch::Fixed(self.tcx.def_descr(expected.def_id)))
}
@@ -1735,7 +1743,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}
- if let Some((expected, found, exp_p, found_p)) = expected_found {
+ if let Some((expected, found, path)) = expected_found {
let (expected_label, found_label, exp_found) = match exp_found {
Mismatch::Variable(ef) => (
ef.expected.prefix_string(self.tcx),
@@ -1861,40 +1869,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
TypeError::Sorts(values) => {
let extra = expected == found;
- let sort_string = |ty: Ty<'tcx>, path: Option<PathBuf>| {
- let mut s = match (extra, ty.kind()) {
- (true, ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) => {
- let sm = self.tcx.sess.source_map();
- let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
- format!(
- " (opaque type at <{}:{}:{}>)",
- sm.filename_for_diagnostics(&pos.file.name),
- pos.line,
- pos.col.to_usize() + 1,
- )
- }
- (true, ty::Alias(ty::Projection, proj))
- if self.tcx.is_impl_trait_in_trait(proj.def_id) =>
- {
- let sm = self.tcx.sess.source_map();
- let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
- format!(
- " (trait associated opaque type at <{}:{}:{}>)",
- sm.filename_for_diagnostics(&pos.file.name),
- pos.line,
- pos.col.to_usize() + 1,
- )
- }
- (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
- (false, _) => "".to_string(),
- };
- if let Some(path) = path {
- s.push_str(&format!(
- "\nthe full type name has been written to '{}'",
- path.display(),
- ));
+ let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
+ (true, ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) => {
+ let sm = self.tcx.sess.source_map();
+ let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
+ format!(
+ " (opaque type at <{}:{}:{}>)",
+ sm.filename_for_diagnostics(&pos.file.name),
+ pos.line,
+ pos.col.to_usize() + 1,
+ )
}
- s
+ (true, ty::Alias(ty::Projection, proj))
+ if self.tcx.is_impl_trait_in_trait(proj.def_id) =>
+ {
+ let sm = self.tcx.sess.source_map();
+ let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
+ format!(
+ " (trait associated opaque type at <{}:{}:{}>)",
+ sm.filename_for_diagnostics(&pos.file.name),
+ pos.line,
+ pos.col.to_usize() + 1,
+ )
+ }
+ (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
+ (false, _) => "".to_string(),
};
if !(values.expected.is_simple_text(self.tcx)
&& values.found.is_simple_text(self.tcx))
@@ -1925,9 +1924,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
expected,
&found_label,
found,
- &sort_string(values.expected, exp_p),
- &sort_string(values.found, found_p),
+ &sort_string(values.expected),
+ &sort_string(values.found),
);
+ if let Some(path) = path {
+ diag.note(format!(
+ "the full type name has been written to '{}'",
+ path.display(),
+ ));
+ }
}
}
}
@@ -1999,7 +2004,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
diag.span_note(span, "this closure does not fulfill the lifetime requirements");
self.suggest_for_all_lifetime_closure(
span,
- self.tcx.hir().get_by_def_id(def_id),
+ self.tcx.hir_node_by_def_id(def_id),
&exp_found,
diag,
);
@@ -2093,7 +2098,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if let &(MatchExpressionArm(box MatchExpressionArmCause { source, .. })
| BlockTailExpression(.., source)) = code
&& let hir::MatchSource::TryDesugar(_) = source
- && let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values)
+ && let Some((expected_ty, found_ty, _)) = self.values_str(trace.values)
{
suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert {
found: found_ty.content(),
@@ -2113,7 +2118,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let TypeError::FixedArraySize(sz) = terr else {
return None;
};
- let tykind = match hir.find_by_def_id(trace.cause.body_id) {
+ let tykind = match self.tcx.opt_hir_node_by_def_id(trace.cause.body_id) {
Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => {
let body = hir.body(*body_id);
struct LetVisitor<'v> {
@@ -2211,33 +2216,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn values_str(
&self,
values: ValuePairs<'tcx>,
- ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
- {
+ ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>)> {
match values {
infer::Regions(exp_found) => self.expected_found_str(exp_found),
infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
infer::Aliases(exp_found) => self.expected_found_str(exp_found),
infer::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
infer::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
- infer::TraitRefs(exp_found) => {
- let pretty_exp_found = ty::error::ExpectedFound {
- expected: exp_found.expected.print_only_trait_path(),
- found: exp_found.found.print_only_trait_path(),
- };
- match self.expected_found_str(pretty_exp_found) {
- Some((expected, found, _, _)) if expected == found => {
- self.expected_found_str(exp_found)
- }
- ret => ret,
- }
- }
infer::PolyTraitRefs(exp_found) => {
let pretty_exp_found = ty::error::ExpectedFound {
- expected: exp_found.expected.print_only_trait_path(),
- found: exp_found.found.print_only_trait_path(),
+ expected: exp_found.expected.print_trait_sugared(),
+ found: exp_found.found.print_trait_sugared(),
};
match self.expected_found_str(pretty_exp_found) {
- Some((expected, found, _, _)) if expected == found => {
+ Some((expected, found, _)) if expected == found => {
self.expected_found_str(exp_found)
}
ret => ret,
@@ -2249,7 +2241,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
return None;
}
let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found);
- Some((exp, fnd, None, None))
+ Some((exp, fnd, None))
}
}
}
@@ -2257,8 +2249,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn expected_found_str_term(
&self,
exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
- ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
- {
+ ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>)> {
let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
@@ -2273,25 +2264,21 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let len = self.tcx.sess().diagnostic_width() + 40;
let exp_s = exp.content();
let fnd_s = fnd.content();
- let mut exp_p = None;
- let mut fnd_p = None;
+ let mut path = None;
if exp_s.len() > len {
- let (exp_s, exp_path) = self.tcx.short_ty_string(expected);
+ let exp_s = self.tcx.short_ty_string(expected, &mut path);
exp = DiagnosticStyledString::highlighted(exp_s);
- exp_p = exp_path;
}
if fnd_s.len() > len {
- let (fnd_s, fnd_path) = self.tcx.short_ty_string(found);
+ let fnd_s = self.tcx.short_ty_string(found, &mut path);
fnd = DiagnosticStyledString::highlighted(fnd_s);
- fnd_p = fnd_path;
}
- (exp, fnd, exp_p, fnd_p)
+ (exp, fnd, path)
}
_ => (
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
None,
- None,
),
})
}
@@ -2300,8 +2287,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
fn expected_found_str<T: fmt::Display + TypeFoldable<TyCtxt<'tcx>>>(
&self,
exp_found: ty::error::ExpectedFound<T>,
- ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
- {
+ ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>)> {
let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
@@ -2311,7 +2297,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
None,
- None,
))
}
@@ -2351,6 +2336,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let labeled_user_string = match bound_kind {
GenericKind::Param(ref p) => format!("the parameter type `{p}`"),
+ GenericKind::Placeholder(ref p) => format!("the placeholder type `{p:?}`"),
GenericKind::Alias(ref p) => match p.kind(self.tcx) {
ty::AliasKind::Projection | ty::AliasKind::Inherent => {
format!("the associated type `{p}`")
@@ -2364,7 +2350,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
span,
format!("{labeled_user_string} may not live long enough"),
match sub.kind() {
- ty::ReEarlyBound(_) | ty::ReFree(_) if sub.has_name() => error_code!(E0309),
+ ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => error_code!(E0309),
ty::ReStatic => error_code!(E0310),
_ => error_code!(E0311),
},
@@ -2372,7 +2358,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
'_explain: {
let (description, span) = match sub.kind() {
- ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
+ ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => {
msg_span_from_named_region(self.tcx, sub, Some(span))
}
_ => (format!("lifetime `{sub}`"), Some(span)),
@@ -2455,7 +2441,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if !suggs.is_empty() {
err.multipart_suggestion_verbose(
- format!("{msg}"),
+ msg,
suggs,
Applicability::MaybeIncorrect, // Issue #41966
);
@@ -2515,7 +2501,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let (lifetime_def_id, lifetime_scope) = match self.tcx.is_suitable_region(lifetime) {
Some(info) if !lifetime.has_name() => {
- (info.boundregion.get_id().unwrap().expect_local(), info.def_id)
+ (info.bound_region.get_id().unwrap().expect_local(), info.def_id)
}
_ => return lifetime.get_name_or_anon().to_string(),
};
@@ -2594,8 +2580,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if let infer::Subtype(ref sup_trace) = sup_origin
&& let infer::Subtype(ref sub_trace) = sub_origin
- && let Some((sup_expected, sup_found, _, _)) = self.values_str(sup_trace.values)
- && let Some((sub_expected, sub_found, _, _)) = self.values_str(sub_trace.values)
+ && let Some((sup_expected, sup_found, _)) = self.values_str(sup_trace.values)
+ && let Some((sub_expected, sub_found, _)) = self.values_str(sub_trace.values)
&& sub_expected == sup_expected
&& sub_found == sup_found
{
@@ -2667,11 +2653,6 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
self.0.tcx
}
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- // Unused, only for consts which we treat as always equal
- ty::ParamEnv::empty()
- }
-
fn tag(&self) -> &'static str {
"SameTypeModuloInfer"
}
@@ -2714,8 +2695,8 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
a: ty::Region<'tcx>,
b: ty::Region<'tcx>,
) -> RelateResult<'tcx, ty::Region<'tcx>> {
- if (a.is_var() && b.is_free_or_static())
- || (b.is_var() && a.is_free_or_static())
+ if (a.is_var() && b.is_free())
+ || (b.is_var() && a.is_free())
|| (a.is_var() && b.is_var())
|| a == b
{
@@ -2768,18 +2749,20 @@ impl<'tcx> InferCtxt<'tcx> {
infer::AddrOfRegion(_) => " for borrow expression".to_string(),
infer::Autoref(_) => " for autoref".to_string(),
infer::Coercion(_) => " for automatic coercion".to_string(),
- infer::LateBoundRegion(_, br, infer::FnCall) => {
+ infer::BoundRegion(_, br, infer::FnCall) => {
format!(" for lifetime parameter {}in function call", br_string(br))
}
- infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
+ infer::BoundRegion(_, br, infer::HigherRankedType) => {
format!(" for lifetime parameter {}in generic type", br_string(br))
}
- infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!(
+ infer::BoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!(
" for lifetime parameter {}in trait containing associated type `{}`",
br_string(br),
self.tcx.associated_item(def_id).name
),
- infer::EarlyBoundRegion(_, name) => format!(" for lifetime parameter `{name}`"),
+ infer::RegionParameterDefinition(_, name) => {
+ format!(" for lifetime parameter `{name}`")
+ }
infer::UpvarRegion(ref upvar_id, _) => {
let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
format!(" for capture of `{var_name}` by closure")
@@ -2906,9 +2889,6 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => {
"const is compatible with trait"
}
- ExprAssignable => "expression is assignable",
- IfExpression { .. } => "`if` and `else` have incompatible types",
- IfExpressionWithNoElse => "`if` missing an `else` returns `()`",
MainFunctionType => "`main` function has the correct type",
StartFunctionType => "`#[start]` function has the correct type",
LangFunctionType(_) => "lang item function has the correct type",
@@ -2929,9 +2909,6 @@ impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> {
CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => "method_compat",
CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => "type_compat",
CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => "const_compat",
- ExprAssignable => "expr_assignable",
- IfExpression { .. } => "if_else_different",
- IfExpressionWithNoElse => "no_else",
MainFunctionType => "fn_main_correct_type",
StartFunctionType => "fn_start_correct_type",
LangFunctionType(_) => "fn_lang_correct_type",
@@ -3004,7 +2981,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// Given a [`hir::HirId`] for a block, get the span of its last expression
/// or statement, peeling off any inner blocks.
pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
- match self.tcx.hir().get(hir_id) {
+ match self.tcx.hir_node(hir_id) {
hir::Node::Block(blk) => self.find_block_span(blk),
// The parser was in a weird state if either of these happen, but
// it's better not to panic.
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 4beb51da7..817a4451d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -232,7 +232,9 @@ fn ty_to_string<'tcx>(
/// something users are familiar with. Directly printing the `fn_sig` of closures also
/// doesn't work as they actually use the "rust-call" API.
fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
- let ty::Closure(_, args) = ty.kind() else { unreachable!() };
+ let ty::Closure(_, args) = ty.kind() else {
+ bug!("cannot convert non-closure to fn str in `closure_as_fn_str`")
+ };
let fn_sig = args.as_closure().sig();
let args = fn_sig
.inputs()
@@ -374,7 +376,7 @@ impl<'tcx> InferCtxt<'tcx> {
multi_suggestions,
bad_label,
}
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
+ .into_diagnostic(self.tcx.sess.dcx()),
TypeAnnotationNeeded::E0283 => AmbiguousImpl {
span,
source_kind,
@@ -384,7 +386,7 @@ impl<'tcx> InferCtxt<'tcx> {
multi_suggestions,
bad_label,
}
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
+ .into_diagnostic(self.tcx.sess.dcx()),
TypeAnnotationNeeded::E0284 => AmbiguousReturn {
span,
source_kind,
@@ -394,7 +396,7 @@ impl<'tcx> InferCtxt<'tcx> {
multi_suggestions,
bad_label,
}
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
+ .into_diagnostic(self.tcx.sess.dcx()),
}
}
}
@@ -419,7 +421,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
return self.bad_inference_failure_err(failure_span, arg_data, error_code);
};
- let mut local_visitor = FindInferSourceVisitor::new(&self, typeck_results, arg);
+ let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg);
if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(
self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(),
) {
@@ -581,7 +583,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
multi_suggestions,
bad_label: None,
}
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
+ .into_diagnostic(self.tcx.sess.dcx()),
TypeAnnotationNeeded::E0283 => AmbiguousImpl {
span,
source_kind,
@@ -591,7 +593,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
multi_suggestions,
bad_label: None,
}
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
+ .into_diagnostic(self.tcx.sess.dcx()),
TypeAnnotationNeeded::E0284 => AmbiguousReturn {
span,
source_kind,
@@ -601,7 +603,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
multi_suggestions,
bad_label: None,
}
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
+ .into_diagnostic(self.tcx.sess.dcx()),
}
}
}
@@ -1087,7 +1089,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
Box::new(segment.into_iter())
}
- hir::QPath::LangItem(_, _, _) => Box::new(iter::empty()),
+ hir::QPath::LangItem(_, _) => Box::new(iter::empty()),
}
}
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
index 1a60bab18..f56d5d7d3 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -70,9 +70,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let anon_reg_sub = self.tcx().is_suitable_region(sub)?;
let scope_def_id_sup = anon_reg_sup.def_id;
- let bregion_sup = anon_reg_sup.boundregion;
+ let bregion_sup = anon_reg_sup.bound_region;
let scope_def_id_sub = anon_reg_sub.def_id;
- let bregion_sub = anon_reg_sub.boundregion;
+ let bregion_sub = anon_reg_sub.bound_region;
let ty_sup = find_anon_type(self.tcx(), sup, &bregion_sup)?;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
index 0df417d09..4f74365d0 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -26,8 +26,7 @@ pub fn find_anon_type<'tcx>(
br: &ty::BoundRegionKind,
) -> Option<(&'tcx hir::Ty<'tcx>, &'tcx hir::FnSig<'tcx>)> {
let anon_reg = tcx.is_suitable_region(region)?;
- let hir_id = tcx.hir().local_def_id_to_hir_id(anon_reg.def_id);
- let fn_sig = tcx.hir().get(hir_id).fn_sig()?;
+ let fn_sig = tcx.hir_node_by_def_id(anon_reg.def_id).fn_sig()?;
fn_sig
.decl
@@ -96,7 +95,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
}
}
- hir::TyKind::Ref(ref lifetime, _) => {
+ hir::TyKind::Ref(lifetime, _) => {
// the lifetime of the Ref
let hir_id = lifetime.hir_id;
match (self.tcx.named_bound_var(hir_id), self.bound_region) {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
index 6901955af..df7907e1f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
@@ -81,7 +81,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
for matching_def_id in v.0 {
let mut hir_v =
super::static_impl_trait::HirTraitObjectVisitor(&mut traits, matching_def_id);
- hir_v.visit_ty(&impl_self_ty);
+ hir_v.visit_ty(impl_self_ty);
}
if traits.is_empty() {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index c38e5b8cd..d98ca995d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -197,11 +197,6 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
value_pairs: &ValuePairs<'tcx>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
let (expected_args, found_args, trait_def_id) = match value_pairs {
- ValuePairs::TraitRefs(ExpectedFound { expected, found })
- if expected.def_id == found.def_id =>
- {
- (expected.args, found.args, expected.def_id)
- }
ValuePairs::PolyTraitRefs(ExpectedFound { expected, found })
if expected.def_id() == found.def_id() =>
{
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index e2be6cf42..01b43f719 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -78,7 +78,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
has_impl_path,
impl_path,
});
- if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
+ if self.find_impl_on_dyn_trait(&mut err, param.param_ty, ctxt) {
let reported = err.emit();
return Some(reported);
} else {
@@ -204,7 +204,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
&& let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code()
// Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a
// `'static` lifetime when called as a method on a binding: `bar.qux()`.
- && self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt)
+ && self.find_impl_on_dyn_trait(&mut err, param.param_ty, ctxt)
{
override_error_code = Some(ctxt.assoc_item.name);
}
@@ -460,7 +460,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| {
if let Node::Item(Item {
kind: ItemKind::Impl(hir::Impl { self_ty, .. }), ..
- }) = tcx.hir().find_by_def_id(impl_did)?
+ }) = tcx.opt_hir_node_by_def_id(impl_did)?
&& trait_objects.iter().all(|did| {
// FIXME: we should check `self_ty` against the receiver
// type in the `UnifyReceiver` context, but for now, use
@@ -530,7 +530,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
for found_did in found_dids {
let mut traits = vec![];
let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did);
- hir_v.visit_ty(&self_ty);
+ hir_v.visit_ty(self_ty);
for &span in &traits {
let subdiag = DynTraitConstraintSuggestion { span, ident };
subdiag.add_to_diagnostic(err);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index cb51254a1..b16d5c509 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -101,7 +101,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
ty::AssocKind::Fn => {
let hir = self.tcx().hir();
if let Some(hir_id) =
- assoc_item.def_id.as_local().map(|id| hir.local_def_id_to_hir_id(id))
+ assoc_item.def_id.as_local().map(|id| self.tcx().local_def_id_to_hir_id(id))
{
if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) {
visitor.visit_fn_decl(decl);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
index be6d1a375..bfff00b94 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
@@ -41,8 +41,8 @@ pub fn find_param_with_region<'tcx>(
replace_region: Region<'tcx>,
) -> Option<AnonymousParamInfo<'tcx>> {
let (id, bound_region) = match *anon_region {
- ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
- ty::ReEarlyBound(ebr) => {
+ ty::ReLateParam(late_param) => (late_param.scope, late_param.bound_region),
+ ty::ReEarlyParam(ebr) => {
(tcx.parent(ebr.def_id), ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name))
}
_ => return None, // not a free region
@@ -50,11 +50,10 @@ pub fn find_param_with_region<'tcx>(
let hir = &tcx.hir();
let def_id = id.as_local()?;
- let hir_id = hir.local_def_id_to_hir_id(def_id);
// FIXME: use def_kind
// Don't perform this on closures
- match hir.get(hir_id) {
+ match tcx.hir_node_by_def_id(def_id) {
hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
return None;
}
@@ -161,7 +160,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
&& self
.tcx()
.opt_associated_item(scope_def_id.to_def_id())
- .map(|i| i.fn_has_self_parameter)
- == Some(true)
+ .is_some_and(|i| i.fn_has_self_parameter)
}
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 8d3cd23b7..859c10ef1 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -22,7 +22,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
span: trace.cause.span,
requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
- expected_found: self.values_str(trace.values).map(|(e, f, _, _)| (e, f)),
+ expected_found: self.values_str(trace.values).map(|(e, f, _)| (e, f)),
}
.add_to_diagnostic(err),
infer::Reborrow(span) => {
@@ -63,7 +63,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
.add_to_diagnostic(err);
}
infer::CheckAssociatedTypeBounds { ref parent, .. } => {
- self.note_region_origin(err, &parent);
+ self.note_region_origin(err, parent);
}
infer::AscribeUserTypeProvePredicate(span) => {
RegionOriginNote::Plain {
@@ -140,7 +140,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
span,
notes: reference_valid.into_iter().chain(content_valid).collect(),
}
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
+ .into_diagnostic(self.tcx.sess.dcx())
}
infer::RelateObjectBound(span) => {
let object_valid = note_and_explain::RegionExplanation::new(
@@ -161,7 +161,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
span,
notes: object_valid.into_iter().chain(pointer_valid).collect(),
}
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
+ .into_diagnostic(self.tcx.sess.dcx())
}
infer::RelateParamBound(span, ty, opt_span) => {
let prefix = match *sub {
@@ -177,7 +177,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.tcx, sub, opt_span, prefix, suffix,
);
FulfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note }
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
+ .into_diagnostic(self.tcx.sess.dcx())
}
infer::RelateRegionParamBound(span) => {
let param_instantiated = note_and_explain::RegionExplanation::new(
@@ -198,7 +198,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
span,
notes: param_instantiated.into_iter().chain(param_must_outlive).collect(),
}
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
+ .into_diagnostic(self.tcx.sess.dcx())
}
infer::ReferenceOutlivesReferent(ty, span) => {
let pointer_valid = note_and_explain::RegionExplanation::new(
@@ -220,7 +220,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
ty: self.resolve_vars_if_possible(ty),
notes: pointer_valid.into_iter().chain(data_valid).collect(),
}
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
+ .into_diagnostic(self.tcx.sess.dcx())
}
infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
let mut err = self.report_extra_impl_obligation(
@@ -281,7 +281,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
span,
notes: instantiated.into_iter().chain(must_outlive).collect(),
}
- .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
+ .into_diagnostic(self.tcx.sess.dcx())
}
};
if sub.is_error() || sup.is_error() {
@@ -375,7 +375,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err.span_note(span, "the lifetime requirement is introduced here");
err
} else {
- unreachable!()
+ unreachable!(
+ "control flow ensures we have a `BindingObligation` or `ExprBindingObligation` here..."
+ )
}
}
infer::Subtype(box trace) => {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index a8ae43d52..afb3c5c1e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -87,7 +87,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
| (ty::Alias(ty::Projection, proj), ty::Param(p))
if !tcx.is_impl_trait_in_trait(proj.def_id) =>
{
- let parent = tcx.generics_of(body_owner_def_id)
+ let parent = tcx
+ .generics_of(body_owner_def_id)
.opt_type_param(p, tcx)
.and_then(|param| {
let p_def_id = param.def_id;
@@ -104,7 +105,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
);
}
p_def_id.as_local().and_then(|id| {
- let local_id = tcx.hir().local_def_id_to_hir_id(id);
+ let local_id = tcx.local_def_id_to_hir_id(id);
let generics = tcx.hir().find_parent(local_id)?.generics()?;
Some((id, generics))
})
@@ -654,7 +655,7 @@ fn foo(&self) -> Self::T { String::new() }
// When `body_owner` is an `impl` or `trait` item, look in its associated types for
// `expected` and point at it.
let parent_id = tcx.hir().get_parent_item(hir_id);
- let item = tcx.hir().find_by_def_id(parent_id.def_id);
+ let item = tcx.opt_hir_node_by_def_id(parent_id.def_id);
debug!("expected_projection parent item {:?}", item);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index fe18d0029..bbe07b8ed 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -42,7 +42,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
]
.into_iter()
.find_map(|(id, ty)| {
- let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
+ let hir::Node::Block(blk) = self.tcx.hir_node(id?) else { return None };
self.could_remove_semicolon(blk, ty)
});
match remove_semicolon {
@@ -62,7 +62,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let mut ret = None;
for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
if let Some(id) = id
- && let hir::Node::Block(blk) = self.tcx.hir().get(id)
+ && let hir::Node::Block(blk) = self.tcx.hir_node(id)
&& let Some(diag) = self.consider_returning_binding_diag(blk, ty)
{
ret = Some(diag);
@@ -511,7 +511,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
- visitor.visit_body(&body);
+ visitor.visit_body(body);
if visitor.result {
return Some(TypeErrorAdditionalDiags::AddLetForLetChains {
span: span.shrink_to_lo(),
@@ -572,8 +572,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if let ty::Ref(expected_region, _, _) = expected.kind()
&& let ty::Ref(found_region, _, _) = found.kind()
- && expected_region.is_late_bound()
- && !found_region.is_late_bound()
+ && expected_region.is_bound()
+ && !found_region.is_bound()
&& let hir::TyKind::Infer = arg_hir.kind
{
// If the expected region is late bound, the found region is not, and users are asking compiler
@@ -636,10 +636,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
return None;
}
let last_stmt = blk.stmts.last()?;
- let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else {
+ let hir::StmtKind::Semi(last_expr) = last_stmt.kind else {
return None;
};
- let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(*last_expr)?;
+ let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(last_expr)?;
let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
_ if last_expr_ty.references_error() => return None,
_ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
@@ -668,26 +668,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
(
hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }),
- ) if std::iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| {
- match (left, right) {
- (
- hir::GenericBound::Trait(tl, ml),
- hir::GenericBound::Trait(tr, mr),
- ) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
+ ) if std::iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| match (
+ left, right,
+ ) {
+ (hir::GenericBound::Trait(tl, ml), hir::GenericBound::Trait(tr, mr))
+ if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
&& ml == mr =>
- {
- true
- }
- (
- hir::GenericBound::LangItemTrait(langl, _, _, argsl),
- hir::GenericBound::LangItemTrait(langr, _, _, argsr),
- ) if langl == langr => {
- // FIXME: consider the bounds!
- debug!("{:?} {:?}", argsl, argsr);
- true
- }
- _ => false,
+ {
+ true
}
+ _ => false,
}) =>
{
StatementAsExpression::NeedsBoxing
diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs
index ed1a2a117..0dde3082d 100644
--- a/compiler/rustc_infer/src/infer/free_regions.rs
+++ b/compiler/rustc_infer/src/infer/free_regions.rs
@@ -22,8 +22,8 @@ impl<'a, 'tcx> RegionRelations<'a, 'tcx> {
Self { tcx, free_regions }
}
- pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> {
- self.free_regions.lub_free_regions(self.tcx, r_a, r_b)
+ pub fn lub_param_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> {
+ self.free_regions.lub_param_regions(self.tcx, r_a, r_b)
}
}
@@ -59,7 +59,7 @@ impl<'tcx> FreeRegionMap<'tcx> {
r_a: Region<'tcx>,
r_b: Region<'tcx>,
) -> bool {
- assert!(r_a.is_free_or_static() && r_b.is_free_or_static());
+ assert!(r_a.is_free() && r_b.is_free());
let re_static = tcx.lifetimes.re_static;
if self.check_relation(re_static, r_b) {
// `'a <= 'static` is always true, and not stored in the
@@ -80,15 +80,15 @@ impl<'tcx> FreeRegionMap<'tcx> {
/// cases, this is more conservative than necessary, in order to
/// avoid making arbitrary choices. See
/// `TransitiveRelation::postdom_upper_bound` for more details.
- pub fn lub_free_regions(
+ pub fn lub_param_regions(
&self,
tcx: TyCtxt<'tcx>,
r_a: Region<'tcx>,
r_b: Region<'tcx>,
) -> Region<'tcx> {
- debug!("lub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b);
- assert!(r_a.is_free());
- assert!(r_b.is_free());
+ debug!("lub_param_regions(r_a={:?}, r_b={:?})", r_a, r_b);
+ assert!(r_a.is_param());
+ assert!(r_b.is_param());
let result = if r_a == r_b {
r_a
} else {
@@ -97,7 +97,7 @@ impl<'tcx> FreeRegionMap<'tcx> {
Some(r) => r,
}
};
- debug!("lub_free_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result);
+ debug!("lub_param_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result);
result
}
}
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index 35204478c..11ab86277 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -110,13 +110,13 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
- ty::ReLateBound(..) => {
+ ty::ReBound(..) => {
// leave bound regions alone
r
}
- ty::ReEarlyBound(..)
- | ty::ReFree(_)
+ ty::ReEarlyParam(..)
+ | ty::ReLateParam(_)
| ty::ReVar(_)
| ty::RePlaceholder(..)
| ty::ReStatic
diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs
index 7e878ac06..8ca97ae1b 100644
--- a/compiler/rustc_infer/src/infer/fudge.rs
+++ b/compiler/rustc_infer/src/infer/fudge.rs
@@ -187,7 +187,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
if self.type_vars.0.contains(&vid) {
// This variable was created during the fudging.
// Recreate it with a fresh variable here.
- let idx = (vid.as_usize() - self.type_vars.0.start.as_usize()) as usize;
+ let idx = vid.as_usize() - self.type_vars.0.start.as_usize();
let origin = self.type_vars.1[idx];
self.infcx.next_ty_var(origin)
} else {
@@ -236,7 +236,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
if self.const_vars.0.contains(&vid) {
// This variable was created during the fudging.
// Recreate it with a fresh variable here.
- let idx = (vid.index() - self.const_vars.0.start.index()) as usize;
+ let idx = vid.index() - self.const_vars.0.start.index();
let origin = self.const_vars.1[idx];
self.infcx.next_const_var(ct.ty(), origin)
} else {
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index bee0a978a..0fbc4a0ce 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -16,8 +16,8 @@ use rustc_data_structures::intern::Interned;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{ReEarlyBound, ReErased, ReError, ReFree, ReStatic};
-use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
+use rustc_middle::ty::{ReBound, RePlaceholder, ReVar};
+use rustc_middle::ty::{ReEarlyParam, ReErased, ReError, ReLateParam, ReStatic};
use rustc_middle::ty::{Region, RegionVid};
use rustc_span::Span;
use std::fmt;
@@ -31,13 +31,12 @@ use super::outlives::test_type_match;
/// all the variables as well as a set of errors that must be reported.
#[instrument(level = "debug", skip(region_rels, var_infos, data))]
pub(crate) fn resolve<'tcx>(
- param_env: ty::ParamEnv<'tcx>,
region_rels: &RegionRelations<'_, 'tcx>,
var_infos: VarInfos,
data: RegionConstraintData<'tcx>,
) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
let mut errors = vec![];
- let mut resolver = LexicalResolver { param_env, region_rels, var_infos, data };
+ let mut resolver = LexicalResolver { region_rels, var_infos, data };
let values = resolver.infer_variable_values(&mut errors);
(values, errors)
}
@@ -120,7 +119,6 @@ struct RegionAndOrigin<'tcx> {
type RegionGraph<'tcx> = Graph<(), Constraint<'tcx>>;
struct LexicalResolver<'cx, 'tcx> {
- param_env: ty::ParamEnv<'tcx>,
region_rels: &'cx RegionRelations<'cx, 'tcx>,
var_infos: VarInfos,
data: RegionConstraintData<'tcx>,
@@ -378,7 +376,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// so it doesn't really matter if it's shorter or longer than an empty region
ReError(_) => false,
- ReLateBound(..) | ReErased => {
+ ReBound(..) | ReErased => {
bug!("cannot relate region: {:?}", a);
}
@@ -390,7 +388,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
);
}
- ReStatic | ReEarlyBound(_) | ReFree(_) => {
+ ReStatic | ReEarlyParam(_) | ReLateParam(_) => {
// nothing lives longer than `'static`
// All empty regions are less than early-bound, free,
@@ -411,7 +409,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// so it doesn't really matter if it's shorter or longer than an empty region
ReError(_) => false,
- ReLateBound(..) | ReErased => {
+ ReBound(..) | ReErased => {
bug!("cannot relate region: {:?}", b);
}
@@ -423,9 +421,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
);
}
- ReStatic | ReEarlyBound(_) | ReFree(_) => {
+ ReStatic | ReEarlyParam(_) | ReLateParam(_) => {
// nothing lives longer than `'static`
- // All empty regions are less than early-bound, free,
+ // All empty regions are less than early-bound, late-bound,
// and scope regions.
true
}
@@ -450,8 +448,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// Check for the case where we know that `'b: 'static` -- in that case,
// `a <= b` for all `a`.
- let b_free_or_static = b.is_free_or_static();
- if b_free_or_static && sub_free_regions(tcx.lifetimes.re_static, b) {
+ if b.is_free() && sub_free_regions(tcx.lifetimes.re_static, b) {
return true;
}
@@ -460,8 +457,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// `lub` relationship defined below, since sometimes the "lub"
// is actually the `postdom_upper_bound` (see
// `TransitiveRelation` for more details).
- let a_free_or_static = a.is_free_or_static();
- if a_free_or_static && b_free_or_static {
+ if a.is_free() && b.is_free() {
return sub_free_regions(a, b);
}
@@ -478,7 +474,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
#[instrument(level = "trace", skip(self), ret)]
fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
match (*a, *b) {
- (ReLateBound(..), _) | (_, ReLateBound(..)) | (ReErased, _) | (_, ReErased) => {
+ (ReBound(..), _) | (_, ReBound(..)) | (ReErased, _) | (_, ReErased) => {
bug!("cannot relate region: LUB({:?}, {:?})", a, b);
}
@@ -501,8 +497,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
self.tcx().lifetimes.re_static
}
- (ReEarlyBound(_) | ReFree(_), ReEarlyBound(_) | ReFree(_)) => {
- self.region_rels.lub_free_regions(a, b)
+ (ReEarlyParam(_) | ReLateParam(_), ReEarlyParam(_) | ReLateParam(_)) => {
+ self.region_rels.lub_param_regions(a, b)
}
// For these types, we cannot define any additional
@@ -683,17 +679,13 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
for constraint in self.data.constraints.keys() {
match *constraint {
Constraint::VarSubVar(a_id, b_id) => {
- graph.add_edge(
- NodeIndex(a_id.index() as usize),
- NodeIndex(b_id.index() as usize),
- *constraint,
- );
+ graph.add_edge(NodeIndex(a_id.index()), NodeIndex(b_id.index()), *constraint);
}
Constraint::RegSubVar(_, b_id) => {
- graph.add_edge(dummy_source, NodeIndex(b_id.index() as usize), *constraint);
+ graph.add_edge(dummy_source, NodeIndex(b_id.index()), *constraint);
}
Constraint::VarSubReg(a_id, _) => {
- graph.add_edge(NodeIndex(a_id.index() as usize), dummy_sink, *constraint);
+ graph.add_edge(NodeIndex(a_id.index()), dummy_sink, *constraint);
}
Constraint::RegSubReg(..) => {
// this would be an edge from `dummy_source` to
@@ -723,13 +715,13 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
return;
}
- // We place free regions first because we are special casing
- // SubSupConflict(ReFree, ReFree) when reporting error, and so
+ // We place late-bound regions first because we are special casing
+ // SubSupConflict(ReLateParam, ReLateParam) when reporting error, and so
// the user will more likely get a specific suggestion.
fn region_order_key(x: &RegionAndOrigin<'_>) -> u8 {
match *x.region {
- ReEarlyBound(_) => 0,
- ReFree(_) => 1,
+ ReEarlyParam(_) => 0,
+ ReLateParam(_) => 1,
_ => 2,
}
}
@@ -804,7 +796,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// Errors in earlier passes can yield error variables without
// resolution errors here; delay ICE in favor of those errors.
- self.tcx().sess.delay_span_bug(
+ self.tcx().sess.span_delayed_bug(
self.var_infos[node_idx].origin.span(),
format!(
"collect_error_for_expanding_node() could not find \
@@ -880,7 +872,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
) {
debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir);
- let source_node_index = NodeIndex(source_vid.index() as usize);
+ let source_node_index = NodeIndex(source_vid.index());
for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
match edge.data {
Constraint::VarSubVar(from_vid, to_vid) => {
@@ -920,12 +912,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
match bound {
VerifyBound::IfEq(verify_if_eq_b) => {
let verify_if_eq_b = var_values.normalize(self.region_rels.tcx, *verify_if_eq_b);
- match test_type_match::extract_verify_if_eq(
- self.tcx(),
- self.param_env,
- &verify_if_eq_b,
- generic_ty,
- ) {
+ match test_type_match::extract_verify_if_eq(self.tcx(), &verify_if_eq_b, generic_ty)
+ {
Some(r) => {
self.bound_is_met(&VerifyBound::OutlivedBy(r), var_values, generic_ty, min)
}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 4ee897ffe..e092bbbfd 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1,11 +1,11 @@
pub use self::at::DefineOpaqueTypes;
pub use self::freshen::TypeFreshener;
pub use self::lexical_region_resolve::RegionResolutionError;
-pub use self::LateBoundRegionConversionTime::*;
+pub use self::BoundRegionConversionTime::*;
pub use self::RegionVariableOrigin::*;
pub use self::SubregionOrigin::*;
pub use self::ValuePairs::*;
-pub use combine::ObligationEmittingRelation;
+pub use relate::combine::ObligationEmittingRelation;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::undo_log::UndoLogs;
use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
@@ -32,7 +32,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BoundVarReplacerDelegate;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::relate::RelateResult;
-use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
+use rustc_middle::ty::visit::TypeVisitableExt;
pub use rustc_middle::ty::IntVarValue;
use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt};
use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
@@ -43,7 +43,6 @@ use rustc_span::{Span, DUMMY_SP};
use std::cell::{Cell, RefCell};
use std::fmt;
-use self::combine::CombineFields;
use self::error_reporting::TypeErrCtxt;
use self::free_regions::RegionRelations;
use self::lexical_region_resolve::LexicalRegionResolutions;
@@ -51,29 +50,23 @@ use self::region_constraints::{GenericKind, VarInfos, VerifyBound};
use self::region_constraints::{
RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot,
};
+pub use self::relate::combine::CombineFields;
+pub use self::relate::nll as nll_relate;
use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
pub mod at;
pub mod canonical;
-mod combine;
-mod equate;
pub mod error_reporting;
pub mod free_regions;
mod freshen;
mod fudge;
-mod generalize;
-mod glb;
-mod higher_ranked;
-pub mod lattice;
mod lexical_region_resolve;
-mod lub;
-pub mod nll_relate;
pub mod opaque_types;
pub mod outlives;
mod projection;
pub mod region_constraints;
+mod relate;
pub mod resolve;
-mod sub;
pub mod type_variable;
mod undo_log;
@@ -98,6 +91,8 @@ pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable<
/// call to `start_snapshot` and `rollback_to`.
#[derive(Clone)]
pub struct InferCtxtInner<'tcx> {
+ undo_log: InferCtxtUndoLogs<'tcx>,
+
/// Cache for projections.
///
/// This cache is snapshotted along with the infcx.
@@ -162,8 +157,6 @@ pub struct InferCtxtInner<'tcx> {
/// that all type inference variables have been bound and so forth.
region_obligations: Vec<RegionObligation<'tcx>>,
- undo_log: InferCtxtUndoLogs<'tcx>,
-
/// Caches for opaque type inference.
opaque_type_storage: OpaqueTypeStorage<'tcx>,
}
@@ -171,9 +164,10 @@ pub struct InferCtxtInner<'tcx> {
impl<'tcx> InferCtxtInner<'tcx> {
fn new() -> InferCtxtInner<'tcx> {
InferCtxtInner {
+ undo_log: InferCtxtUndoLogs::default(),
+
projection_cache: Default::default(),
type_variable_storage: type_variable::TypeVariableStorage::new(),
- undo_log: InferCtxtUndoLogs::default(),
const_unification_storage: ut::UnificationTableStorage::new(),
int_unification_storage: ut::UnificationTableStorage::new(),
float_unification_storage: ut::UnificationTableStorage::new(),
@@ -345,37 +339,57 @@ pub struct InferCtxt<'tcx> {
impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
type Interner = TyCtxt<'tcx>;
- fn universe_of_ty(&self, ty: ty::InferTy) -> Option<ty::UniverseIndex> {
- use InferTy::*;
- match ty {
- // FIXME(BoxyUwU): this is kind of jank and means that printing unresolved
- // ty infers will give you the universe of the var it resolved to not the universe
- // it actually had. It also means that if you have a `?0.1` and infer it to `u8` then
- // try to print out `?0.1` it will just print `?0`.
- TyVar(ty_vid) => match self.probe_ty_var(ty_vid) {
- Err(universe) => Some(universe),
- Ok(_) => None,
- },
- IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => None,
+ fn interner(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn universe_of_ty(&self, vid: TyVid) -> Option<ty::UniverseIndex> {
+ // FIXME(BoxyUwU): this is kind of jank and means that printing unresolved
+ // ty infers will give you the universe of the var it resolved to not the universe
+ // it actually had. It also means that if you have a `?0.1` and infer it to `u8` then
+ // try to print out `?0.1` it will just print `?0`.
+ match self.probe_ty_var(vid) {
+ Err(universe) => Some(universe),
+ Ok(_) => None,
}
}
- fn universe_of_ct(&self, ct: ty::InferConst) -> Option<ty::UniverseIndex> {
- use ty::InferConst::*;
- match ct {
- // Same issue as with `universe_of_ty`
- Var(ct_vid) => match self.probe_const_var(ct_vid) {
- Err(universe) => Some(universe),
- Ok(_) => None,
- },
- EffectVar(_) => None,
- Fresh(_) => None,
+ fn universe_of_ct(&self, ct: ConstVid) -> Option<ty::UniverseIndex> {
+ // Same issue as with `universe_of_ty`
+ match self.probe_const_var(ct) {
+ Err(universe) => Some(universe),
+ Ok(_) => None,
}
}
fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
Some(self.universe_of_region_vid(lt))
}
+
+ fn root_ty_var(&self, vid: TyVid) -> TyVid {
+ self.root_var(vid)
+ }
+
+ fn probe_ty_var(&self, vid: TyVid) -> Option<Ty<'tcx>> {
+ self.probe_ty_var(vid).ok()
+ }
+
+ fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> Option<ty::Region<'tcx>> {
+ let re = self
+ .inner
+ .borrow_mut()
+ .unwrap_region_constraints()
+ .opportunistic_resolve_var(self.tcx, vid);
+ if *re == ty::ReVar(vid) { None } else { Some(re) }
+ }
+
+ fn root_ct_var(&self, vid: ConstVid) -> ConstVid {
+ self.root_const_var(vid)
+ }
+
+ fn probe_ct_var(&self, vid: ConstVid) -> Option<ty::Const<'tcx>> {
+ self.probe_const_var(vid).ok()
+ }
}
/// See the `error_reporting` module for more details.
@@ -384,7 +398,6 @@ pub enum ValuePairs<'tcx> {
Regions(ExpectedFound<ty::Region<'tcx>>),
Terms(ExpectedFound<ty::Term<'tcx>>),
Aliases(ExpectedFound<ty::AliasTy<'tcx>>),
- TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
@@ -472,9 +485,9 @@ impl<'tcx> SubregionOrigin<'tcx> {
}
}
-/// Times when we replace late-bound regions with variables:
+/// Times when we replace bound regions with existentials:
#[derive(Clone, Copy, Debug)]
-pub enum LateBoundRegionConversionTime {
+pub enum BoundRegionConversionTime {
/// when a fn is called
FnCall,
@@ -508,11 +521,14 @@ pub enum RegionVariableOrigin {
Coercion(Span),
/// Region variables created as the values for early-bound regions.
- EarlyBoundRegion(Span, Symbol),
+ ///
+ /// FIXME(@lcnr): This can also store a `DefId`, similar to
+ /// `TypeVariableOriginKind::TypeParameterDefinition`.
+ RegionParameterDefinition(Span, Symbol),
- /// Region variables created for bound regions
- /// in a function or method that is called.
- LateBoundRegion(Span, ty::BoundRegionKind, LateBoundRegionConversionTime),
+ /// Region variables created when instantiating a binder with
+ /// existential variables, e.g. when calling a function or method.
+ BoundRegion(Span, ty::BoundRegionKind, BoundRegionConversionTime),
UpvarRegion(ty::UpvarId, Span),
@@ -697,10 +713,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
}
impl<'tcx, T> InferOk<'tcx, T> {
- pub fn unit(self) -> InferOk<'tcx, ()> {
- InferOk { value: (), obligations: self.obligations }
- }
-
/// Extracts `value`, registering any obligations into `fulfill_cx`.
pub fn into_value_registering_obligations(
self,
@@ -757,7 +769,7 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn type_var_origin(&self, ty: Ty<'tcx>) -> Option<TypeVariableOrigin> {
match *ty.kind() {
ty::Infer(ty::TyVar(vid)) => {
- Some(*self.inner.borrow_mut().type_variables().var_origin(vid))
+ Some(self.inner.borrow_mut().type_variables().var_origin(vid))
}
_ => None,
}
@@ -767,11 +779,11 @@ impl<'tcx> InferCtxt<'tcx> {
freshen::TypeFreshener::new(self)
}
- pub fn unsolved_variables(&self) -> Vec<Ty<'tcx>> {
+ pub fn unresolved_variables(&self) -> Vec<Ty<'tcx>> {
let mut inner = self.inner.borrow_mut();
let mut vars: Vec<Ty<'_>> = inner
.type_variables()
- .unsolved_variables()
+ .unresolved_variables()
.into_iter()
.map(|t| Ty::new_var(self.tcx, t))
.collect();
@@ -903,12 +915,14 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
}
- pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
+ pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool
where
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
- self.probe(|_| self.at(origin, param_env).sub(DefineOpaqueTypes::No, a, b).is_ok())
+ self.probe(|_| {
+ self.at(origin, param_env).sub(DefineOpaqueTypes::No, expected, actual).is_ok()
+ })
}
pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
@@ -1007,15 +1021,10 @@ impl<'tcx> InferCtxt<'tcx> {
_ => {}
}
- Ok(self.commit_if_ok(|_snapshot| {
- let ty::SubtypePredicate { a_is_expected, a, b } =
- self.instantiate_binder_with_placeholders(predicate);
-
- let ok =
- self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b)?;
+ let ty::SubtypePredicate { a_is_expected, a, b } =
+ self.instantiate_binder_with_placeholders(predicate);
- Ok(ok.unit())
- }))
+ Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b))
}
pub fn region_outlives_predicate(
@@ -1165,7 +1174,7 @@ impl<'tcx> InferCtxt<'tcx> {
GenericParamDefKind::Lifetime => {
// Create a region inference variable for the given
// region parameter definition.
- self.next_region_var(EarlyBoundRegion(span, param.name)).into()
+ self.next_region_var(RegionParameterDefinition(span, param.name)).into()
}
GenericParamDefKind::Type { .. } => {
// Create a type inference variable for the given
@@ -1278,12 +1287,7 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn region_var_origin(&self, vid: ty::RegionVid) -> RegionVariableOrigin {
let mut inner = self.inner.borrow_mut();
let inner = &mut *inner;
- inner
- .region_constraint_storage
- .as_mut()
- .expect("regions already resolved")
- .with_log(&mut inner.undo_log)
- .var_origin(vid)
+ inner.unwrap_region_constraints().var_origin(vid)
}
/// Clone the list of variable regions. This is used only during NLL processing
@@ -1401,17 +1405,6 @@ impl<'tcx> InferCtxt<'tcx> {
value.fold_with(&mut r)
}
- /// Returns the first unresolved type or const variable contained in `T`.
- pub fn first_unresolved_const_or_ty_var<T>(
- &self,
- value: &T,
- ) -> Option<(ty::Term<'tcx>, Option<Span>)>
- where
- T: TypeVisitable<TyCtxt<'tcx>>,
- {
- value.visit_with(&mut resolve::UnresolvedTypeOrConstFinder::new(self)).break_value()
- }
-
pub fn probe_const_var(&self, vid: ty::ConstVid) -> Result<ty::Const<'tcx>, ty::UniverseIndex> {
match self.inner.borrow_mut().const_unification_table().probe_value(vid).val {
ConstVariableValue::Known { value } => Ok(value),
@@ -1440,7 +1433,7 @@ impl<'tcx> InferCtxt<'tcx> {
let guar = self
.tcx
.sess
- .delay_span_bug(DUMMY_SP, format!("`{value:?}` is not fully resolved"));
+ .span_delayed_bug(DUMMY_SP, format!("`{value:?}` is not fully resolved"));
Ok(self.tcx.fold_regions(value, |re, _| {
if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re }
}))
@@ -1456,13 +1449,13 @@ impl<'tcx> InferCtxt<'tcx> {
// variables in the current universe.
//
// Use this method if you'd like to find some substitution of the binder's
- // variables (e.g. during a method call). If there isn't a [`LateBoundRegionConversionTime`]
+ // variables (e.g. during a method call). If there isn't a [`BoundRegionConversionTime`]
// that corresponds to your use case, consider whether or not you should
// use [`InferCtxt::instantiate_binder_with_placeholders`] instead.
pub fn instantiate_binder_with_fresh_vars<T>(
&self,
span: Span,
- lbrct: LateBoundRegionConversionTime,
+ lbrct: BoundRegionConversionTime,
value: ty::Binder<'tcx, T>,
) -> T
where
@@ -1475,7 +1468,7 @@ impl<'tcx> InferCtxt<'tcx> {
struct ToFreshVars<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
span: Span,
- lbrct: LateBoundRegionConversionTime,
+ lbrct: BoundRegionConversionTime,
map: FxHashMap<ty::BoundVar, ty::GenericArg<'tcx>>,
}
@@ -1485,7 +1478,7 @@ impl<'tcx> InferCtxt<'tcx> {
.entry(br.var)
.or_insert_with(|| {
self.infcx
- .next_region_var(LateBoundRegion(self.span, br.kind, self.lbrct))
+ .next_region_var(BoundRegion(self.span, br.kind, self.lbrct))
.into()
})
.expect_region()
@@ -2041,8 +2034,8 @@ impl RegionVariableOrigin {
| AddrOfRegion(a)
| Autoref(a)
| Coercion(a)
- | EarlyBoundRegion(a, ..)
- | LateBoundRegion(a, ..)
+ | RegionParameterDefinition(a, ..)
+ | BoundRegion(a, ..)
| UpvarRegion(_, a) => a,
Nll(..) => bug!("NLL variable used with `span`"),
}
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 7a5dec22f..a492c6bf9 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -374,7 +374,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// in its defining scope.
#[instrument(skip(self), level = "trace", ret)]
pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
- let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
+ let opaque_hir_id = self.tcx.local_def_id_to_hir_id(def_id);
let parent_def_id = match self.defining_use_anchor {
DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
DefiningAnchor::Bind(bind) => bind,
@@ -432,7 +432,7 @@ where
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
match *r {
// ignore bound regions, keep visiting
- ty::ReLateBound(_, _) => ControlFlow::Continue(()),
+ ty::ReBound(_, _) => ControlFlow::Continue(()),
_ => {
(self.op)(r);
ControlFlow::Continue(())
@@ -447,7 +447,7 @@ where
}
match ty.kind() {
- ty::Closure(_, ref args) => {
+ ty::Closure(_, args) => {
// Skip lifetime parameters of the enclosing item(s)
for upvar in args.as_closure().upvar_tys() {
@@ -456,7 +456,7 @@ where
args.as_closure().sig_as_fn_ptr_ty().visit_with(self);
}
- ty::Coroutine(_, ref args, _) => {
+ ty::Coroutine(_, args, _) => {
// Skip lifetime parameters of the enclosing item(s)
// Also skip the witness type, because that has no free regions.
@@ -468,7 +468,7 @@ where
args.as_coroutine().resume_ty().visit_with(self);
}
- ty::Alias(ty::Opaque, ty::AliasTy { def_id, ref args, .. }) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
// Skip lifetime parameters that are not captures.
let variances = self.tcx.variances_of(*def_id);
@@ -575,7 +575,7 @@ impl<'tcx> InferCtxt<'tcx> {
.register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
if let Some(prev) = prev {
obligations.extend(
- self.at(&cause, param_env)
+ self.at(cause, param_env)
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
.obligations,
);
@@ -671,7 +671,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool {
- let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let mut hir_id = tcx.local_def_id_to_hir_id(def_id);
// Named opaque types can be defined by any siblings or children of siblings.
let scope = tcx.hir().get_defining_scope(opaque_hir_id);
@@ -683,8 +683,8 @@ fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hi
let res = hir_id == scope;
trace!(
"may_define_opaque_type(def={:?}, opaque_node={:?}) = {}",
- tcx.hir().find(hir_id),
- tcx.hir().get(opaque_hir_id),
+ tcx.opt_hir_node(hir_id),
+ tcx.hir_node(opaque_hir_id),
res
);
res
diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs
index a737761ba..715006a50 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/table.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs
@@ -41,7 +41,7 @@ impl<'tcx> Drop for OpaqueTypeStorage<'tcx> {
fn drop(&mut self) {
if !self.opaque_types.is_empty() {
ty::tls::with(|tcx| {
- tcx.sess.delay_span_bug(DUMMY_SP, format!("{:?}", self.opaque_types))
+ tcx.sess.span_delayed_bug(DUMMY_SP, format!("{:?}", self.opaque_types))
});
}
}
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index 38819e8ad..47038cfd4 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -11,6 +11,7 @@ use smallvec::{smallvec, SmallVec};
pub enum Component<'tcx> {
Region(ty::Region<'tcx>),
Param(ty::ParamTy),
+ Placeholder(ty::PlaceholderType),
UnresolvedInferenceVariable(ty::InferTy),
// Projections like `T::Foo` are tricky because a constraint like
@@ -97,12 +98,12 @@ fn compute_components<'tcx>(
compute_components(tcx, element, out, visited);
}
- ty::Closure(_, ref args) => {
+ ty::Closure(_, args) => {
let tupled_ty = args.as_closure().tupled_upvars_ty();
compute_components(tcx, tupled_ty, out, visited);
}
- ty::Coroutine(_, ref args, _) => {
+ ty::Coroutine(_, args, _) => {
// Same as the closure case
let tupled_ty = args.as_coroutine().tupled_upvars_ty();
compute_components(tcx, tupled_ty, out, visited);
@@ -120,6 +121,10 @@ fn compute_components<'tcx>(
out.push(Component::Param(p));
}
+ ty::Placeholder(p) => {
+ out.push(Component::Placeholder(p));
+ }
+
// For projections, we prefer to generate an obligation like
// `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
// regionck more ways to prove that it holds. However,
@@ -176,7 +181,6 @@ fn compute_components<'tcx>(
ty::Tuple(..) | // ...
ty::FnPtr(_) | // OutlivesFunction (*)
ty::Dynamic(..) | // OutlivesObject, OutlivesFragment (*)
- ty::Placeholder(..) |
ty::Bound(..) |
ty::Error(_) => {
// (*) Function pointers and trait objects are both binders.
@@ -199,7 +203,9 @@ pub(super) fn compute_alias_components_recursive<'tcx>(
out: &mut SmallVec<[Component<'tcx>; 4]>,
visited: &mut SsoHashSet<GenericArg<'tcx>>,
) {
- let ty::Alias(kind, alias_ty) = alias_ty.kind() else { bug!() };
+ let ty::Alias(kind, alias_ty) = alias_ty.kind() else {
+ unreachable!("can only call `compute_alias_components_recursive` on an alias type")
+ };
let opt_variances = if *kind == ty::Opaque { tcx.variances_of(alias_ty.def_id) } else { &[] };
for (index, child) in alias_ty.args.iter().enumerate() {
if opt_variances.get(index) == Some(&ty::Bivariant) {
@@ -213,8 +219,8 @@ pub(super) fn compute_alias_components_recursive<'tcx>(
compute_components(tcx, ty, out, visited);
}
GenericArgKind::Lifetime(lt) => {
- // Ignore late-bound regions.
- if !lt.is_late_bound() {
+ // Ignore higher ranked regions.
+ if !lt.is_bound() {
out.push(Component::Region(lt));
}
}
@@ -241,8 +247,8 @@ fn compute_components_recursive<'tcx>(
compute_components(tcx, ty, out, visited);
}
GenericArgKind::Lifetime(lt) => {
- // Ignore late-bound regions.
- if !lt.is_late_bound() {
+ // Ignore higher ranked regions.
+ if !lt.is_bound() {
out.push(Component::Region(lt));
}
}
diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs
index 47e3dd762..f8dbfdde3 100644
--- a/compiler/rustc_infer/src/infer/outlives/env.rs
+++ b/compiler/rustc_infer/src/infer/outlives/env.rs
@@ -138,8 +138,8 @@ impl<'tcx> OutlivesEnvironmentBuilder<'tcx> {
}
OutlivesBound::RegionSubRegion(r_a, r_b) => match (*r_a, *r_b) {
(
- ty::ReStatic | ty::ReEarlyBound(_) | ty::ReFree(_),
- ty::ReStatic | ty::ReEarlyBound(_) | ty::ReFree(_),
+ ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_),
+ ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_),
) => self.region_relation.add(r_a, r_b),
(ty::ReError(_), _) | (_, ty::ReError(_)) => {}
// FIXME(#109628): We shouldn't have existential variables in implied bounds.
diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
index 398ac94ee..42e3d6cad 100644
--- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
+++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs
@@ -37,7 +37,7 @@ where
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
match *r {
// ignore bound regions, keep visiting
- ty::ReLateBound(_, _) => ControlFlow::Continue(()),
+ ty::ReBound(_, _) => ControlFlow::Continue(()),
_ => {
(self.op)(r);
ControlFlow::Continue(())
@@ -84,7 +84,6 @@ where
} else {
test_type_match::extract_verify_if_eq(
tcx,
- param_env,
&outlives.map_bound(|ty::OutlivesPredicate(ty, bound)| {
VerifyIfEq { ty, bound }
}),
@@ -112,7 +111,9 @@ where
};
for (idx, s) in args.iter().enumerate() {
- if variances.map(|variances| variances[idx]) != Some(ty::Variance::Bivariant) {
+ if variances.map(|variances| variances[idx])
+ != Some(ty::Variance::Bivariant)
+ {
s.visit_with(self)?;
}
}
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 0987915f4..6379f84aa 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -3,7 +3,7 @@ use self::env::OutlivesEnvironment;
use super::region_constraints::RegionConstraintData;
use super::{InferCtxt, RegionResolutionError};
use crate::infer::free_regions::RegionRelations;
-use crate::infer::lexical_region_resolve::{self, LexicalRegionResolutions};
+use crate::infer::lexical_region_resolve;
use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty;
@@ -37,32 +37,6 @@ pub fn explicit_outlives_bounds<'tcx>(
}
impl<'tcx> InferCtxt<'tcx> {
- pub fn skip_region_resolution(&self) {
- let (var_infos, _) = {
- let mut inner = self.inner.borrow_mut();
- let inner = &mut *inner;
- // Note: `inner.region_obligations` may not be empty, because we
- // didn't necessarily call `process_registered_region_obligations`.
- // This is okay, because that doesn't introduce new vars.
- inner
- .region_constraint_storage
- .take()
- .expect("regions already resolved")
- .with_log(&mut inner.undo_log)
- .into_infos_and_data()
- };
-
- let lexical_region_resolutions = LexicalRegionResolutions {
- values: rustc_index::IndexVec::from_elem_n(
- crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
- var_infos.len(),
- ),
- };
-
- let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
- assert!(old_value.is_none());
- }
-
/// Process the region constraints and return any errors that
/// result. After this, no more unification operations should be
/// done -- or the compiler will panic -- but it is legal to use
@@ -93,7 +67,7 @@ impl<'tcx> InferCtxt<'tcx> {
let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
let (lexical_region_resolutions, errors) =
- lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data);
+ lexical_region_resolve::resolve(region_rels, var_infos, data);
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
assert!(old_value.is_none());
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index f36802e12..395830d93 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -136,7 +136,7 @@ impl<'tcx> InferCtxt<'tcx> {
let outlives = &mut TypeOutlives::new(
self,
self.tcx,
- &outlives_env.region_bound_pairs(),
+ outlives_env.region_bound_pairs(),
None,
outlives_env.param_env,
);
@@ -243,15 +243,18 @@ where
Component::Param(param_ty) => {
self.param_ty_must_outlive(origin, region, *param_ty);
}
+ Component::Placeholder(placeholder_ty) => {
+ self.placeholder_ty_must_outlive(origin, region, *placeholder_ty);
+ }
Component::Alias(alias_ty) => self.alias_ty_must_outlive(origin, region, *alias_ty),
Component::EscapingAlias(subcomponents) => {
- self.components_must_outlive(origin, &subcomponents, region, category);
+ self.components_must_outlive(origin, subcomponents, region, category);
}
Component::UnresolvedInferenceVariable(v) => {
// ignore this, we presume it will yield an error
// later, since if a type variable is not resolved by
// this point it never will be
- self.tcx.sess.delay_span_bug(
+ self.tcx.sess.span_delayed_bug(
origin.span(),
format!("unresolved inference variable in outlives: {v:?}"),
);
@@ -267,11 +270,29 @@ where
region: ty::Region<'tcx>,
param_ty: ty::ParamTy,
) {
- let verify_bound = self.verify_bound.param_bound(param_ty);
+ let verify_bound = self.verify_bound.param_or_placeholder_bound(param_ty.to_ty(self.tcx));
self.delegate.push_verify(origin, GenericKind::Param(param_ty), region, verify_bound);
}
#[instrument(level = "debug", skip(self))]
+ fn placeholder_ty_must_outlive(
+ &mut self,
+ origin: infer::SubregionOrigin<'tcx>,
+ region: ty::Region<'tcx>,
+ placeholder_ty: ty::PlaceholderType,
+ ) {
+ let verify_bound = self
+ .verify_bound
+ .param_or_placeholder_bound(Ty::new_placeholder(self.tcx, placeholder_ty));
+ self.delegate.push_verify(
+ origin,
+ GenericKind::Placeholder(placeholder_ty),
+ region,
+ verify_bound,
+ );
+ }
+
+ #[instrument(level = "debug", skip(self))]
fn alias_ty_must_outlive(
&mut self,
origin: infer::SubregionOrigin<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index 6f973ee37..236dc4ec3 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -36,19 +36,18 @@ use crate::infer::region_constraints::VerifyIfEq;
/// like are used. This is a particular challenge since this function is invoked
/// very late in inference and hence cannot make use of the normal inference
/// machinery.
-#[instrument(level = "debug", skip(tcx, param_env))]
+#[instrument(level = "debug", skip(tcx))]
pub fn extract_verify_if_eq<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
verify_if_eq_b: &ty::Binder<'tcx, VerifyIfEq<'tcx>>,
test_ty: Ty<'tcx>,
) -> Option<ty::Region<'tcx>> {
assert!(!verify_if_eq_b.has_escaping_bound_vars());
- let mut m = MatchAgainstHigherRankedOutlives::new(tcx, param_env);
+ let mut m = MatchAgainstHigherRankedOutlives::new(tcx);
let verify_if_eq = verify_if_eq_b.skip_binder();
m.relate(verify_if_eq.ty, test_ty).ok()?;
- if let ty::RegionKind::ReLateBound(depth, br) = verify_if_eq.bound.kind() {
+ if let ty::RegionKind::ReBound(depth, br) = verify_if_eq.bound.kind() {
assert!(depth == ty::INNERMOST);
match m.map.get(&br) {
Some(&r) => Some(r),
@@ -73,10 +72,9 @@ pub fn extract_verify_if_eq<'tcx>(
}
/// True if a (potentially higher-ranked) outlives
-#[instrument(level = "debug", skip(tcx, param_env))]
+#[instrument(level = "debug", skip(tcx))]
pub(super) fn can_match_erased_ty<'tcx>(
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
outlives_predicate: ty::Binder<'tcx, ty::TypeOutlivesPredicate<'tcx>>,
erased_ty: Ty<'tcx>,
) -> bool {
@@ -87,25 +85,20 @@ pub(super) fn can_match_erased_ty<'tcx>(
// pointless micro-optimization
true
} else {
- MatchAgainstHigherRankedOutlives::new(tcx, param_env).relate(outlives_ty, erased_ty).is_ok()
+ MatchAgainstHigherRankedOutlives::new(tcx).relate(outlives_ty, erased_ty).is_ok()
}
}
struct MatchAgainstHigherRankedOutlives<'tcx> {
tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
pattern_depth: ty::DebruijnIndex,
map: FxHashMap<ty::BoundRegion, ty::Region<'tcx>>,
}
impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
- fn new(
- tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- ) -> MatchAgainstHigherRankedOutlives<'tcx> {
+ fn new(tcx: TyCtxt<'tcx>) -> MatchAgainstHigherRankedOutlives<'tcx> {
MatchAgainstHigherRankedOutlives {
tcx,
- param_env,
pattern_depth: ty::INNERMOST,
map: FxHashMap::default(),
}
@@ -144,15 +137,13 @@ impl<'tcx> MatchAgainstHigherRankedOutlives<'tcx> {
impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> {
fn tag(&self) -> &'static str {
- "Match"
+ "MatchAgainstHigherRankedOutlives"
}
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env
- }
+
fn a_is_expected(&self) -> bool {
true
} // irrelevant
@@ -177,7 +168,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstHigherRankedOutlives<'tcx> {
value: ty::Region<'tcx>,
) -> RelateResult<'tcx, ty::Region<'tcx>> {
debug!("self.pattern_depth = {:?}", self.pattern_depth);
- if let ty::RegionKind::ReLateBound(depth, br) = pattern.kind()
+ if let ty::RegionKind::ReBound(depth, br) = pattern.kind()
&& depth == self.pattern_depth
{
self.bind(br, value)
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 7f0a4717d..90282f58e 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -1,7 +1,7 @@
use crate::infer::outlives::components::{compute_alias_components_recursive, Component};
use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::region_constraints::VerifyIfEq;
-use crate::infer::VerifyBound;
+use crate::infer::{GenericKind, VerifyBound};
use rustc_data_structures::sso::SsoHashSet;
use rustc_middle::ty::GenericArg;
use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt};
@@ -37,11 +37,11 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
}
#[instrument(level = "debug", skip(self))]
- pub fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
+ pub fn param_or_placeholder_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
// Start with anything like `T: 'a` we can scrape from the
// environment. If the environment contains something like
// `for<'a> T: 'a`, then we know that `T` outlives everything.
- let declared_bounds_from_env = self.declared_generic_bounds_from_env(param_ty);
+ let declared_bounds_from_env = self.declared_generic_bounds_from_env(ty);
debug!(?declared_bounds_from_env);
let mut param_bounds = vec![];
for declared_bound in declared_bounds_from_env {
@@ -51,7 +51,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
param_bounds.push(VerifyBound::OutlivedBy(region));
} else {
// This is `for<'a> T: 'a`. This means that `T` outlives everything! All done here.
- debug!("found that {param_ty:?} outlives any lifetime, returning empty vector");
+ debug!("found that {ty:?} outlives any lifetime, returning empty vector");
return VerifyBound::AllBounds(vec![]);
}
}
@@ -130,12 +130,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// see the extensive comment in projection_must_outlive
let recursive_bound = {
let mut components = smallvec![];
- compute_alias_components_recursive(
- self.tcx,
- alias_ty_as_ty.into(),
- &mut components,
- visited,
- );
+ compute_alias_components_recursive(self.tcx, alias_ty_as_ty, &mut components, visited);
self.bound_from_components(&components, visited)
};
@@ -168,7 +163,10 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
) -> VerifyBound<'tcx> {
match *component {
Component::Region(lt) => VerifyBound::OutlivedBy(lt),
- Component::Param(param_ty) => self.param_bound(param_ty),
+ Component::Param(param_ty) => self.param_or_placeholder_bound(param_ty.to_ty(self.tcx)),
+ Component::Placeholder(placeholder_ty) => {
+ self.param_or_placeholder_bound(Ty::new_placeholder(self.tcx, placeholder_ty))
+ }
Component::Alias(alias_ty) => self.alias_bound(alias_ty, visited),
Component::EscapingAlias(ref components) => {
self.bound_from_components(components, visited)
@@ -177,7 +175,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// ignore this, we presume it will yield an error
// later, since if a type variable is not resolved by
// this point it never will be
- self.tcx.sess.delay_span_bug(
+ self.tcx.sess.span_delayed_bug(
rustc_span::DUMMY_SP,
format!("unresolved inference variable in outlives: {v:?}"),
);
@@ -195,9 +193,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
/// bounds, but all the bounds it returns can be relied upon.
fn declared_generic_bounds_from_env(
&self,
- param_ty: ty::ParamTy,
+ generic_ty: Ty<'tcx>,
) -> Vec<ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>> {
- let generic_ty = param_ty.to_ty(self.tcx);
+ assert!(matches!(generic_ty.kind(), ty::Param(_) | ty::Placeholder(_)));
self.declared_generic_bounds_from_env_for_erased_ty(generic_ty)
}
@@ -242,10 +240,20 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
"declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}",
(r, p)
);
+ // Fast path for the common case.
+ match (&p, erased_ty.kind()) {
+ // In outlive routines, all types are expected to be fully normalized.
+ // And therefore we can safely use structural equality for alias types.
+ (GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {}
+ (GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {}
+ (GenericKind::Alias(a1), ty::Alias(_, a2)) if a1.def_id == a2.def_id => {}
+ _ => return None,
+ }
+
let p_ty = p.to_ty(tcx);
let erased_p_ty = self.tcx.erase_regions(p_ty);
(erased_p_ty == erased_ty)
- .then_some(ty::Binder::dummy(ty::OutlivesPredicate(p.to_ty(tcx), r)))
+ .then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r)))
});
param_bounds
@@ -314,14 +322,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
) -> impl Iterator<Item = ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>>
{
let tcx = self.tcx;
- let param_env = self.param_env;
clauses.filter_map(|p| p.as_type_outlives_clause()).filter(move |outlives_predicate| {
- super::test_type_match::can_match_erased_ty(
- tcx,
- param_env,
- *outlives_predicate,
- erased_ty,
- )
+ super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty)
})
}
}
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index b6ff8f2f5..e06596df7 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -81,7 +81,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
return Ok(());
}
- let mini_graph = &MiniGraph::new(tcx, &self, only_consider_snapshot);
+ let mini_graph = &MiniGraph::new(tcx, self, only_consider_snapshot);
let mut leak_check = LeakCheck::new(tcx, outer_universe, max_universe, mini_graph, self);
leak_check.assign_placeholder_values()?;
@@ -341,11 +341,13 @@ impl<'tcx> SccUniverse<'tcx> {
}
rustc_index::newtype_index! {
+ #[orderable]
#[debug_format = "LeakCheckNode({})"]
struct LeakCheckNode {}
}
rustc_index::newtype_index! {
+ #[orderable]
#[debug_format = "LeakCheckScc({})"]
struct LeakCheckScc {}
}
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 3fa9a7333..cbd8040c9 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -16,7 +16,7 @@ use rustc_index::IndexVec;
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
use rustc_middle::ty::ReStatic;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{ReLateBound, ReVar};
+use rustc_middle::ty::{ReBound, ReVar};
use rustc_middle::ty::{Region, RegionVid};
use rustc_span::Span;
@@ -147,6 +147,7 @@ pub struct Verify<'tcx> {
#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
pub enum GenericKind<'tcx> {
Param(ty::ParamTy),
+ Placeholder(ty::PlaceholderType),
Alias(ty::AliasTy<'tcx>),
}
@@ -316,7 +317,7 @@ impl<'tcx> RegionConstraintStorage<'tcx> {
match undo_entry {
AddVar(vid) => {
self.var_infos.pop().unwrap();
- assert_eq!(self.var_infos.len(), vid.index() as usize);
+ assert_eq!(self.var_infos.len(), vid.index());
}
AddConstraint(ref constraint) => {
self.data.constraints.remove(constraint);
@@ -531,7 +532,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
debug!("origin = {:#?}", origin);
match (*sub, *sup) {
- (ReLateBound(..), _) | (_, ReLateBound(..)) => {
+ (ReBound(..), _) | (_, ReBound(..)) => {
span_bug!(origin.span(), "cannot relate bound region: {:?} <= {:?}", sub, sup);
}
(_, ReStatic) => {
@@ -662,12 +663,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
match *region {
ty::ReStatic
| ty::ReErased
- | ty::ReFree(..)
- | ty::ReEarlyBound(..)
+ | ty::ReLateParam(..)
+ | ty::ReEarlyParam(..)
| ty::ReError(_) => ty::UniverseIndex::ROOT,
ty::RePlaceholder(placeholder) => placeholder.universe,
ty::ReVar(vid) => self.var_universe(vid),
- ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region),
+ ty::ReBound(..) => bug!("universe(): encountered bound region {:?}", region),
}
}
@@ -707,6 +708,7 @@ impl<'tcx> fmt::Debug for GenericKind<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
GenericKind::Param(ref p) => write!(f, "{p:?}"),
+ GenericKind::Placeholder(ref p) => write!(f, "{p:?}"),
GenericKind::Alias(ref p) => write!(f, "{p:?}"),
}
}
@@ -716,6 +718,7 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
GenericKind::Param(ref p) => write!(f, "{p}"),
+ GenericKind::Placeholder(ref p) => write!(f, "{p:?}"),
GenericKind::Alias(ref p) => write!(f, "{p}"),
}
}
@@ -725,6 +728,7 @@ impl<'tcx> GenericKind<'tcx> {
pub fn to_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match *self {
GenericKind::Param(ref p) => p.to_ty(tcx),
+ GenericKind::Placeholder(ref p) => Ty::new_placeholder(tcx, *p),
GenericKind::Alias(ref p) => p.to_ty(tcx),
}
}
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 2a9e20b9f..ee911c432 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -3,7 +3,7 @@
//! combining two instances of various things and yielding a new instance.
//! These combiner methods always yield a `Result<T>`. To relate two
//! types, you can use `infcx.at(cause, param_env)` which then allows
-//! you to use the relevant methods of [At](super::at::At).
+//! you to use the relevant methods of [At](crate::infer::at::At).
//!
//! Combiners mostly do their specific behavior and then hand off the
//! bulk of the work to [InferCtxt::super_combine_tys] and
@@ -23,11 +23,11 @@
//! this should be correctly updated.
use super::equate::Equate;
+use super::generalize::{self, CombineDelegate, Generalization};
use super::glb::Glb;
use super::lub::Lub;
use super::sub::Sub;
-use super::{DefineOpaqueTypes, InferCtxt, TypeTrace};
-use crate::infer::generalize::{self, CombineDelegate, Generalization};
+use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
use crate::traits::{Obligation, PredicateObligations};
use rustc_middle::infer::canonical::OriginalQueryValues;
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue, EffectVarValue};
@@ -35,6 +35,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{AliasRelationDirection, TyVar};
use rustc_middle::ty::{IntType, UintType};
use rustc_span::DUMMY_SP;
@@ -102,15 +103,19 @@ impl<'tcx> InferCtxt<'tcx> {
}
// We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm.
- (
- ty::Alias(..),
- ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
- )
- | (
- ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
- ty::Alias(..),
- ) if self.next_trait_solver() => {
- bug!()
+ (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..))
+ if self.next_trait_solver() =>
+ {
+ bug!(
+ "We do not expect to encounter `TyVar` this late in combine \
+ -- they should have been handled earlier"
+ )
+ }
+ (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)))
+ | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _)
+ if self.next_trait_solver() =>
+ {
+ bug!("We do not expect to encounter `Fresh` variables in the new solver")
}
(_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => {
@@ -171,11 +176,11 @@ impl<'tcx> InferCtxt<'tcx> {
// two const param's types are able to be equal has to go through a canonical query with the actual logic
// in `rustc_trait_selection`.
let canonical = self.canonicalize_query(
- (relation.param_env(), a.ty(), b.ty()),
+ relation.param_env().and((a.ty(), b.ty())),
&mut OriginalQueryValues::default(),
);
self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
- self.tcx.sess.delay_span_bug(
+ self.tcx.sess.span_delayed_bug(
DUMMY_SP,
format!("cannot relate consts of different types (a={a:?}, b={b:?})",),
)
@@ -326,7 +331,9 @@ impl<'tcx> InferCtxt<'tcx> {
) -> RelateResult<'tcx, ty::Const<'tcx>> {
let span =
self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span;
- let Generalization { value, needs_wf: _ } = generalize::generalize(
+ // FIXME(generic_const_exprs): Occurs check failures for unevaluated
+ // constants and generic expressions are not yet handled correctly.
+ let Generalization { value_may_be_infer: value, needs_wf: _ } = generalize::generalize(
self,
&mut CombineDelegate { infcx: self, span, param_env },
ct,
@@ -445,7 +452,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
// `'?2` and `?3` are fresh region/type inference
// variables. (Down below, we will relate `a_ty <: b_ty`,
// adding constraints like `'x: '?2` and `?1 <: ?3`.)
- let Generalization { value: b_ty, needs_wf } = generalize::generalize(
+ let Generalization { value_may_be_infer: b_ty, needs_wf } = generalize::generalize(
self.infcx,
&mut CombineDelegate {
infcx: self.infcx,
@@ -457,8 +464,12 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
ambient_variance,
)?;
- debug!(?b_ty);
- self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
+ // Constrain `b_vid` to the generalized type `b_ty`.
+ if let &ty::Infer(TyVar(b_ty_vid)) = b_ty.kind() {
+ self.infcx.inner.borrow_mut().type_variables().equate(b_vid, b_ty_vid);
+ } else {
+ self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
+ }
if needs_wf {
self.obligations.push(Obligation::new(
@@ -477,25 +488,71 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
// relations wind up attributed to the same spans. We need
// to associate causes/spans with each of the relations in
// the stack to get this right.
- match ambient_variance {
- ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
- ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty),
- ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance(
- ty::Contravariant,
- ty::VarianceDiagInfo::default(),
- a_ty,
- b_ty,
- ),
- ty::Variance::Bivariant => {
- unreachable!("no code should be generalizing bivariantly (currently)")
+ if b_ty.is_ty_var() {
+ // This happens for cases like `<?0 as Trait>::Assoc == ?0`.
+ // We can't instantiate `?0` here as that would result in a
+ // cyclic type. We instead delay the unification in case
+ // the alias can be normalized to something which does not
+ // mention `?0`.
+ if self.infcx.next_trait_solver() {
+ let (lhs, rhs, direction) = match ambient_variance {
+ ty::Variance::Invariant => {
+ (a_ty.into(), b_ty.into(), AliasRelationDirection::Equate)
+ }
+ ty::Variance::Covariant => {
+ (a_ty.into(), b_ty.into(), AliasRelationDirection::Subtype)
+ }
+ ty::Variance::Contravariant => {
+ (b_ty.into(), a_ty.into(), AliasRelationDirection::Subtype)
+ }
+ ty::Variance::Bivariant => unreachable!("bivariant generalization"),
+ };
+ self.obligations.push(Obligation::new(
+ self.tcx(),
+ self.trace.cause.clone(),
+ self.param_env,
+ ty::PredicateKind::AliasRelate(lhs, rhs, direction),
+ ));
+ } else {
+ match a_ty.kind() {
+ &ty::Alias(ty::AliasKind::Projection, data) => {
+ // FIXME: This does not handle subtyping correctly, we could
+ // instead create a new inference variable for `a_ty`, emitting
+ // `Projection(a_ty, a_infer)` and `a_infer <: b_ty`.
+ self.obligations.push(Obligation::new(
+ self.tcx(),
+ self.trace.cause.clone(),
+ self.param_env,
+ ty::ProjectionPredicate { projection_ty: data, term: b_ty.into() },
+ ))
+ }
+ // The old solver only accepts projection predicates for associated types.
+ ty::Alias(
+ ty::AliasKind::Inherent | ty::AliasKind::Weak | ty::AliasKind::Opaque,
+ _,
+ ) => return Err(TypeError::CyclicTy(a_ty)),
+ _ => bug!("generalizated `{a_ty:?} to infer, not an alias"),
+ }
}
- }?;
+ } else {
+ match ambient_variance {
+ ty::Variance::Invariant => self.equate(a_is_expected).relate(a_ty, b_ty),
+ ty::Variance::Covariant => self.sub(a_is_expected).relate(a_ty, b_ty),
+ ty::Variance::Contravariant => self.sub(a_is_expected).relate_with_variance(
+ ty::Contravariant,
+ ty::VarianceDiagInfo::default(),
+ a_ty,
+ b_ty,
+ ),
+ ty::Variance::Bivariant => unreachable!("bivariant generalization"),
+ }?;
+ }
Ok(())
}
pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
- self.obligations.extend(obligations.into_iter());
+ self.obligations.extend(obligations);
}
pub fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>) {
@@ -506,6 +563,8 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
}
pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
+ fn param_env(&self) -> ty::ParamEnv<'tcx>;
+
/// Register obligations that must hold in order for this relation to hold
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/relate/equate.rs
index 5d929394e..cb62f2583 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/relate/equate.rs
@@ -1,8 +1,6 @@
-use crate::infer::DefineOpaqueTypes;
-use crate::traits::PredicateObligations;
-
use super::combine::{CombineFields, ObligationEmittingRelation};
-use super::Subtype;
+use crate::infer::{DefineOpaqueTypes, SubregionOrigin};
+use crate::traits::PredicateObligations;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::GenericArgsRef;
@@ -35,10 +33,6 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
self.fields.tcx()
}
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.fields.param_env
- }
-
fn a_is_expected(&self) -> bool {
self.a_is_expected
}
@@ -133,7 +127,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
b: ty::Region<'tcx>,
) -> RelateResult<'tcx, ty::Region<'tcx>> {
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
- let origin = Subtype(Box::new(self.fields.trace.clone()));
+ let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
self.fields
.infcx
.inner
@@ -176,6 +170,10 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
}
impl<'tcx> ObligationEmittingRelation<'tcx> for Equate<'_, '_, 'tcx> {
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ self.fields.param_env
+ }
+
fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
self.fields.register_predicates(obligations);
}
diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 17fe3aa7b..665af7381 100644
--- a/compiler/rustc_infer/src/infer/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -1,19 +1,22 @@
+use std::mem;
+
use rustc_data_structures::sso::SsoHashMap;
use rustc_hir::def_id::DefId;
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::visit::MaxUniverse;
+use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
use rustc_span::Span;
use crate::infer::nll_relate::TypeRelatingDelegate;
-use crate::infer::type_variable::TypeVariableValue;
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind, TypeVariableValue};
use crate::infer::{InferCtxt, RegionVariableOrigin};
/// Attempts to generalize `term` for the type variable `for_vid`.
/// This checks for cycles -- that is, whether the type `term`
/// references `for_vid`.
-pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>> + Relate<'tcx>>(
+pub fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>> + Relate<'tcx>>(
infcx: &InferCtxt<'tcx>,
delegate: &mut D,
term: T,
@@ -38,14 +41,15 @@ pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>>
root_vid,
for_universe,
root_term: term.into(),
+ in_alias: false,
needs_wf: false,
cache: Default::default(),
};
assert!(!term.has_escaping_bound_vars());
- let value = generalizer.relate(term, term)?;
+ let value_may_be_infer = generalizer.relate(term, term)?;
let needs_wf = generalizer.needs_wf;
- Ok(Generalization { value, needs_wf })
+ Ok(Generalization { value_may_be_infer, needs_wf })
}
/// Abstracts the handling of region vars between HIR and MIR/NLL typechecking
@@ -55,6 +59,8 @@ pub trait GeneralizerDelegate<'tcx> {
fn forbid_inference_vars() -> bool;
+ fn span(&self) -> Span;
+
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
}
@@ -73,6 +79,10 @@ impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> {
false
}
+ fn span(&self) -> Span {
+ self.span
+ }
+
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
// FIXME: This is non-ideal because we don't give a
// very descriptive origin for this region variable.
@@ -93,6 +103,10 @@ where
<Self as TypeRelatingDelegate<'tcx>>::forbid_inference_vars()
}
+ fn span(&self) -> Span {
+ <Self as TypeRelatingDelegate<'tcx>>::span(&self)
+ }
+
fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
<Self as TypeRelatingDelegate<'tcx>>::generalize_existential(self, universe)
}
@@ -139,6 +153,13 @@ struct Generalizer<'me, 'tcx, D> {
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
+ /// This is set once we're generalizing the arguments of an alias.
+ ///
+ /// This is necessary to correctly handle
+ /// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
+ /// hold by either normalizing the outer or the inner associated type.
+ in_alias: bool,
+
/// See the field `needs_wf` in `Generalization`.
needs_wf: bool,
}
@@ -161,10 +182,6 @@ where
self.infcx.tcx
}
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.delegate.param_env()
- }
-
fn tag(&self) -> &'static str {
"Generalizer"
}
@@ -193,7 +210,7 @@ where
opt_variances,
a_subst,
b_subst,
- true,
+ false,
)
}
}
@@ -274,7 +291,7 @@ where
ty::Covariant | ty::Contravariant => (),
}
- let origin = *inner.type_variables().var_origin(vid);
+ let origin = inner.type_variables().var_origin(vid);
let new_var_id =
inner.type_variables().new_var(self.for_universe, origin);
let u = Ty::new_var(self.tcx(), new_var_id);
@@ -309,6 +326,44 @@ where
}
}
+ ty::Alias(kind, data) => {
+ // An occurs check failure inside of an alias does not mean
+ // that the types definitely don't unify. We may be able
+ // to normalize the alias after all.
+ //
+ // We handle this by lazily equating the alias and generalizing
+ // it to an inference variable.
+ let is_nested_alias = mem::replace(&mut self.in_alias, true);
+ let result = match self.relate(data, data) {
+ Ok(data) => Ok(Ty::new_alias(self.tcx(), kind, data)),
+ Err(e) => {
+ if is_nested_alias {
+ return Err(e);
+ } else {
+ let mut visitor = MaxUniverse::new();
+ t.visit_with(&mut visitor);
+ let infer_replacement_is_complete =
+ self.for_universe.can_name(visitor.max_universe())
+ && !t.has_escaping_bound_vars();
+ if !infer_replacement_is_complete {
+ warn!("may incompletely handle alias type: {t:?}");
+ }
+
+ debug!("generalization failure in alias");
+ Ok(self.infcx.next_ty_var_in_universe(
+ TypeVariableOrigin {
+ kind: TypeVariableOriginKind::MiscVariable,
+ span: self.delegate.span(),
+ },
+ self.for_universe,
+ ))
+ }
+ }
+ };
+ self.in_alias = is_nested_alias;
+ result
+ }
+
_ => relate::structurally_relate_tys(self, t, t),
}?;
@@ -327,7 +382,7 @@ where
match *r {
// Never make variables for regions bound within the type itself,
// nor for erased regions.
- ty::ReLateBound(..) | ty::ReErased => {
+ ty::ReBound(..) | ty::ReErased => {
return Ok(r);
}
@@ -340,8 +395,8 @@ where
ty::RePlaceholder(..)
| ty::ReVar(..)
| ty::ReStatic
- | ty::ReEarlyBound(..)
- | ty::ReFree(..) => {
+ | ty::ReEarlyParam(..)
+ | ty::ReLateParam(..) => {
// see common code below
}
}
@@ -457,7 +512,15 @@ where
/// indicating whether further WF checks are needed.
#[derive(Debug)]
pub struct Generalization<T> {
- pub value: T,
+ /// When generalizing `<?0 as Trait>::Assoc` or
+ /// `<T as Bar<<?0 as Foo>::Assoc>>::Assoc`
+ /// for `?0` generalization returns an inference
+ /// variable.
+ ///
+ /// This has to be handled wotj care as it can
+ /// otherwise very easily result in infinite
+ /// recursion.
+ pub value_may_be_infer: T,
/// If true, then the generalized type may not be well-formed,
/// even if the source type is well-formed, so we should add an
diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/relate/glb.rs
index 2f659d9a6..aa8912430 100644
--- a/compiler/rustc_infer/src/infer/glb.rs
+++ b/compiler/rustc_infer/src/infer/relate/glb.rs
@@ -1,13 +1,12 @@
//! Greatest lower bound. See [`lattice`].
+use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+
use super::combine::{CombineFields, ObligationEmittingRelation};
use super::lattice::{self, LatticeDir};
-use super::Subtype;
-use super::{DefineOpaqueTypes, InferCtxt};
-
+use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
use crate::traits::{ObligationCause, PredicateObligations};
-use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
/// "Greatest lower bound" (common subtype)
pub struct Glb<'combine, 'infcx, 'tcx> {
@@ -33,10 +32,6 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
self.fields.tcx()
}
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.fields.param_env
- }
-
fn a_is_expected(&self) -> bool {
self.a_is_expected
}
@@ -68,7 +63,7 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
) -> RelateResult<'tcx, ty::Region<'tcx>> {
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
- let origin = Subtype(Box::new(self.fields.trace.clone()));
+ let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
// GLB(&'static u8, &'a u8) == &RegionLUB('static, 'a) u8 == &'static u8
Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions(
self.tcx(),
@@ -139,6 +134,10 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx,
}
impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> {
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ self.fields.param_env
+ }
+
fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
self.fields.register_predicates(obligations);
}
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs
index 510b1797d..440df8c89 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs
@@ -2,8 +2,8 @@
//! the end of the file for details.
use super::combine::CombineFields;
-use super::{HigherRankedType, InferCtxt};
use crate::infer::CombinedSnapshot;
+use crate::infer::{HigherRankedType, InferCtxt};
use rustc_middle::ty::fold::FnMutDelegate;
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, Binder, Ty, TyCtxt, TypeFoldable};
diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs
index 9ef35429f..744e2dfa3 100644
--- a/compiler/rustc_infer/src/infer/lattice.rs
+++ b/compiler/rustc_infer/src/infer/relate/lattice.rs
@@ -18,10 +18,10 @@
//! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
use super::combine::ObligationEmittingRelation;
-use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use super::{DefineOpaqueTypes, InferCtxt};
-
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::{DefineOpaqueTypes, InferCtxt};
use crate::traits::ObligationCause;
+
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, Ty};
diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/relate/lub.rs
index e41ec7e6c..87d777530 100644
--- a/compiler/rustc_infer/src/infer/lub.rs
+++ b/compiler/rustc_infer/src/infer/relate/lub.rs
@@ -2,10 +2,9 @@
use super::combine::{CombineFields, ObligationEmittingRelation};
use super::lattice::{self, LatticeDir};
-use super::Subtype;
-use super::{DefineOpaqueTypes, InferCtxt};
-
+use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
use crate::traits::{ObligationCause, PredicateObligations};
+
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
@@ -33,10 +32,6 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
self.fields.tcx()
}
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.fields.param_env
- }
-
fn a_is_expected(&self) -> bool {
self.a_is_expected
}
@@ -68,7 +63,7 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
) -> RelateResult<'tcx, ty::Region<'tcx>> {
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
- let origin = Subtype(Box::new(self.fields.trace.clone()));
+ let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
// LUB(&'static u8, &'a u8) == &RegionGLB('static, 'a) u8 == &'a u8
Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
self.tcx(),
@@ -139,6 +134,10 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx,
}
impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> {
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ self.fields.param_env
+ }
+
fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
self.fields.register_predicates(obligations);
}
diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs
new file mode 100644
index 000000000..f688c2b74
--- /dev/null
+++ b/compiler/rustc_infer/src/infer/relate/mod.rs
@@ -0,0 +1,12 @@
+//! This module contains the definitions of most `TypeRelation`s in the type system
+//! (except for some relations used for diagnostics and heuristics in the compiler).
+
+pub(super) mod combine;
+mod equate;
+pub(super) mod generalize;
+mod glb;
+mod higher_ranked;
+mod lattice;
+mod lub;
+pub mod nll;
+mod sub;
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/relate/nll.rs
index c80491643..1ef865cfc 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/relate/nll.rs
@@ -30,8 +30,8 @@ use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
use rustc_span::{Span, Symbol};
use std::fmt::Debug;
-use crate::infer::combine::ObligationEmittingRelation;
-use crate::infer::generalize::{self, Generalization};
+use super::combine::ObligationEmittingRelation;
+use super::generalize::{self, Generalization};
use crate::infer::InferCtxt;
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::traits::{Obligation, PredicateObligations};
@@ -113,9 +113,6 @@ pub trait TypeRelatingDelegate<'tcx> {
fn forbid_inference_vars() -> bool;
}
-#[derive(Copy, Clone)]
-struct UniversallyQuantified(bool);
-
impl<'me, 'tcx, D> TypeRelating<'me, 'tcx, D>
where
D: TypeRelatingDelegate<'tcx>,
@@ -217,13 +214,17 @@ where
}
fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
- let Generalization { value: ty, needs_wf: _ } = generalize::generalize(
+ let Generalization { value_may_be_infer: ty, needs_wf: _ } = generalize::generalize(
self.infcx,
&mut self.delegate,
ty,
for_vid,
self.ambient_variance,
)?;
+
+ if ty.is_ty_var() {
+ span_bug!(self.delegate.span(), "occurs check failure in MIR typeck");
+ }
Ok(ty)
}
@@ -246,7 +247,9 @@ where
let (a, b) = match (a.kind(), b.kind()) {
(&ty::Alias(ty::Opaque, ..), _) => (a, generalize(b, false)?),
(_, &ty::Alias(ty::Opaque, ..)) => (generalize(a, true)?, b),
- _ => unreachable!(),
+ _ => unreachable!(
+ "expected at least one opaque type in `relate_opaques`, got {a} and {b}."
+ ),
};
let cause = ObligationCause::dummy_with_span(self.delegate.span());
let obligations = self
@@ -428,10 +431,6 @@ where
self.infcx.tcx
}
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.delegate.param_env()
- }
-
fn tag(&self) -> &'static str {
"nll::subtype"
}
@@ -497,7 +496,7 @@ where
// shouldn't ever fail. Instead, it unconditionally emits an
// alias-relate goal.
assert!(!self.infcx.next_trait_solver());
- self.tcx().sess.delay_span_bug(
+ self.tcx().sess.span_delayed_bug(
self.delegate.span(),
"failure to relate an opaque to itself should result in an error later on",
);
@@ -555,7 +554,7 @@ where
match b.kind() {
ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
// Forbid inference variables in the RHS.
- self.infcx.tcx.sess.delay_span_bug(
+ self.infcx.tcx.sess.span_delayed_bug(
self.delegate.span(),
format!("unexpected inference var {b:?}",),
);
@@ -667,6 +666,10 @@ impl<'tcx, D> ObligationEmittingRelation<'tcx> for TypeRelating<'_, 'tcx, D>
where
D: TypeRelatingDelegate<'tcx>,
{
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ self.delegate.param_env()
+ }
+
fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
self.delegate.register_obligations(
obligations
@@ -706,7 +709,9 @@ where
),
// FIXME(deferred_projection_equality): Implement this when we trigger it.
// Probably just need to do nothing here.
- ty::Variance::Bivariant => unreachable!(),
+ ty::Variance::Bivariant => {
+ unreachable!("cannot defer an alias-relate goal with Bivariant variance (yet?)")
+ }
})]);
}
}
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/relate/sub.rs
index 0c3bb633b..36876acd7 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/relate/sub.rs
@@ -1,7 +1,7 @@
use super::combine::CombineFields;
-use super::{DefineOpaqueTypes, ObligationEmittingRelation, SubregionOrigin};
-
+use crate::infer::{DefineOpaqueTypes, ObligationEmittingRelation, SubregionOrigin};
use crate::traits::{Obligation, PredicateObligations};
+
use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::TyVar;
@@ -39,10 +39,6 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
self.fields.infcx.tcx
}
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.fields.param_env
- }
-
fn a_is_expected(&self) -> bool {
self.a_is_expected
}
@@ -203,6 +199,10 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
}
impl<'tcx> ObligationEmittingRelation<'tcx> for Sub<'_, '_, 'tcx> {
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ self.fields.param_env
+ }
+
fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
self.fields.register_predicates(obligations);
}
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 18a9cb6b4..f317ccee6 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -134,7 +134,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for UnresolvedTypeOrConstFinder<'a, 'tc
if let TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeParameterDefinition(_, _),
span,
- } = *ty_vars.var_origin(ty_vid)
+ } = ty_vars.var_origin(ty_vid)
{
Some(span)
} else {
@@ -260,3 +260,85 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
}
}
}
+
+///////////////////////////////////////////////////////////////////////////
+// EAGER RESOLUTION
+
+/// Resolves ty, region, and const vars to their inferred values or their root vars.
+pub struct EagerResolver<'a, 'tcx> {
+ infcx: &'a InferCtxt<'tcx>,
+}
+
+impl<'a, 'tcx> EagerResolver<'a, 'tcx> {
+ pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
+ EagerResolver { infcx }
+ }
+}
+
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerResolver<'_, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
+ self.infcx.tcx
+ }
+
+ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+ match *t.kind() {
+ ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
+ Ok(t) => t.fold_with(self),
+ Err(_) => Ty::new_var(self.infcx.tcx, self.infcx.root_var(vid)),
+ },
+ ty::Infer(ty::IntVar(vid)) => self.infcx.opportunistic_resolve_int_var(vid),
+ ty::Infer(ty::FloatVar(vid)) => self.infcx.opportunistic_resolve_float_var(vid),
+ _ => {
+ if t.has_infer() {
+ t.super_fold_with(self)
+ } else {
+ t
+ }
+ }
+ }
+ }
+
+ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+ match *r {
+ ty::ReVar(vid) => self
+ .infcx
+ .inner
+ .borrow_mut()
+ .unwrap_region_constraints()
+ .opportunistic_resolve_var(self.infcx.tcx, vid),
+ _ => r,
+ }
+ }
+
+ fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
+ match c.kind() {
+ ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
+ // FIXME: we need to fold the ty too, I think.
+ match self.infcx.probe_const_var(vid) {
+ Ok(c) => c.fold_with(self),
+ Err(_) => {
+ ty::Const::new_var(self.infcx.tcx, self.infcx.root_const_var(vid), c.ty())
+ }
+ }
+ }
+ ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
+ debug_assert_eq!(c.ty(), self.infcx.tcx.types.bool);
+ match self.infcx.probe_effect_var(vid) {
+ Some(c) => c.as_const(self.infcx.tcx),
+ None => ty::Const::new_infer(
+ self.infcx.tcx,
+ ty::InferConst::EffectVar(self.infcx.root_effect_var(vid)),
+ self.infcx.tcx.types.bool,
+ ),
+ }
+ }
+ _ => {
+ if c.has_infer() {
+ c.super_fold_with(self)
+ } else {
+ c
+ }
+ }
+ }
+ }
+}
diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs
index bc83f8d3f..58b811015 100644
--- a/compiler/rustc_infer/src/infer/type_variable.rs
+++ b/compiler/rustc_infer/src/infer/type_variable.rs
@@ -1,4 +1,5 @@
use rustc_hir::def_id::DefId;
+use rustc_index::IndexVec;
use rustc_middle::ty::{self, Ty, TyVid};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
@@ -11,14 +12,13 @@ use std::cmp;
use std::marker::PhantomData;
use std::ops::Range;
-use rustc_data_structures::undo_log::{Rollback, UndoLogs};
+use rustc_data_structures::undo_log::Rollback;
/// Represents a single undo-able action that affects a type inference variable.
#[derive(Clone)]
pub(crate) enum UndoLog<'tcx> {
EqRelation(sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>),
SubRelation(sv::UndoLog<ut::Delegate<ty::TyVid>>),
- Values(sv::UndoLog<Delegate>),
}
/// Convert from a specific kind of undo to the more general UndoLog
@@ -35,34 +35,19 @@ impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::TyVid>>> for UndoLog<'tcx> {
}
}
-/// Convert from a specific kind of undo to the more general UndoLog
-impl<'tcx> From<sv::UndoLog<Delegate>> for UndoLog<'tcx> {
- fn from(l: sv::UndoLog<Delegate>) -> Self {
- UndoLog::Values(l)
- }
-}
-
-/// Convert from a specific kind of undo to the more general UndoLog
-impl<'tcx> From<Instantiate> for UndoLog<'tcx> {
- fn from(l: Instantiate) -> Self {
- UndoLog::Values(sv::UndoLog::Other(l))
- }
-}
-
impl<'tcx> Rollback<UndoLog<'tcx>> for TypeVariableStorage<'tcx> {
fn reverse(&mut self, undo: UndoLog<'tcx>) {
match undo {
UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo),
UndoLog::SubRelation(undo) => self.sub_relations.reverse(undo),
- UndoLog::Values(undo) => self.values.reverse(undo),
}
}
}
#[derive(Clone)]
pub struct TypeVariableStorage<'tcx> {
- values: sv::SnapshotVecStorage<Delegate>,
-
+ /// The origins of each type variable.
+ values: IndexVec<TyVid, TypeVariableData>,
/// Two variables are unified in `eq_relations` when we have a
/// constraint `?X == ?Y`. This table also stores, for each key,
/// the known value.
@@ -168,15 +153,10 @@ impl<'tcx> TypeVariableValue<'tcx> {
}
}
-#[derive(Clone)]
-pub(crate) struct Instantiate;
-
-pub(crate) struct Delegate;
-
impl<'tcx> TypeVariableStorage<'tcx> {
pub fn new() -> TypeVariableStorage<'tcx> {
TypeVariableStorage {
- values: sv::SnapshotVecStorage::new(),
+ values: Default::default(),
eq_relations: ut::UnificationTableStorage::new(),
sub_relations: ut::UnificationTableStorage::new(),
}
@@ -194,6 +174,11 @@ impl<'tcx> TypeVariableStorage<'tcx> {
pub(crate) fn eq_relations_ref(&self) -> &ut::UnificationTableStorage<TyVidEqKey<'tcx>> {
&self.eq_relations
}
+
+ pub(super) fn finalize_rollback(&mut self) {
+ debug_assert!(self.values.len() >= self.eq_relations.len());
+ self.values.truncate(self.eq_relations.len());
+ }
}
impl<'tcx> TypeVariableTable<'_, 'tcx> {
@@ -201,8 +186,8 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
///
/// Note that this function does not return care whether
/// `vid` has been unified with something else or not.
- pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin {
- &self.storage.values.get(vid.as_usize()).origin
+ pub fn var_origin(&self, vid: ty::TyVid) -> TypeVariableOrigin {
+ self.storage.values[vid].origin
}
/// Records that `a == b`, depending on `dir`.
@@ -229,20 +214,14 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
/// Precondition: `vid` must not have been previously instantiated.
pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) {
let vid = self.root_var(vid);
+ debug_assert!(!ty.is_ty_var(), "instantiating ty var with var: {vid:?} {ty:?}");
debug_assert!(self.probe(vid).is_unknown());
debug_assert!(
self.eq_relations().probe_value(vid).is_unknown(),
- "instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}",
- vid,
- ty,
+ "instantiating type variable `{vid:?}` twice: new-value = {ty:?}, old-value={:?}",
self.eq_relations().probe_value(vid)
);
self.eq_relations().union_value(vid, TypeVariableValue::Known { value: ty });
-
- // Hack: we only need this so that `types_escaping_snapshot`
- // can see what has been unified; see the Delegate impl for
- // more details.
- self.undo_log.push(Instantiate);
}
/// Creates a new type variable.
@@ -263,14 +242,14 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
let sub_key = self.sub_relations().new_key(());
- assert_eq!(eq_key.vid, sub_key);
+ debug_assert_eq!(eq_key.vid, sub_key);
- let index = self.values().push(TypeVariableData { origin });
- assert_eq!(eq_key.vid.as_u32(), index as u32);
+ let index = self.storage.values.push(TypeVariableData { origin });
+ debug_assert_eq!(eq_key.vid, index);
debug!("new_var(index={:?}, universe={:?}, origin={:?})", eq_key.vid, universe, origin);
- eq_key.vid
+ index
}
/// Returns the number of type variables created thus far.
@@ -331,13 +310,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
}
#[inline]
- fn values(
- &mut self,
- ) -> sv::SnapshotVec<Delegate, &mut Vec<TypeVariableData>, &mut InferCtxtUndoLogs<'tcx>> {
- self.storage.values.with_log(self.undo_log)
- }
-
- #[inline]
fn eq_relations(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidEqKey<'tcx>> {
self.storage.eq_relations.with_log(self.undo_log)
}
@@ -355,16 +327,14 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
let range = TyVid::from_usize(value_count)..TyVid::from_usize(self.num_vars());
(
range.start..range.end,
- (range.start.as_usize()..range.end.as_usize())
- .map(|index| self.storage.values.get(index).origin)
- .collect(),
+ (range.start..range.end).map(|index| self.var_origin(index)).collect(),
)
}
/// Returns indices of all variables that are not yet
/// instantiated.
- pub fn unsolved_variables(&mut self) -> Vec<ty::TyVid> {
- (0..self.storage.values.len())
+ pub fn unresolved_variables(&mut self) -> Vec<ty::TyVid> {
+ (0..self.num_vars())
.filter_map(|i| {
let vid = ty::TyVid::from_usize(i);
match self.probe(vid) {
@@ -376,26 +346,6 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
}
}
-impl sv::SnapshotVecDelegate for Delegate {
- type Value = TypeVariableData;
- type Undo = Instantiate;
-
- fn reverse(_values: &mut Vec<TypeVariableData>, _action: Instantiate) {
- // We don't actually have to *do* anything to reverse an
- // instantiation; the value for a variable is stored in the
- // `eq_relations` and hence its rollback code will handle
- // it. In fact, we could *almost* just remove the
- // `SnapshotVec` entirely, except that we would have to
- // reproduce *some* of its logic, since we want to know which
- // type variables have been instantiated since the snapshot
- // was started, so we can implement `types_escaping_snapshot`.
- //
- // (If we extended the `UnificationTable` to let us see which
- // values have been unified and so forth, that might also
- // suffice.)
- }
-}
-
///////////////////////////////////////////////////////////////////////////
/// These structs (a newtyped TyVid) are used as the unification key
diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs
index 565573051..be02452d8 100644
--- a/compiler/rustc_infer/src/infer/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/undo_log.rs
@@ -32,7 +32,7 @@ pub(crate) enum UndoLog<'tcx> {
}
macro_rules! impl_from {
- ($($ctor: ident ($ty: ty),)*) => {
+ ($($ctor:ident ($ty:ty),)*) => {
$(
impl<'tcx> From<$ty> for UndoLog<'tcx> {
fn from(x: $ty) -> Self {
@@ -50,8 +50,6 @@ impl_from! {
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
TypeVariables(sv::UndoLog<ut::Delegate<ty::TyVid>>),
- TypeVariables(sv::UndoLog<type_variable::Delegate>),
- TypeVariables(type_variable::Instantiate),
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
@@ -140,6 +138,8 @@ impl<'tcx> InferCtxtInner<'tcx> {
self.reverse(undo);
}
+ self.type_variable_storage.finalize_rollback();
+
if self.undo_log.num_open_snapshots == 1 {
// After the root snapshot the undo log should be empty.
assert!(snapshot.undo_len == 0);
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index 4a6d1bc68..221b78048 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -13,9 +13,9 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![cfg_attr(not(bootstrap), doc(rust_logo))]
-#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
-#![cfg_attr(not(bootstrap), allow(internal_features))]
+#![doc(rust_logo)]
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
#![feature(associated_type_bounds)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
@@ -37,11 +37,8 @@ extern crate tracing;
#[macro_use]
extern crate rustc_middle;
-use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
-use rustc_fluent_macro::fluent_messages;
-
mod errors;
pub mod infer;
pub mod traits;
-fluent_messages! { "../messages.ftl" }
+rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index 329660119..b3cfd843a 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -101,12 +101,19 @@ pub fn report_object_safety_error<'tcx>(
to be resolvable dynamically; for more information visit \
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
);
+
+ // Only provide the help if its a local trait, otherwise it's not actionable.
if trait_span.is_some() {
let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
reported_violations.sort();
- for violation in reported_violations {
- // Only provide the help if its a local trait, otherwise it's not actionable.
- violation.solution(&mut err);
+
+ let mut potential_solutions: Vec<_> =
+ reported_violations.into_iter().map(|violation| violation.solution()).collect();
+ potential_solutions.sort();
+ // Allows us to skip suggesting that the same item should be moved to another trait multiple times.
+ potential_solutions.dedup();
+ for solution in potential_solutions {
+ solution.add_to(&mut err);
}
}
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index a26e676c5..b9be17891 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -135,7 +135,7 @@ pub enum FulfillmentErrorCode<'tcx> {
CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
CodeConstEquateError(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
CodeAmbiguity {
- /// Overflow reported from the new solver `-Ztrait-solver=next`, which will
+ /// Overflow reported from the new solver `-Znext-solver`, which will
/// be reported as an regular error as opposed to a fatal error.
overflow: bool,
},
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 3c566e0dd..50190058a 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -261,9 +261,14 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
fn elaborate(&mut self, elaboratable: &O) {
let tcx = self.visited.tcx;
- let bound_predicate = elaboratable.predicate().kind();
- match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
+ // We only elaborate clauses.
+ let Some(clause) = elaboratable.predicate().as_clause() else {
+ return;
+ };
+
+ let bound_clause = clause.kind();
+ match bound_clause.skip_binder() {
+ ty::ClauseKind::Trait(data) => {
// Negative trait bounds do not imply any supertrait bounds
if data.polarity == ty::ImplPolarity::Negative {
return;
@@ -280,52 +285,16 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
let obligations =
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
elaboratable.child_with_derived_cause(
- clause.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
+ clause.subst_supertrait(tcx, &bound_clause.rebind(data.trait_ref)),
span,
- bound_predicate.rebind(data),
+ bound_clause.rebind(data),
index,
)
});
debug!(?data, ?obligations, "super_predicates");
self.extend_deduped(obligations);
}
- ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) => {
- // Currently, we do not elaborate WF predicates,
- // although we easily could.
- }
- ty::PredicateKind::ObjectSafe(..) => {
- // Currently, we do not elaborate object-safe
- // predicates.
- }
- ty::PredicateKind::Subtype(..) => {
- // Currently, we do not "elaborate" predicates like `X <: Y`,
- // though conceivably we might.
- }
- ty::PredicateKind::Coerce(..) => {
- // Currently, we do not "elaborate" predicates like `X -> Y`,
- // though conceivably we might.
- }
- ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => {
- // Nothing to elaborate in a projection predicate.
- }
- ty::PredicateKind::ClosureKind(..) => {
- // Nothing to elaborate when waiting for a closure's kind to be inferred.
- }
- ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
- // Currently, we do not elaborate const-evaluatable
- // predicates.
- }
- ty::PredicateKind::ConstEquate(..) => {
- // Currently, we do not elaborate const-equate
- // predicates.
- }
- ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {
- // Nothing to elaborate from `'a: 'b`.
- }
- ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
- ty_max,
- r_min,
- ))) => {
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
// We know that `T: 'a` for some type `T`. We can
// often elaborate this. For example, if we know that
// `[U]: 'a`, that implies that `U: 'a`. Similarly, if
@@ -340,7 +309,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
// consider this as evidence that `T: 'static`, but
// I'm a bit wary of such constructions and so for now
// I want to be conservative. --nmatsakis
- if r_min.is_late_bound() {
+ if r_min.is_bound() {
return;
}
@@ -351,7 +320,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
.into_iter()
.filter_map(|component| match component {
Component::Region(r) => {
- if r.is_late_bound() {
+ if r.is_bound() {
None
} else {
Some(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
@@ -365,6 +334,11 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min)))
}
+ Component::Placeholder(p) => {
+ let ty = Ty::new_placeholder(tcx, p);
+ Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min)))
+ }
+
Component::UnresolvedInferenceVariable(_) => None,
Component::Alias(alias_ty) => {
@@ -383,15 +357,25 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
}
})
.map(|clause| {
- elaboratable.child(bound_predicate.rebind(clause).to_predicate(tcx))
+ elaboratable.child(bound_clause.rebind(clause).to_predicate(tcx))
}),
);
}
- ty::PredicateKind::Ambiguous => {}
- ty::PredicateKind::AliasRelate(..) => {
- // No
+ ty::ClauseKind::RegionOutlives(..) => {
+ // Nothing to elaborate from `'a: 'b`.
+ }
+ ty::ClauseKind::WellFormed(..) => {
+ // Currently, we do not elaborate WF predicates,
+ // although we easily could.
+ }
+ ty::ClauseKind::Projection(..) => {
+ // Nothing to elaborate in a projection predicate.
+ }
+ ty::ClauseKind::ConstEvaluatable(..) => {
+ // Currently, we do not elaborate const-evaluatable
+ // predicates.
}
- ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => {
+ ty::ClauseKind::ConstArgHasType(..) => {
// Nothing to elaborate
}
}