summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_infer/src/infer
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_infer/src/infer')
-rw-r--r--compiler/rustc_infer/src/infer/at.rs3
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs12
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs40
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs620
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs11
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs36
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs15
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs21
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs32
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs83
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs2
-rw-r--r--compiler/rustc_infer/src/infer/generalize.rs479
-rw-r--r--compiler/rustc_infer/src/infer/higher_ranked/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/lattice.rs5
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs26
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs72
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs363
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs108
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/table.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs40
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs31
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs12
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs13
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs2
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs6
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs4
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs11
33 files changed, 958 insertions, 1117 deletions
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index d240d8e49..0c8854e96 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -30,8 +30,6 @@ use super::*;
use rustc_middle::ty::relate::{Relate, TypeRelation};
use rustc_middle::ty::{Const, ImplSubject};
-use std::cell::Cell;
-
/// Whether we should define opaque types or just treat them opaquely.
///
/// Currently only used to prevent predicate matching from matching anything
@@ -84,7 +82,6 @@ impl<'tcx> InferCtxt<'tcx> {
in_snapshot: self.in_snapshot.clone(),
universe: self.universe.clone(),
intercrate: self.intercrate,
- inside_canonicalization_ctxt: Cell::new(self.inside_canonicalization_ctxt()),
}
}
}
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index e808911a3..427d05c8b 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -16,7 +16,7 @@ use rustc_middle::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags,
use std::sync::atomic::Ordering;
use rustc_data_structures::fx::FxHashMap;
-use rustc_index::vec::Idx;
+use rustc_index::Idx;
use smallvec::SmallVec;
impl<'tcx> InferCtxt<'tcx> {
@@ -205,7 +205,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
// `delay_span_bug` to allow type error over an ICE.
canonicalizer.tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP,
- &format!("unexpected region in query response: `{:?}`", r),
+ format!("unexpected region in query response: `{:?}`", r),
);
r
}
@@ -561,15 +561,13 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
where
V: TypeFoldable<TyCtxt<'tcx>>,
{
- let _inside_canonical_ctxt_guard = infcx.set_canonicalization_ctxt();
-
let needs_canonical_flags = if canonicalize_region_mode.any() {
- TypeFlags::NEEDS_INFER |
+ TypeFlags::HAS_INFER |
TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS`
TypeFlags::HAS_TY_PLACEHOLDER |
TypeFlags::HAS_CT_PLACEHOLDER
} else {
- TypeFlags::NEEDS_INFER
+ TypeFlags::HAS_INFER
| TypeFlags::HAS_RE_PLACEHOLDER
| TypeFlags::HAS_TY_PLACEHOLDER
| TypeFlags::HAS_CT_PLACEHOLDER
@@ -600,7 +598,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
// Once we have canonicalized `out_value`, it should not
// contain anything that ties it to this inference context
// anymore.
- debug_assert!(!out_value.needs_infer() && !out_value.has_placeholders());
+ debug_assert!(!out_value.has_infer() && !out_value.has_placeholders());
let canonical_variables =
tcx.mk_canonical_var_infos(&canonicalizer.universe_canonicalized_variables());
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index fbb2257bf..2abdd5b0a 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -23,7 +23,7 @@
use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind};
use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::GenericArg;
use rustc_middle::ty::{self, List, TyCtxt};
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index e98f68ae5..88256c819 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -15,12 +15,12 @@ use crate::infer::canonical::{
use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
-use crate::traits::query::{Fallible, NoSolution};
+use crate::traits::query::NoSolution;
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use crate::traits::{PredicateObligations, TraitEngine, TraitEngineExt};
use rustc_data_structures::captures::Captures;
-use rustc_index::vec::Idx;
-use rustc_index::vec::IndexVec;
+use rustc_index::Idx;
+use rustc_index::IndexVec;
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::fold::TypeFoldable;
@@ -57,7 +57,7 @@ impl<'tcx> InferCtxt<'tcx> {
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
fulfill_cx: &mut dyn TraitEngine<'tcx>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, T>>
+ ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
where
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
@@ -153,20 +153,22 @@ impl<'tcx> InferCtxt<'tcx> {
/// Used by the new solver as that one takes the opaque types at the end of a probe
/// to deal with multiple candidates without having to recompute them.
- pub fn clone_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+ pub fn clone_opaque_types_for_query_response(
+ &self,
+ ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
self.inner
.borrow()
.opaque_type_storage
.opaque_types
.iter()
- .map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
+ .map(|(k, v)| (*k, v.hidden_type.ty))
.collect()
}
- fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'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)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
+ .map(|(k, v)| (k, v.hidden_type.ty))
.collect()
}
@@ -467,11 +469,11 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
GenericArgKind::Const(result_value) => {
- if let ty::ConstKind::Bound(debrujin, b) = result_value.kind() {
+ if let ty::ConstKind::Bound(debruijn, b) = result_value.kind() {
// ...in which case we would set `canonical_vars[0]` to `Some(const X)`.
// We only allow a `ty::INNERMOST` index in substitutions.
- assert_eq!(debrujin, ty::INNERMOST);
+ assert_eq!(debruijn, ty::INNERMOST);
opt_values[b] = Some(*original_value);
}
}
@@ -507,8 +509,22 @@ impl<'tcx> InferCtxt<'tcx> {
let a = substitute_value(self.tcx, &result_subst, a);
let b = substitute_value(self.tcx, &result_subst, b);
debug!(?a, ?b, "constrain opaque type");
- obligations
- .extend(self.at(cause, param_env).eq(DefineOpaqueTypes::Yes, a, b)?.obligations);
+ // We use equate here instead of, for example, just registering the
+ // opaque type's hidden value directly, because we may be instantiating
+ // a query response that was canonicalized in an InferCtxt that had
+ // a different defining anchor. In that case, we may have inferred
+ // `NonLocalOpaque := LocalOpaque` but can only instantiate it in
+ // the other direction as `LocalOpaque := NonLocalOpaque`. Using eq
+ // here allows us to try both directions (in `InferCtxt::handle_opaque_type`).
+ obligations.extend(
+ self.at(cause, param_env)
+ .eq(
+ DefineOpaqueTypes::Yes,
+ self.tcx.mk_opaque(a.def_id.to_def_id(), a.substs),
+ b,
+ )?
+ .obligations,
+ );
}
Ok(InferOk { value: result_subst, obligations })
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index fe45b5ebe..b6b935de6 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -26,24 +26,17 @@ use super::equate::Equate;
use super::glb::Glb;
use super::lub::Lub;
use super::sub::Sub;
-use super::type_variable::TypeVariableValue;
-use super::{DefineOpaqueTypes, InferCtxt, MiscVariable, TypeTrace};
+use super::{DefineOpaqueTypes, InferCtxt, TypeTrace};
+use crate::infer::generalize::{self, CombineDelegate, Generalization};
use crate::traits::{Obligation, PredicateObligations};
-use rustc_data_structures::sso::SsoHashMap;
-use rustc_hir::def_id::DefId;
use rustc_middle::infer::canonical::OriginalQueryValues;
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{
- self, AliasKind, FallibleTypeFolder, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable,
- TypeSuperFoldable, TypeVisitableExt,
-};
+use rustc_middle::ty::relate::{RelateResult, TypeRelation};
+use rustc_middle::ty::{self, AliasKind, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{IntType, UintType};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::DUMMY_SP;
#[derive(Clone)]
pub struct CombineFields<'infcx, 'tcx> {
@@ -55,13 +48,6 @@ pub struct CombineFields<'infcx, 'tcx> {
pub define_opaque_types: DefineOpaqueTypes,
}
-#[derive(Copy, Clone, Debug)]
-pub enum RelationDir {
- SubtypeOf,
- SupertypeOf,
- EqTo,
-}
-
impl<'tcx> InferCtxt<'tcx> {
pub fn super_combine_tys<R>(
&self,
@@ -73,6 +59,8 @@ impl<'tcx> InferCtxt<'tcx> {
R: ObligationEmittingRelation<'tcx>,
{
let a_is_expected = relation.a_is_expected();
+ debug_assert!(!a.has_escaping_bound_vars());
+ debug_assert!(!b.has_escaping_bound_vars());
match (a.kind(), b.kind()) {
// Relate integral variables to other types
@@ -125,9 +113,7 @@ impl<'tcx> InferCtxt<'tcx> {
bug!()
}
- (_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _)
- if self.tcx.trait_solver_next() =>
- {
+ (_, ty::Alias(..)) | (ty::Alias(..), _) if self.tcx.trait_solver_next() => {
relation.register_type_relate_obligation(a, b);
Ok(a)
}
@@ -149,7 +135,7 @@ impl<'tcx> InferCtxt<'tcx> {
Ok(a)
}
- _ => ty::relate::super_relate_tys(relation, a, b),
+ _ => ty::relate::structurally_relate_tys(relation, a, b),
}
}
@@ -163,6 +149,8 @@ impl<'tcx> InferCtxt<'tcx> {
R: ObligationEmittingRelation<'tcx>,
{
debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
+ debug_assert!(!a.has_escaping_bound_vars());
+ debug_assert!(!b.has_escaping_bound_vars());
if a == b {
return Ok(a);
}
@@ -192,7 +180,7 @@ impl<'tcx> InferCtxt<'tcx> {
self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
self.tcx.sess.delay_span_bug(
DUMMY_SP,
- &format!("cannot relate consts of different types (a={:?}, b={:?})", a, b,),
+ format!("cannot relate consts of different types (a={:?}, b={:?})", a, b,),
)
})
});
@@ -204,13 +192,13 @@ impl<'tcx> InferCtxt<'tcx> {
// HACK: equating both sides with `[const error]` eagerly prevents us
// from leaving unconstrained inference vars during things like impl
// matching in the solver.
- let a_error = self.tcx.const_error_with_guaranteed(a.ty(), guar);
+ let a_error = self.tcx.const_error(a.ty(), guar);
if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
- return self.unify_const_variable(vid, a_error);
+ return self.unify_const_variable(vid, a_error, relation.param_env());
}
- let b_error = self.tcx.const_error_with_guaranteed(b.ty(), guar);
+ let b_error = self.tcx.const_error(b.ty(), guar);
if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
- return self.unify_const_variable(vid, b_error);
+ return self.unify_const_variable(vid, b_error, relation.param_env());
}
return Ok(if relation.a_is_expected() { a_error } else { b_error });
@@ -232,32 +220,22 @@ impl<'tcx> InferCtxt<'tcx> {
}
(ty::ConstKind::Infer(InferConst::Var(vid)), _) => {
- return self.unify_const_variable(vid, b);
+ return self.unify_const_variable(vid, b, relation.param_env());
}
(_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
- return self.unify_const_variable(vid, a);
+ return self.unify_const_variable(vid, a, relation.param_env());
}
- (ty::ConstKind::Unevaluated(..), _) if self.tcx.lazy_normalization() => {
- // FIXME(#59490): Need to remove the leak check to accommodate
- // escaping bound variables here.
- if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
- relation.register_const_equate_obligation(a, b);
- }
+ (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
+ if self.tcx.lazy_normalization() =>
+ {
+ relation.register_const_equate_obligation(a, b);
return Ok(b);
}
- (_, ty::ConstKind::Unevaluated(..)) if self.tcx.lazy_normalization() => {
- // FIXME(#59490): Need to remove the leak check to accommodate
- // escaping bound variables here.
- if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
- relation.register_const_equate_obligation(a, b);
- }
- return Ok(a);
- }
_ => {}
}
- ty::relate::super_relate_consts(relation, a, b)
+ ty::relate::structurally_relate_consts(relation, a, b)
}
/// Unifies the const variable `target_vid` with the given constant.
@@ -299,24 +277,17 @@ impl<'tcx> InferCtxt<'tcx> {
&self,
target_vid: ty::ConstVid<'tcx>,
ct: ty::Const<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
) -> RelateResult<'tcx, ty::Const<'tcx>> {
- let (for_universe, span) = {
- let mut inner = self.inner.borrow_mut();
- let variable_table = &mut inner.const_unification_table();
- let var_value = variable_table.probe_value(target_vid);
- match var_value.val {
- ConstVariableValue::Known { value } => {
- bug!("instantiating {:?} which has a known value {:?}", target_vid, value)
- }
- ConstVariableValue::Unknown { universe } => (universe, var_value.origin.span),
- }
- };
- let value = ct.try_fold_with(&mut ConstInferUnifier {
- infcx: self,
- span,
- for_universe,
+ let span =
+ self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span;
+ let Generalization { value, needs_wf: _ } = generalize::generalize(
+ self,
+ &mut CombineDelegate { infcx: self, span, param_env },
+ ct,
target_vid,
- })?;
+ ty::Variance::Invariant,
+ )?;
self.inner.borrow_mut().const_unification_table().union_value(
target_vid,
@@ -397,12 +368,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
pub fn instantiate(
&mut self,
a_ty: Ty<'tcx>,
- dir: RelationDir,
+ ambient_variance: ty::Variance,
b_vid: ty::TyVid,
a_is_expected: bool,
) -> RelateResult<'tcx, ()> {
- use self::RelationDir::*;
-
// Get the actual variable that b_vid has been inferred to
debug_assert!(self.infcx.inner.borrow_mut().type_variables().probe(b_vid).is_unknown());
@@ -417,7 +386,18 @@ 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 { ty: b_ty, needs_wf } = self.generalize(a_ty, b_vid, dir)?;
+ let Generalization { value: b_ty, needs_wf } = generalize::generalize(
+ self.infcx,
+ &mut CombineDelegate {
+ infcx: self.infcx,
+ param_env: self.param_env,
+ span: self.trace.span(),
+ },
+ a_ty,
+ b_vid,
+ ambient_variance,
+ )?;
+
debug!(?b_ty);
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
@@ -436,78 +416,23 @@ 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 dir {
- EqTo => self.equate(a_is_expected).relate(a_ty, b_ty),
- SubtypeOf => self.sub(a_is_expected).relate(a_ty, b_ty),
- SupertypeOf => self.sub(a_is_expected).relate_with_variance(
+ 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)")
+ }
}?;
Ok(())
}
- /// Attempts to generalize `ty` for the type variable `for_vid`.
- /// This checks for cycle -- that is, whether the type `ty`
- /// references `for_vid`. The `dir` is the "direction" for which we
- /// a performing the generalization (i.e., are we producing a type
- /// that can be used as a supertype etc).
- ///
- /// Preconditions:
- ///
- /// - `for_vid` is a "root vid"
- #[instrument(skip(self), level = "trace", ret)]
- fn generalize(
- &self,
- ty: Ty<'tcx>,
- for_vid: ty::TyVid,
- dir: RelationDir,
- ) -> RelateResult<'tcx, Generalization<'tcx>> {
- // Determine the ambient variance within which `ty` appears.
- // The surrounding equation is:
- //
- // ty [op] ty2
- //
- // where `op` is either `==`, `<:`, or `:>`. This maps quite
- // naturally.
- let ambient_variance = match dir {
- RelationDir::EqTo => ty::Invariant,
- RelationDir::SubtypeOf => ty::Covariant,
- RelationDir::SupertypeOf => ty::Contravariant,
- };
-
- trace!(?ambient_variance);
-
- let for_universe = match self.infcx.inner.borrow_mut().type_variables().probe(for_vid) {
- v @ TypeVariableValue::Known { .. } => {
- bug!("instantiating {:?} which has a known value {:?}", for_vid, v,)
- }
- TypeVariableValue::Unknown { universe } => universe,
- };
-
- trace!(?for_universe);
- trace!(?self.trace);
-
- let mut generalize = Generalizer {
- infcx: self.infcx,
- cause: &self.trace.cause,
- for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
- for_universe,
- ambient_variance,
- needs_wf: false,
- root_ty: ty,
- param_env: self.param_env,
- cache: SsoHashMap::new(),
- };
-
- let ty = generalize.relate(ty, ty)?;
- let needs_wf = generalize.needs_wf;
- Ok(Generalization { ty, needs_wf })
- }
-
pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.obligations.extend(obligations.into_iter());
}
@@ -519,320 +444,13 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
}
}
-struct Generalizer<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'tcx>,
-
- /// The span, used when creating new type variables and things.
- cause: &'cx ObligationCause<'tcx>,
-
- /// The vid of the type variable that is in the process of being
- /// instantiated; if we find this within the type we are folding,
- /// that means we would have created a cyclic type.
- for_vid_sub_root: ty::TyVid,
-
- /// The universe of the type variable that is in the process of
- /// being instantiated. Any fresh variables that we create in this
- /// process should be in that same universe.
- for_universe: ty::UniverseIndex,
-
- /// Track the variance as we descend into the type.
- ambient_variance: ty::Variance,
-
- /// See the field `needs_wf` in `Generalization`.
- needs_wf: bool,
-
- /// The root type that we are generalizing. Used when reporting cycles.
- root_ty: Ty<'tcx>,
-
- param_env: ty::ParamEnv<'tcx>,
-
- cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
-}
-
-/// Result from a generalization operation. This includes
-/// not only the generalized type, but also a bool flag
-/// indicating whether further WF checks are needed.
-#[derive(Debug)]
-struct Generalization<'tcx> {
- ty: Ty<'tcx>,
-
- /// If true, then the generalized type may not be well-formed,
- /// even if the source type is well-formed, so we should add an
- /// additional check to enforce that it is. This arises in
- /// particular around 'bivariant' type parameters that are only
- /// constrained by a where-clause. As an example, imagine a type:
- ///
- /// struct Foo<A, B> where A: Iterator<Item = B> {
- /// data: A
- /// }
- ///
- /// here, `A` will be covariant, but `B` is
- /// unconstrained. However, whatever it is, for `Foo` to be WF, it
- /// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
- /// then after generalization we will wind up with a type like
- /// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
- /// ?D>` (or `>:`), we will wind up with the requirement that `?A
- /// <: ?C`, but no particular relationship between `?B` and `?D`
- /// (after all, we do not know the variance of the normalized form
- /// of `A::Item` with respect to `A`). If we do nothing else, this
- /// may mean that `?D` goes unconstrained (as in #41677). So, in
- /// this scenario where we create a new type variable in a
- /// bivariant context, we set the `needs_wf` flag to true. This
- /// will force the calling code to check that `WF(Foo<?C, ?D>)`
- /// holds, which in turn implies that `?C::Item == ?D`. So once
- /// `?C` is constrained, that should suffice to restrict `?D`.
- needs_wf: bool,
-}
-
-impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
- self.infcx.tcx
- }
-
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env
- }
-
- fn tag(&self) -> &'static str {
- "Generalizer"
- }
-
- fn a_is_expected(&self) -> bool {
- true
- }
-
- fn binders<T>(
- &mut self,
- a: ty::Binder<'tcx, T>,
- b: ty::Binder<'tcx, T>,
- ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
- where
- T: Relate<'tcx>,
- {
- Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
- }
-
- fn relate_item_substs(
- &mut self,
- item_def_id: DefId,
- a_subst: SubstsRef<'tcx>,
- b_subst: SubstsRef<'tcx>,
- ) -> RelateResult<'tcx, SubstsRef<'tcx>> {
- if self.ambient_variance == ty::Variance::Invariant {
- // Avoid fetching the variance if we are in an invariant
- // context; no need, and it can induce dependency cycles
- // (e.g., #41849).
- relate::relate_substs(self, a_subst, b_subst)
- } else {
- let tcx = self.tcx();
- let opt_variances = tcx.variances_of(item_def_id);
- relate::relate_substs_with_variances(
- self,
- item_def_id,
- &opt_variances,
- a_subst,
- b_subst,
- true,
- )
- }
- }
-
- fn relate_with_variance<T: Relate<'tcx>>(
- &mut self,
- variance: ty::Variance,
- _info: ty::VarianceDiagInfo<'tcx>,
- a: T,
- b: T,
- ) -> RelateResult<'tcx, T> {
- let old_ambient_variance = self.ambient_variance;
- self.ambient_variance = self.ambient_variance.xform(variance);
-
- let result = self.relate(a, b);
- self.ambient_variance = old_ambient_variance;
- result
- }
-
- fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
- assert_eq!(t, t2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
-
- if let Some(&result) = self.cache.get(&t) {
- return Ok(result);
- }
- debug!("generalize: t={:?}", t);
-
- // Check to see whether the type we are generalizing references
- // any other type variable related to `vid` via
- // subtyping. This is basically our "occurs check", preventing
- // us from creating infinitely sized types.
- let result = match *t.kind() {
- ty::Infer(ty::TyVar(vid)) => {
- let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
- let sub_vid = self.infcx.inner.borrow_mut().type_variables().sub_root_var(vid);
- if sub_vid == self.for_vid_sub_root {
- // If sub-roots are equal, then `for_vid` and
- // `vid` are related via subtyping.
- Err(TypeError::CyclicTy(self.root_ty))
- } else {
- let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
- match probe {
- TypeVariableValue::Known { value: u } => {
- debug!("generalize: known value {:?}", u);
- self.relate(u, u)
- }
- TypeVariableValue::Unknown { universe } => {
- match self.ambient_variance {
- // Invariant: no need to make a fresh type variable.
- ty::Invariant => {
- if self.for_universe.can_name(universe) {
- return Ok(t);
- }
- }
-
- // Bivariant: make a fresh var, but we
- // may need a WF predicate. See
- // comment on `needs_wf` field for
- // more info.
- ty::Bivariant => self.needs_wf = true,
-
- // Co/contravariant: this will be
- // sufficiently constrained later on.
- ty::Covariant | ty::Contravariant => (),
- }
-
- let origin =
- *self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
- let new_var_id = self
- .infcx
- .inner
- .borrow_mut()
- .type_variables()
- .new_var(self.for_universe, origin);
- let u = self.tcx().mk_ty_var(new_var_id);
-
- // Record that we replaced `vid` with `new_var_id` as part of a generalization
- // operation. This is needed to detect cyclic types. To see why, see the
- // docs in the `type_variables` module.
- self.infcx.inner.borrow_mut().type_variables().sub(vid, new_var_id);
- debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
- Ok(u)
- }
- }
- }
- }
- ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
- // No matter what mode we are in,
- // integer/floating-point types must be equal to be
- // relatable.
- Ok(t)
- }
- ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
- let s = self.relate(substs, substs)?;
- Ok(if s == substs { t } else { self.infcx.tcx.mk_opaque(def_id, s) })
- }
- _ => relate::super_relate_tys(self, t, t),
- }?;
-
- self.cache.insert(t, result);
- Ok(result)
- }
-
- fn regions(
- &mut self,
- r: ty::Region<'tcx>,
- r2: ty::Region<'tcx>,
- ) -> RelateResult<'tcx, ty::Region<'tcx>> {
- assert_eq!(r, r2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
-
- debug!("generalize: regions r={:?}", r);
-
- match *r {
- // Never make variables for regions bound within the type itself,
- // nor for erased regions.
- ty::ReLateBound(..) | ty::ReErased => {
- return Ok(r);
- }
-
- ty::ReError(_) => {
- return Ok(r);
- }
-
- ty::RePlaceholder(..)
- | ty::ReVar(..)
- | ty::ReStatic
- | ty::ReEarlyBound(..)
- | ty::ReFree(..) => {
- // see common code below
- }
- }
-
- // If we are in an invariant context, we can re-use the region
- // as is, unless it happens to be in some universe that we
- // can't name. (In the case of a region *variable*, we could
- // use it if we promoted it into our universe, but we don't
- // bother.)
- if let ty::Invariant = self.ambient_variance {
- let r_universe = self.infcx.universe_of_region(r);
- if self.for_universe.can_name(r_universe) {
- return Ok(r);
- }
- }
-
- // FIXME: This is non-ideal because we don't give a
- // very descriptive origin for this region variable.
- Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe))
- }
-
- fn consts(
- &mut self,
- c: ty::Const<'tcx>,
- c2: ty::Const<'tcx>,
- ) -> RelateResult<'tcx, ty::Const<'tcx>> {
- assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be ==
-
- match c.kind() {
- ty::ConstKind::Infer(InferConst::Var(vid)) => {
- let mut inner = self.infcx.inner.borrow_mut();
- let variable_table = &mut inner.const_unification_table();
- let var_value = variable_table.probe_value(vid);
- match var_value.val {
- ConstVariableValue::Known { value: u } => {
- drop(inner);
- self.relate(u, u)
- }
- ConstVariableValue::Unknown { universe } => {
- if self.for_universe.can_name(universe) {
- Ok(c)
- } else {
- let new_var_id = variable_table.new_key(ConstVarValue {
- origin: var_value.origin,
- val: ConstVariableValue::Unknown { universe: self.for_universe },
- });
- Ok(self.tcx().mk_const(new_var_id, c.ty()))
- }
- }
- }
- }
- ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
- let substs = self.relate_with_variance(
- ty::Variance::Invariant,
- ty::VarianceDiagInfo::default(),
- substs,
- substs,
- )?;
- Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
- }
- _ => relate::super_relate_consts(self, c, c),
- }
- }
-}
-
pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
/// Register obligations that must hold in order for this relation to hold
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
/// Register predicates that must hold in order for this relation to hold. Uses
/// a default obligation cause, [`ObligationEmittingRelation::register_obligations`] should
- /// be used if control over the obligaton causes is required.
+ /// be used if control over the obligation causes is required.
fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>);
/// Register an obligation that both constants must be equal to each other.
@@ -878,135 +496,3 @@ fn float_unification_error<'tcx>(
let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v;
TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b))
}
-
-struct ConstInferUnifier<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'tcx>,
-
- span: Span,
-
- for_universe: ty::UniverseIndex,
-
- /// The vid of the const variable that is in the process of being
- /// instantiated; if we find this within the const we are folding,
- /// that means we would have created a cyclic const.
- target_vid: ty::ConstVid<'tcx>,
-}
-
-impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for ConstInferUnifier<'_, 'tcx> {
- type Error = TypeError<'tcx>;
-
- fn interner(&self) -> TyCtxt<'tcx> {
- self.infcx.tcx
- }
-
- #[instrument(level = "debug", skip(self), ret)]
- fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, TypeError<'tcx>> {
- match t.kind() {
- &ty::Infer(ty::TyVar(vid)) => {
- let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
- let probe = self.infcx.inner.borrow_mut().type_variables().probe(vid);
- match probe {
- TypeVariableValue::Known { value: u } => {
- debug!("ConstOccursChecker: known value {:?}", u);
- u.try_fold_with(self)
- }
- TypeVariableValue::Unknown { universe } => {
- if self.for_universe.can_name(universe) {
- return Ok(t);
- }
-
- let origin =
- *self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
- let new_var_id = self
- .infcx
- .inner
- .borrow_mut()
- .type_variables()
- .new_var(self.for_universe, origin);
- Ok(self.interner().mk_ty_var(new_var_id))
- }
- }
- }
- ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => Ok(t),
- _ => t.try_super_fold_with(self),
- }
- }
-
- #[instrument(level = "debug", skip(self), ret)]
- fn try_fold_region(
- &mut self,
- r: ty::Region<'tcx>,
- ) -> Result<ty::Region<'tcx>, TypeError<'tcx>> {
- debug!("ConstInferUnifier: r={:?}", r);
-
- match *r {
- // Never make variables for regions bound within the type itself,
- // nor for erased regions.
- ty::ReLateBound(..) | ty::ReErased | ty::ReError(_) => {
- return Ok(r);
- }
-
- ty::RePlaceholder(..)
- | ty::ReVar(..)
- | ty::ReStatic
- | ty::ReEarlyBound(..)
- | ty::ReFree(..) => {
- // see common code below
- }
- }
-
- let r_universe = self.infcx.universe_of_region(r);
- if self.for_universe.can_name(r_universe) {
- return Ok(r);
- } else {
- // FIXME: This is non-ideal because we don't give a
- // very descriptive origin for this region variable.
- Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe))
- }
- }
-
- #[instrument(level = "debug", skip(self), ret)]
- fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, TypeError<'tcx>> {
- match c.kind() {
- ty::ConstKind::Infer(InferConst::Var(vid)) => {
- // Check if the current unification would end up
- // unifying `target_vid` with a const which contains
- // an inference variable which is unioned with `target_vid`.
- //
- // Not doing so can easily result in stack overflows.
- if self
- .infcx
- .inner
- .borrow_mut()
- .const_unification_table()
- .unioned(self.target_vid, vid)
- {
- return Err(TypeError::CyclicConst(c));
- }
-
- let var_value =
- self.infcx.inner.borrow_mut().const_unification_table().probe_value(vid);
- match var_value.val {
- ConstVariableValue::Known { value: u } => u.try_fold_with(self),
- ConstVariableValue::Unknown { universe } => {
- if self.for_universe.can_name(universe) {
- Ok(c)
- } else {
- let new_var_id =
- self.infcx.inner.borrow_mut().const_unification_table().new_key(
- ConstVarValue {
- origin: var_value.origin,
- val: ConstVariableValue::Unknown {
- universe: self.for_universe,
- },
- },
- );
- Ok(self.interner().mk_const(new_var_id, c.ty()))
- }
- }
- }
- }
- _ => c.try_super_fold_with(self),
- }
- }
-}
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index fe4a2dd38..42dfe4f6b 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -1,7 +1,7 @@
use crate::infer::DefineOpaqueTypes;
use crate::traits::PredicateObligations;
-use super::combine::{CombineFields, ObligationEmittingRelation, RelationDir};
+use super::combine::{CombineFields, ObligationEmittingRelation};
use super::Subtype;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
@@ -88,11 +88,11 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
}
(&ty::Infer(TyVar(a_id)), _) => {
- self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?;
+ self.fields.instantiate(b, ty::Invariant, a_id, self.a_is_expected)?;
}
(_, &ty::Infer(TyVar(b_id))) => {
- self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
+ self.fields.instantiate(a, ty::Invariant, b_id, self.a_is_expected)?;
}
(
@@ -104,7 +104,8 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
- && def_id.is_local() =>
+ && def_id.is_local()
+ && !self.tcx().trait_solver_next() =>
{
self.fields.obligations.extend(
infcx
@@ -178,7 +179,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
where
T: Relate<'tcx>,
{
- // A binder is equal to itself if it's structually equal to itself
+ // A binder is equal to itself if it's structurally equal to itself
if a == b {
return Ok(a);
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 9e5f6d107..35c05e80b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -74,7 +74,6 @@ use rustc_middle::ty::{
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt,
};
-use rustc_span::DUMMY_SP;
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
use std::ops::{ControlFlow, Deref};
@@ -138,7 +137,7 @@ impl Drop for TypeErrCtxt<'_, '_> {
self.infcx
.tcx
.sess
- .delay_span_bug(DUMMY_SP, "used a `TypeErrCtxt` without failing compilation");
+ .delay_good_path_bug("used a `TypeErrCtxt` without raising an error or lint");
}
}
}
@@ -283,9 +282,9 @@ fn emit_msg_span(
let message = format!("{}{}{}", prefix, description, suffix);
if let Some(span) = span {
- err.span_note(span, &message);
+ err.span_note(span, message);
} else {
- err.note(&message);
+ err.note(message);
}
}
@@ -299,9 +298,9 @@ fn label_msg_span(
let message = format!("{}{}{}", prefix, description, suffix);
if let Some(span) = span {
- err.span_label(span, &message);
+ err.span_label(span, message);
} else {
- err.note(&message);
+ err.note(message);
}
}
@@ -403,7 +402,7 @@ impl<'tcx> InferCtxt<'tcx> {
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
- self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs).find_map(
+ self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs).find_map(
|(predicate, _)| {
predicate
.kind()
@@ -1826,7 +1825,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
s
};
if !(values.expected.is_simple_text() && values.found.is_simple_text())
- || (exp_found.map_or(false, |ef| {
+ || (exp_found.is_some_and(|ef| {
// This happens when the type error is a subset of the expectation,
// like when you have two references but one is `usize` and the other
// is `f32`. In those cases we still want to show the `note`. If the
@@ -1878,7 +1877,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let exp_found = match terr {
// `terr` has more accurate type information than `exp_found` in match expressions.
ty::error::TypeError::Sorts(terr)
- if exp_found.map_or(false, |ef| terr.found == ef.found) =>
+ if exp_found.is_some_and(|ef| terr.found == ef.found) =>
{
Some(terr)
}
@@ -1927,6 +1926,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
{
let span = self.tcx.def_span(def_id);
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), &exp_found, diag);
}
// It reads better to have the error origin as the final
@@ -1961,7 +1961,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
&& let Some(code) = code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
&& !code.starts_with("\\u") // forbid all Unicode escapes
- && code.chars().next().map_or(false, |c| c.is_ascii()) // forbids literal Unicode characters beyond ASCII
+ && code.chars().next().is_some_and(|c| c.is_ascii()) // forbids literal Unicode characters beyond ASCII
{
suggestions.push(TypeErrorAdditionalDiags::MeantByteLiteral { span, code: escape_literal(code) })
}
@@ -2329,7 +2329,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
.source_map()
.span_to_prev_source(p.span.shrink_to_hi())
.ok()
- .map_or(false, |s| *s.as_bytes().last().unwrap() == b'&')
+ .is_some_and(|s| *s.as_bytes().last().unwrap() == b'&')
{
add_lt_suggs
.push(Some(
@@ -2354,7 +2354,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let labeled_user_string = match bound_kind {
GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
GenericKind::Alias(ref p) => match p.kind(self.tcx) {
- ty::AliasKind::Projection => format!("the associated type `{}`", p),
+ ty::AliasKind::Projection | ty::AliasKind::Inherent => {
+ format!("the associated type `{}`", p)
+ }
ty::AliasKind::Opaque => format!("the opaque type `{}`", p),
},
};
@@ -2395,7 +2397,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
);
} else {
let consider = format!("{} `{}: {}`...", msg, bound_kind, sub);
- err.help(&consider);
+ err.help(consider);
}
}
@@ -2625,7 +2627,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
);
err.span_note(
sup_trace.cause.span,
- &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
+ format!("...so that the {}", sup_trace.cause.as_requirement_str()),
);
err.note_expected_found(&"", sup_expected, &"", sup_found);
@@ -2721,7 +2723,7 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
| (ty::Infer(ty::InferTy::TyVar(_)), _)
| (_, ty::Infer(ty::InferTy::TyVar(_))) => Ok(a),
(ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Mismatch),
- _ => relate::super_relate_tys(self, a, b),
+ _ => relate::structurally_relate_tys(self, a, b),
}
}
@@ -2885,7 +2887,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
LetElse => ObligationCauseFailureCode::NoDiverge { span, subdiags },
MainFunctionType => ObligationCauseFailureCode::FnMainCorrectType { span },
StartFunctionType => ObligationCauseFailureCode::FnStartCorrectType { span, subdiags },
- IntrinsicType => ObligationCauseFailureCode::IntristicCorrectType { span, subdiags },
+ IntrinsicType => ObligationCauseFailureCode::IntrinsicCorrectType { span, subdiags },
MethodReceiver => ObligationCauseFailureCode::MethodCorrectType { span, subdiags },
// In the case where we have no more specific thing to
@@ -2942,7 +2944,7 @@ impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> {
IfExpressionWithNoElse => "no_else",
MainFunctionType => "fn_main_correct_type",
StartFunctionType => "fn_start_correct_type",
- IntrinsicType => "intristic_correct_type",
+ IntrinsicType => "intrinsic_correct_type",
MethodReceiver => "method_correct_type",
_ => "other",
}
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 75cc4e257..f3b2ec4c5 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
@@ -1,5 +1,5 @@
use crate::errors::{
- AmbigousReturn, AmbiguousImpl, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator,
+ AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator,
SourceKindMultiSuggestion, SourceKindSubdiag,
};
use crate::infer::error_reporting::TypeErrCtxt;
@@ -31,7 +31,7 @@ pub enum TypeAnnotationNeeded {
/// ```
E0282,
/// An implementation cannot be chosen unambiguously because of lack of information.
- /// ```compile_fail,E0283
+ /// ```compile_fail,E0790
/// let _ = Default::default();
/// ```
E0283,
@@ -368,7 +368,7 @@ impl<'tcx> InferCtxt<'tcx> {
bad_label,
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
- TypeAnnotationNeeded::E0284 => AmbigousReturn {
+ TypeAnnotationNeeded::E0284 => AmbiguousReturn {
span,
source_kind,
source_name,
@@ -573,7 +573,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
bad_label: None,
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
- TypeAnnotationNeeded::E0284 => AmbigousReturn {
+ TypeAnnotationNeeded::E0284 => AmbiguousReturn {
span,
source_kind,
source_name: &name,
@@ -671,7 +671,7 @@ impl<'tcx> InferSource<'tcx> {
receiver.span.from_expansion()
}
InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => {
- data.span().from_expansion() || should_wrap_expr.map_or(false, Span::from_expansion)
+ data.span().from_expansion() || should_wrap_expr.is_some_and(Span::from_expansion)
}
};
source_from_expansion || self.span.from_expansion()
@@ -984,7 +984,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
) -> impl Iterator<Item = InsertableGenericArgs<'tcx>> + 'a {
let tcx = self.infcx.tcx;
let have_turbofish = path.segments.iter().any(|segment| {
- segment.args.map_or(false, |args| args.args.iter().any(|arg| arg.is_ty_or_const()))
+ segment.args.is_some_and(|args| args.args.iter().any(|arg| arg.is_ty_or_const()))
});
// The last segment of a path often has `Res::Err` and the
// correct `Res` is the one of the whole path.
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 da0271a34..1a60bab18 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
@@ -21,7 +21,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
///
/// Consider a case where we have
///
- /// ```compile_fail,E0623
+ /// ```compile_fail
/// fn foo(x: &mut Vec<&u8>, y: &u8) {
/// x.push(y);
/// }
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 fec04af23..0df417d09 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
@@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Region, TyCtxt};
/// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
///
/// # Example
-/// ```compile_fail,E0623
+/// ```compile_fail
/// fn foo(x: &mut Vec<&u8>, y: &u8)
/// { x.push(y); }
/// ```
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 c1ea0a0d9..c9c1f0aea 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
@@ -261,11 +261,16 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
(false, None, None, Some(span), String::new())
};
- let expected_trait_ref = self
- .cx
- .resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, expected_substs));
- let actual_trait_ref =
- self.cx.resolve_vars_if_possible(self.cx.tcx.mk_trait_ref(trait_def_id, actual_substs));
+ let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new(
+ self.cx.tcx,
+ trait_def_id,
+ expected_substs,
+ ));
+ let actual_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef::new(
+ self.cx.tcx,
+ trait_def_id,
+ actual_substs,
+ ));
// Search the expected and actual trait references to see (a)
// whether the sub/sup placeholders appear in them (sometimes
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 22c1e3871..aad988582 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
@@ -299,7 +299,7 @@ pub fn suggest_new_region_bound(
if let Some(explicit_static) = &explicit_static {
err.span_suggestion_verbose(
span,
- &format!("{consider} `{ty}`'s {explicit_static}"),
+ format!("{consider} `{ty}`'s {explicit_static}"),
&lifetime_name,
Applicability::MaybeIncorrect,
);
@@ -312,13 +312,10 @@ pub fn suggest_new_region_bound(
Applicability::MaybeIncorrect,
);
}
- } else if opaque.bounds.iter().any(|arg| match arg {
- GenericBound::Outlives(Lifetime { ident, .. })
- if ident.name.to_string() == lifetime_name =>
- {
- true
- }
- _ => false,
+ } else if opaque.bounds.iter().any(|arg| {
+ matches!(arg,
+ GenericBound::Outlives(Lifetime { ident, .. })
+ if ident.name.to_string() == lifetime_name )
}) {
} else {
// get a lifetime name of existing named lifetimes if any
@@ -370,7 +367,7 @@ pub fn suggest_new_region_bound(
spans_suggs
.push((fn_return.span.shrink_to_hi(), format!(" + {name} ")));
err.multipart_suggestion_verbose(
- &format!(
+ format!(
"{declare} `{ty}` {captures}, {use_lt}",
),
spans_suggs,
@@ -379,7 +376,7 @@ pub fn suggest_new_region_bound(
} else {
err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(),
- &format!("{declare} `{ty}` {captures}, {explicit}",),
+ format!("{declare} `{ty}` {captures}, {explicit}",),
&plus_lt,
Applicability::MaybeIncorrect,
);
@@ -390,7 +387,7 @@ pub fn suggest_new_region_bound(
if let LifetimeName::ImplicitObjectLifetimeDefault = lt.res {
err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(),
- &format!(
+ format!(
"{declare} the trait object {captures}, {explicit}",
declare = declare,
captures = captures,
@@ -407,7 +404,7 @@ pub fn suggest_new_region_bound(
if let Some(explicit_static) = &explicit_static {
err.span_suggestion_verbose(
lt.ident.span,
- &format!("{} the trait object's {}", consider, explicit_static),
+ format!("{} the trait object's {}", consider, explicit_static),
&lifetime_name,
Applicability::MaybeIncorrect,
);
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 2875448ee..ce70bcc5c 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
@@ -13,7 +13,7 @@ use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::print::RegionHighlightMode;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::Span;
use std::ops::ControlFlow;
@@ -81,7 +81,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
self.highlight.highlighting_region(r, self.counter);
self.counter += 1;
}
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
}
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 b38bbdfe7..421eb807a 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
@@ -2,6 +2,7 @@ use super::TypeErrCtxt;
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::print::Printer;
@@ -71,9 +72,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
#traits-as-parameters",
);
}
- (ty::Alias(ty::Projection, _), ty::Alias(ty::Projection, _)) => {
+ (ty::Alias(ty::Projection | ty::Inherent, _), ty::Alias(ty::Projection | ty::Inherent, _)) => {
diag.note("an associated type was expected, but a different one was found");
}
+ // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
(ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
if !tcx.is_impl_trait_in_trait(proj.def_id) =>
{
@@ -209,7 +211,7 @@ impl<T> Trait<T> for X {
if !sp.contains(p_span) {
diag.span_label(p_span, "this type parameter");
}
- diag.help(&format!(
+ diag.help(format!(
"every closure has a distinct type and so could not always match the \
caller-chosen type of parameter `{}`",
p
@@ -222,7 +224,7 @@ impl<T> Trait<T> for X {
diag.span_label(p_span, "this type parameter");
}
}
- (ty::Alias(ty::Projection, proj_ty), _) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
+ (ty::Alias(ty::Projection | ty::Inherent, proj_ty), _) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
self.expected_projection(
diag,
proj_ty,
@@ -231,7 +233,7 @@ impl<T> Trait<T> for X {
cause.code(),
);
}
- (_, ty::Alias(ty::Projection, proj_ty)) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
+ (_, ty::Alias(ty::Projection | ty::Inherent, proj_ty)) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
let msg = format!(
"consider constraining the associated type `{}` to `{}`",
values.found, values.expected,
@@ -248,13 +250,22 @@ impl<T> Trait<T> for X {
proj_ty,
values.expected,
)) {
- diag.help(&msg);
+ diag.help(msg);
diag.note(
"for more information, visit \
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
);
}
}
+ (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::AssocFn | DefKind::AssocConst) => {
+ if tcx.is_type_alias_impl_trait(alias.def_id) {
+ if !tcx.opaque_types_defined_by(body_owner_def_id.expect_local()).contains(&alias.def_id.expect_local()) {
+ diag.span_note(tcx.def_span(body_owner_def_id), "\
+ this item must have the opaque type in its signature \
+ in order to be able to register hidden types");
+ }
+ }
+ }
(ty::FnPtr(_), ty::FnDef(def, _))
if let hir::def::DefKind::Fn = tcx.def_kind(def) => {
diag.note(
@@ -415,12 +426,12 @@ impl<T> Trait<T> for X {
if !impl_comparison {
// Generic suggestion when we can't be more specific.
if callable_scope {
- diag.help(&format!(
+ diag.help(format!(
"{} or calling a method that returns `{}`",
msg, values.expected
));
} else {
- diag.help(&msg);
+ diag.help(msg);
}
diag.note(
"for more information, visit \
@@ -462,10 +473,7 @@ fn foo(&self) -> Self::T { String::new() }
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
let opaque_local_def_id = def_id.as_local();
let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
- match &tcx.hir().expect_item(opaque_local_def_id).kind {
- hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
- _ => bug!("The HirId comes from a `ty::Opaque`"),
- }
+ tcx.hir().expect_item(opaque_local_def_id).expect_opaque_ty()
} else {
return false;
};
@@ -539,7 +547,7 @@ fn foo(&self) -> Self::T { String::new() }
for (sp, label) in methods.into_iter() {
span.push_span_label(sp, label);
}
- diag.span_help(span, &msg);
+ diag.span_help(span, msg);
return true;
}
false
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index b5aeca12a..d885d0407 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -1,16 +1,15 @@
use hir::def::CtorKind;
use hir::intravisit::{walk_expr, walk_stmt, Visitor};
use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::Diagnostic;
+use rustc_errors::{Applicability, Diagnostic};
use rustc_hir as hir;
use rustc_middle::traits::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
StatementAsExpression,
};
use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitableExt};
+use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt};
use rustc_span::{sym, BytePos, Span};
-use rustc_target::abi::FieldIdx;
use crate::errors::{
ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
@@ -114,7 +113,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
})
.filter_map(|variant| {
- let sole_field = &variant.fields[FieldIdx::from_u32(0)];
+ let sole_field = &variant.single_field();
let sole_field_ty = sole_field.ty(self.tcx, substs);
if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
let variant_path =
@@ -536,6 +535,82 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
None
}
+
+ /// For "one type is more general than the other" errors on closures, suggest changing the lifetime
+ /// of the parameters to accept all lifetimes.
+ pub(super) fn suggest_for_all_lifetime_closure(
+ &self,
+ span: Span,
+ hir: hir::Node<'_>,
+ exp_found: &ty::error::ExpectedFound<ty::PolyTraitRef<'tcx>>,
+ diag: &mut Diagnostic,
+ ) {
+ // 0. Extract fn_decl from hir
+ let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(hir::Closure { body, fn_decl, .. }), .. }) = hir else { return; };
+ let hir::Body { params, .. } = self.tcx.hir().body(*body);
+
+ // 1. Get the substs of the closure.
+ // 2. Assume exp_found is FnOnce / FnMut / Fn, we can extract function parameters from [1].
+ let Some(expected) = exp_found.expected.skip_binder().substs.get(1) else { return; };
+ let Some(found) = exp_found.found.skip_binder().substs.get(1) else { return; };
+ let expected = expected.unpack();
+ let found = found.unpack();
+ // 3. Extract the tuple type from Fn trait and suggest the change.
+ if let GenericArgKind::Type(expected) = expected &&
+ let GenericArgKind::Type(found) = found &&
+ let ty::Tuple(expected) = expected.kind() &&
+ let ty::Tuple(found)= found.kind() &&
+ expected.len() == found.len() {
+ let mut suggestion = "|".to_string();
+ let mut is_first = true;
+ let mut has_suggestion = false;
+
+ for (((expected, found), param_hir), arg_hir) in expected.iter()
+ .zip(found.iter())
+ .zip(params.iter())
+ .zip(fn_decl.inputs.iter()) {
+ if is_first {
+ is_first = false;
+ } else {
+ suggestion += ", ";
+ }
+
+ 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() &&
+ let hir::TyKind::Infer = arg_hir.kind {
+ // If the expected region is late bound, the found region is not, and users are asking compiler
+ // to infer the type, we can suggest adding `: &_`.
+ if param_hir.pat.span == param_hir.ty_span {
+ // for `|x|`, `|_|`, `|x: impl Foo|`
+ let Ok(pat) = self.tcx.sess.source_map().span_to_snippet(param_hir.pat.span) else { return; };
+ suggestion += &format!("{}: &_", pat);
+ } else {
+ // for `|x: ty|`, `|_: ty|`
+ let Ok(pat) = self.tcx.sess.source_map().span_to_snippet(param_hir.pat.span) else { return; };
+ let Ok(ty) = self.tcx.sess.source_map().span_to_snippet(param_hir.ty_span) else { return; };
+ suggestion += &format!("{}: &{}", pat, ty);
+ }
+ has_suggestion = true;
+ } else {
+ let Ok(arg) = self.tcx.sess.source_map().span_to_snippet(param_hir.span) else { return; };
+ // Otherwise, keep it as-is.
+ suggestion += &arg;
+ }
+ }
+ suggestion += "|";
+
+ if has_suggestion {
+ diag.span_suggestion_verbose(
+ span,
+ "consider specifying the type of the closure parameters",
+ suggestion,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
}
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index d89f63e5c..0219167f6 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -127,7 +127,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
#[inline]
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- if !t.needs_infer() && !t.has_erasable_regions() {
+ if !t.has_infer() && !t.has_erasable_regions() {
t
} else {
match *t.kind() {
diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs
new file mode 100644
index 000000000..d4a1dacde
--- /dev/null
+++ b/compiler/rustc_infer/src/infer/generalize.rs
@@ -0,0 +1,479 @@
+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_span::Span;
+
+use crate::infer::nll_relate::TypeRelatingDelegate;
+use crate::infer::type_variable::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>>(
+ infcx: &InferCtxt<'tcx>,
+ delegate: &mut D,
+ term: T,
+ for_vid: impl Into<ty::TermVid<'tcx>>,
+ ambient_variance: ty::Variance,
+) -> RelateResult<'tcx, Generalization<T>> {
+ let (for_universe, root_vid) = match for_vid.into() {
+ ty::TermVid::Ty(ty_vid) => (
+ infcx.probe_ty_var(ty_vid).unwrap_err(),
+ ty::TermVid::Ty(infcx.inner.borrow_mut().type_variables().sub_root_var(ty_vid)),
+ ),
+ ty::TermVid::Const(ct_vid) => (
+ infcx.probe_const_var(ct_vid).unwrap_err(),
+ ty::TermVid::Const(infcx.inner.borrow_mut().const_unification_table().find(ct_vid)),
+ ),
+ };
+
+ let mut generalizer = Generalizer {
+ infcx,
+ delegate,
+ ambient_variance,
+ root_vid,
+ for_universe,
+ root_term: term.into(),
+ needs_wf: false,
+ cache: Default::default(),
+ };
+
+ assert!(!term.has_escaping_bound_vars());
+ let value = generalizer.relate(term, term)?;
+ let needs_wf = generalizer.needs_wf;
+ Ok(Generalization { value, needs_wf })
+}
+
+/// Abstracts the handling of region vars between HIR and MIR/NLL typechecking
+/// in the generalizer code.
+pub trait GeneralizerDelegate<'tcx> {
+ fn param_env(&self) -> ty::ParamEnv<'tcx>;
+
+ fn forbid_inference_vars() -> bool;
+
+ fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
+}
+
+pub struct CombineDelegate<'cx, 'tcx> {
+ pub infcx: &'cx InferCtxt<'tcx>,
+ pub param_env: ty::ParamEnv<'tcx>,
+ pub span: Span,
+}
+
+impl<'tcx> GeneralizerDelegate<'tcx> for CombineDelegate<'_, 'tcx> {
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ self.param_env
+ }
+
+ fn forbid_inference_vars() -> bool {
+ false
+ }
+
+ 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.
+ self.infcx
+ .next_region_var_in_universe(RegionVariableOrigin::MiscVariable(self.span), universe)
+ }
+}
+
+impl<'tcx, T> GeneralizerDelegate<'tcx> for T
+where
+ T: TypeRelatingDelegate<'tcx>,
+{
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ <Self as TypeRelatingDelegate<'tcx>>::param_env(self)
+ }
+
+ fn forbid_inference_vars() -> bool {
+ <Self as TypeRelatingDelegate<'tcx>>::forbid_inference_vars()
+ }
+
+ fn generalize_region(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
+ <Self as TypeRelatingDelegate<'tcx>>::generalize_existential(self, universe)
+ }
+}
+
+/// The "generalizer" is used when handling inference variables.
+///
+/// The basic strategy for handling a constraint like `?A <: B` is to
+/// apply a "generalization strategy" to the term `B` -- this replaces
+/// all the lifetimes in the term `B` with fresh inference variables.
+/// (You can read more about the strategy in this [blog post].)
+///
+/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
+/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
+/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
+/// establishes `'0: 'x` as a constraint.
+///
+/// [blog post]: https://is.gd/0hKvIr
+struct Generalizer<'me, 'tcx, D> {
+ infcx: &'me InferCtxt<'tcx>,
+
+ /// This is used to abstract the behaviors of the three previous
+ /// generalizer-like implementations (`Generalizer`, `TypeGeneralizer`,
+ /// and `ConstInferUnifier`). See [`GeneralizerDelegate`] for more
+ /// information.
+ delegate: &'me mut D,
+
+ /// After we generalize this type, we are going to relate it to
+ /// some other type. What will be the variance at this point?
+ ambient_variance: ty::Variance,
+
+ /// The vid of the type variable that is in the process of being
+ /// instantiated. If we find this within the value we are folding,
+ /// that means we would have created a cyclic value.
+ root_vid: ty::TermVid<'tcx>,
+
+ /// The universe of the type variable that is in the process of being
+ /// instantiated. If we find anything that this universe cannot name,
+ /// we reject the relation.
+ for_universe: ty::UniverseIndex,
+
+ /// The root term (const or type) we're generalizing. Used for cycle errors.
+ root_term: Term<'tcx>,
+
+ cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
+
+ /// See the field `needs_wf` in `Generalization`.
+ needs_wf: bool,
+}
+
+impl<'tcx, D> Generalizer<'_, 'tcx, D> {
+ /// Create an error that corresponds to the term kind in `root_term`
+ fn cyclic_term_error(&self) -> TypeError<'tcx> {
+ match self.root_term.unpack() {
+ ty::TermKind::Ty(ty) => TypeError::CyclicTy(ty),
+ ty::TermKind::Const(ct) => TypeError::CyclicConst(ct),
+ }
+ }
+}
+
+impl<'tcx, D> TypeRelation<'tcx> for Generalizer<'_, 'tcx, D>
+where
+ D: GeneralizerDelegate<'tcx>,
+{
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.infcx.tcx
+ }
+
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ self.delegate.param_env()
+ }
+
+ fn tag(&self) -> &'static str {
+ "Generalizer"
+ }
+
+ fn a_is_expected(&self) -> bool {
+ true
+ }
+
+ fn relate_item_substs(
+ &mut self,
+ item_def_id: DefId,
+ a_subst: ty::SubstsRef<'tcx>,
+ b_subst: ty::SubstsRef<'tcx>,
+ ) -> RelateResult<'tcx, ty::SubstsRef<'tcx>> {
+ if self.ambient_variance == ty::Variance::Invariant {
+ // Avoid fetching the variance if we are in an invariant
+ // context; no need, and it can induce dependency cycles
+ // (e.g., #41849).
+ relate::relate_substs(self, a_subst, b_subst)
+ } else {
+ let tcx = self.tcx();
+ let opt_variances = tcx.variances_of(item_def_id);
+ relate::relate_substs_with_variances(
+ self,
+ item_def_id,
+ opt_variances,
+ a_subst,
+ b_subst,
+ true,
+ )
+ }
+ }
+
+ #[instrument(level = "debug", skip(self, variance, b), ret)]
+ fn relate_with_variance<T: Relate<'tcx>>(
+ &mut self,
+ variance: ty::Variance,
+ _info: ty::VarianceDiagInfo<'tcx>,
+ a: T,
+ b: T,
+ ) -> RelateResult<'tcx, T> {
+ let old_ambient_variance = self.ambient_variance;
+ self.ambient_variance = self.ambient_variance.xform(variance);
+ debug!(?self.ambient_variance, "new ambient variance");
+ let r = self.relate(a, b)?;
+ self.ambient_variance = old_ambient_variance;
+ Ok(r)
+ }
+
+ #[instrument(level = "debug", skip(self, t2), ret)]
+ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+ assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
+
+ if let Some(&result) = self.cache.get(&t) {
+ return Ok(result);
+ }
+
+ // Check to see whether the type we are generalizing references
+ // any other type variable related to `vid` via
+ // subtyping. This is basically our "occurs check", preventing
+ // us from creating infinitely sized types.
+ let g = match *t.kind() {
+ ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
+ if D::forbid_inference_vars() =>
+ {
+ bug!("unexpected inference variable encountered in NLL generalization: {t}");
+ }
+
+ ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ bug!("unexpected infer type: {t}")
+ }
+
+ ty::Infer(ty::TyVar(vid)) => {
+ let mut inner = self.infcx.inner.borrow_mut();
+ let vid = inner.type_variables().root_var(vid);
+ let sub_vid = inner.type_variables().sub_root_var(vid);
+
+ if ty::TermVid::Ty(sub_vid) == self.root_vid {
+ // If sub-roots are equal, then `root_vid` and
+ // `vid` are related via subtyping.
+ Err(self.cyclic_term_error())
+ } else {
+ let probe = inner.type_variables().probe(vid);
+ match probe {
+ TypeVariableValue::Known { value: u } => {
+ drop(inner);
+ self.relate(u, u)
+ }
+ TypeVariableValue::Unknown { universe } => {
+ match self.ambient_variance {
+ // Invariant: no need to make a fresh type variable
+ // if we can name the universe.
+ ty::Invariant => {
+ if self.for_universe.can_name(universe) {
+ return Ok(t);
+ }
+ }
+
+ // Bivariant: make a fresh var, but we
+ // may need a WF predicate. See
+ // comment on `needs_wf` field for
+ // more info.
+ ty::Bivariant => self.needs_wf = true,
+
+ // Co/contravariant: this will be
+ // sufficiently constrained later on.
+ ty::Covariant | ty::Contravariant => (),
+ }
+
+ let origin = *inner.type_variables().var_origin(vid);
+ let new_var_id =
+ inner.type_variables().new_var(self.for_universe, origin);
+ let u = self.tcx().mk_ty_var(new_var_id);
+
+ // Record that we replaced `vid` with `new_var_id` as part of a generalization
+ // operation. This is needed to detect cyclic types. To see why, see the
+ // docs in the `type_variables` module.
+ inner.type_variables().sub(vid, new_var_id);
+ debug!("replacing original vid={:?} with new={:?}", vid, u);
+ Ok(u)
+ }
+ }
+ }
+ }
+
+ ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
+ // No matter what mode we are in,
+ // integer/floating-point types must be equal to be
+ // relatable.
+ Ok(t)
+ }
+
+ ty::Placeholder(placeholder) => {
+ if self.for_universe.can_name(placeholder.universe) {
+ Ok(t)
+ } else {
+ debug!(
+ "root universe {:?} cannot name placeholder in universe {:?}",
+ self.for_universe, placeholder.universe
+ );
+ Err(TypeError::Mismatch)
+ }
+ }
+
+ _ => relate::structurally_relate_tys(self, t, t),
+ }?;
+
+ self.cache.insert(t, g);
+ Ok(g)
+ }
+
+ #[instrument(level = "debug", skip(self, r2), ret)]
+ fn regions(
+ &mut self,
+ r: ty::Region<'tcx>,
+ r2: ty::Region<'tcx>,
+ ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+ assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
+
+ match *r {
+ // Never make variables for regions bound within the type itself,
+ // nor for erased regions.
+ ty::ReLateBound(..) | ty::ReErased => {
+ return Ok(r);
+ }
+
+ // It doesn't really matter for correctness if we generalize ReError,
+ // since we're already on a doomed compilation path.
+ ty::ReError(_) => {
+ return Ok(r);
+ }
+
+ ty::RePlaceholder(..)
+ | ty::ReVar(..)
+ | ty::ReStatic
+ | ty::ReEarlyBound(..)
+ | ty::ReFree(..) => {
+ // see common code below
+ }
+ }
+
+ // If we are in an invariant context, we can re-use the region
+ // as is, unless it happens to be in some universe that we
+ // can't name.
+ if let ty::Invariant = self.ambient_variance {
+ let r_universe = self.infcx.universe_of_region(r);
+ if self.for_universe.can_name(r_universe) {
+ return Ok(r);
+ }
+ }
+
+ Ok(self.delegate.generalize_region(self.for_universe))
+ }
+
+ #[instrument(level = "debug", skip(self, c2), ret)]
+ fn consts(
+ &mut self,
+ c: ty::Const<'tcx>,
+ c2: ty::Const<'tcx>,
+ ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+ assert_eq!(c, c2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
+
+ match c.kind() {
+ ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
+ bug!("unexpected inference variable encountered in NLL generalization: {:?}", c);
+ }
+ ty::ConstKind::Infer(InferConst::Var(vid)) => {
+ // If root const vids are equal, then `root_vid` and
+ // `vid` are related and we'd be inferring an infinitely
+ // deep const.
+ if ty::TermVid::Const(
+ self.infcx.inner.borrow_mut().const_unification_table().find(vid),
+ ) == self.root_vid
+ {
+ return Err(self.cyclic_term_error());
+ }
+
+ let mut inner = self.infcx.inner.borrow_mut();
+ let variable_table = &mut inner.const_unification_table();
+ let var_value = variable_table.probe_value(vid);
+ match var_value.val {
+ ConstVariableValue::Known { value: u } => {
+ drop(inner);
+ self.relate(u, u)
+ }
+ ConstVariableValue::Unknown { universe } => {
+ if self.for_universe.can_name(universe) {
+ Ok(c)
+ } else {
+ let new_var_id = variable_table.new_key(ConstVarValue {
+ origin: var_value.origin,
+ val: ConstVariableValue::Unknown { universe: self.for_universe },
+ });
+ Ok(self.tcx().mk_const(new_var_id, c.ty()))
+ }
+ }
+ }
+ }
+ // FIXME: remove this branch once `structurally_relate_consts` is fully
+ // structural.
+ ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
+ let substs = self.relate_with_variance(
+ ty::Variance::Invariant,
+ ty::VarianceDiagInfo::default(),
+ substs,
+ substs,
+ )?;
+ Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
+ }
+ ty::ConstKind::Placeholder(placeholder) => {
+ if self.for_universe.can_name(placeholder.universe) {
+ Ok(c)
+ } else {
+ debug!(
+ "root universe {:?} cannot name placeholder in universe {:?}",
+ self.for_universe, placeholder.universe
+ );
+ Err(TypeError::Mismatch)
+ }
+ }
+ _ => relate::structurally_relate_consts(self, c, c),
+ }
+ }
+
+ #[instrument(level = "debug", skip(self), ret)]
+ fn binders<T>(
+ &mut self,
+ a: ty::Binder<'tcx, T>,
+ _: ty::Binder<'tcx, T>,
+ ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
+ where
+ T: Relate<'tcx>,
+ {
+ let result = self.relate(a.skip_binder(), a.skip_binder())?;
+ Ok(a.rebind(result))
+ }
+}
+
+/// Result from a generalization operation. This includes
+/// not only the generalized type, but also a bool flag
+/// indicating whether further WF checks are needed.
+#[derive(Debug)]
+pub struct Generalization<T> {
+ pub value: 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
+ /// additional check to enforce that it is. This arises in
+ /// particular around 'bivariant' type parameters that are only
+ /// constrained by a where-clause. As an example, imagine a type:
+ ///
+ /// struct Foo<A, B> where A: Iterator<Item = B> {
+ /// data: A
+ /// }
+ ///
+ /// here, `A` will be covariant, but `B` is
+ /// unconstrained. However, whatever it is, for `Foo` to be WF, it
+ /// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
+ /// then after generalization we will wind up with a type like
+ /// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
+ /// ?D>` (or `>:`), we will wind up with the requirement that `?A
+ /// <: ?C`, but no particular relationship between `?B` and `?D`
+ /// (after all, we do not know the variance of the normalized form
+ /// of `A::Item` with respect to `A`). If we do nothing else, this
+ /// may mean that `?D` goes unconstrained (as in #41677). So, in
+ /// this scenario where we create a new type variable in a
+ /// bivariant context, we set the `needs_wf` flag to true. This
+ /// will force the calling code to check that `WF(Foo<?C, ?D>)`
+ /// holds, which in turn implies that `?C::Item == ?D`. So once
+ /// `?C` is constrained, that should suffice to restrict `?D`.
+ pub needs_wf: bool,
+}
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index a63cfbc91..c304cd25c 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -42,7 +42,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
// Next, we instantiate each bound region in the subtype
// with a fresh region variable. These region variables --
- // but no other pre-existing region variables -- can name
+ // but no other preexisting region variables -- can name
// the placeholders.
let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub);
diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs
index 7f4c141b9..7190d33d2 100644
--- a/compiler/rustc_infer/src/infer/lattice.rs
+++ b/compiler/rustc_infer/src/infer/lattice.rs
@@ -108,9 +108,12 @@ where
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b),
+
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
- if this.define_opaque_types() == DefineOpaqueTypes::Yes && def_id.is_local() =>
+ if this.define_opaque_types() == DefineOpaqueTypes::Yes
+ && def_id.is_local()
+ && !this.tcx().trait_solver_next() =>
{
this.register_obligations(
infcx
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 f298b95ca..8482ae2aa 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -13,7 +13,7 @@ use rustc_data_structures::graph::implementation::{
Direction, Graph, NodeIndex, INCOMING, OUTGOING,
};
use rustc_data_structures::intern::Interned;
-use rustc_index::vec::{IndexSlice, IndexVec};
+use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::PlaceholderRegion;
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -102,6 +102,17 @@ pub enum RegionResolutionError<'tcx> {
),
}
+impl<'tcx> RegionResolutionError<'tcx> {
+ pub fn origin(&self) -> &SubregionOrigin<'tcx> {
+ match self {
+ RegionResolutionError::ConcreteFailure(origin, _, _)
+ | RegionResolutionError::GenericBoundFailure(origin, _, _)
+ | RegionResolutionError::SubSupConflict(_, _, origin, _, _, _, _)
+ | RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _) => origin,
+ }
+ }
+}
+
struct RegionAndOrigin<'tcx> {
region: Region<'tcx>,
origin: SubregionOrigin<'tcx>,
@@ -131,10 +142,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
self.dump_constraints();
}
- let graph = self.construct_graph();
self.expansion(&mut var_data);
self.collect_errors(&mut var_data, errors);
- self.collect_var_errors(&var_data, &graph, errors);
+ self.collect_var_errors(&var_data, errors);
var_data
}
@@ -622,7 +632,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
fn collect_var_errors(
&self,
var_data: &LexicalRegionResolutions<'tcx>,
- graph: &RegionGraph<'tcx>,
errors: &mut Vec<RegionResolutionError<'tcx>>,
) {
debug!("collect_var_errors, var_data = {:#?}", var_data.values);
@@ -640,6 +649,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// overlapping locations.
let mut dup_vec = IndexVec::from_elem_n(None, self.num_vars());
+ // Only construct the graph when necessary, because it's moderately
+ // expensive.
+ let mut graph = None;
+
for (node_vid, value) in var_data.values.iter_enumerated() {
match *value {
VarValue::Empty(_) | VarValue::Value(_) => { /* Inference successful */ }
@@ -672,7 +685,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// influence the constraints on this value for
// richer diagnostics in `static_impl_trait`.
- self.collect_error_for_expanding_node(graph, &mut dup_vec, node_vid, errors);
+ let g = graph.get_or_insert_with(|| self.construct_graph());
+ self.collect_error_for_expanding_node(g, &mut dup_vec, node_vid, errors);
}
}
}
@@ -821,7 +835,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// resolution errors here; delay ICE in favor of those errors.
self.tcx().sess.delay_span_bug(
self.var_infos[node_idx].origin.span(),
- &format!(
+ format!(
"collect_error_for_expanding_node() could not find \
error for var {:?} in universe {:?}, lower_bounds={:#?}, \
upper_bounds={:#?}",
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 66f51328b..cd99fc312 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -24,7 +24,7 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::traits::select;
+use rustc_middle::traits::{select, DefiningAnchor};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BoundVarReplacerDelegate;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@@ -39,7 +39,6 @@ use rustc_span::Span;
use std::cell::{Cell, RefCell};
use std::fmt;
-use std::ops::Drop;
use self::combine::CombineFields;
use self::error_reporting::TypeErrCtxt;
@@ -59,6 +58,7 @@ pub mod error_reporting;
pub mod free_regions;
mod freshen;
mod fudge;
+mod generalize;
mod glb;
mod higher_ranked;
pub mod lattice;
@@ -231,17 +231,6 @@ impl<'tcx> InferCtxtInner<'tcx> {
}
}
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum DefiningAnchor {
- /// `DefId` of the item.
- Bind(LocalDefId),
- /// When opaque types are not resolved, we `Bubble` up, meaning
- /// return the opaque/hidden type pair from query, for caller of query to handle it.
- Bubble,
- /// Used to catch type mismatch errors when handling opaque types.
- Error,
-}
-
pub struct InferCtxt<'tcx> {
pub tcx: TyCtxt<'tcx>,
@@ -342,11 +331,6 @@ pub struct InferCtxt<'tcx> {
/// there is no type that the user could *actually name* that
/// would satisfy it. This avoids crippling inference, basically.
pub intercrate: bool,
-
- /// Flag that is set when we enter canonicalization. Used for debugging to ensure
- /// that we only collect region information for `BorrowckInferCtxt::reg_var_to_origin`
- /// inside non-canonicalization contexts.
- inside_canonicalization_ctxt: Cell<bool>,
}
/// See the `error_reporting` module for more details.
@@ -638,7 +622,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
skip_leak_check: Cell::new(false),
universe: Cell::new(ty::UniverseIndex::ROOT),
intercrate,
- inside_canonicalization_ctxt: Cell::new(false),
}
}
}
@@ -1228,11 +1211,11 @@ impl<'tcx> InferCtxt<'tcx> {
/// hence that `resolve_regions_and_report_errors` can never be
/// called. This is used only during NLL processing to "hand off" ownership
/// of the set of region variables into the NLL region context.
- pub fn take_region_var_origins(&self) -> VarInfos {
+ pub fn get_region_var_origins(&self) -> VarInfos {
let mut inner = self.inner.borrow_mut();
let (var_infos, data) = inner
.region_constraint_storage
- .take()
+ .clone()
.expect("regions already resolved")
.with_log(&mut inner.undo_log)
.into_infos_and_data();
@@ -1327,7 +1310,7 @@ impl<'tcx> InferCtxt<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
- if !value.needs_infer() {
+ if !value.has_infer() {
return value; // Avoid duplicated subst-folding.
}
let mut r = InferenceLiteralEraser { tcx: self.tcx };
@@ -1365,7 +1348,7 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn fully_resolve<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> FixupResult<'tcx, T> {
let value = resolve::fully_resolve(self, value);
assert!(
- value.as_ref().map_or(true, |value| !value.needs_infer()),
+ value.as_ref().map_or(true, |value| !value.has_infer()),
"`{value:?}` is not fully resolved"
);
value
@@ -1500,7 +1483,7 @@ impl<'tcx> InferCtxt<'tcx> {
Ok(Some(val)) => Ok(self.tcx.mk_const(val, ty)),
Ok(None) => {
let tcx = self.tcx;
- let def_id = unevaluated.def.did;
+ let def_id = unevaluated.def;
span_bug!(
tcx.def_span(def_id),
"unable to construct a constant value for the unevaluated constant {:?}",
@@ -1537,18 +1520,18 @@ impl<'tcx> InferCtxt<'tcx> {
// variables
let tcx = self.tcx;
if substs.has_non_region_infer() {
- if let Some(ct) = tcx.bound_abstract_const(unevaluated.def)? {
+ if let Some(ct) = tcx.thir_abstract_const(unevaluated.def)? {
let ct = tcx.expand_abstract_consts(ct.subst(tcx, substs));
if let Err(e) = ct.error_reported() {
- return Err(ErrorHandled::Reported(e));
+ return Err(ErrorHandled::Reported(e.into()));
} else if ct.has_non_region_infer() || ct.has_non_region_param() {
return Err(ErrorHandled::TooGeneric);
} else {
substs = replace_param_and_infer_substs_with_placeholder(tcx, substs);
}
} else {
- substs = InternalSubsts::identity_for_item(tcx, unevaluated.def.did);
- param_env = tcx.param_env(unevaluated.def.did);
+ substs = InternalSubsts::identity_for_item(tcx, unevaluated.def);
+ param_env = tcx.param_env(unevaluated.def);
}
}
@@ -1577,10 +1560,10 @@ impl<'tcx> InferCtxt<'tcx> {
(TyOrConstInferVar::Ty(ty_var), Ok(inner)) => {
use self::type_variable::TypeVariableValue;
- match inner.try_type_variables_probe_ref(ty_var) {
- Some(TypeVariableValue::Unknown { .. }) => true,
- _ => false,
- }
+ matches!(
+ inner.try_type_variables_probe_ref(ty_var),
+ Some(TypeVariableValue::Unknown { .. })
+ )
}
_ => false,
};
@@ -1636,31 +1619,6 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
}
-
- pub fn inside_canonicalization_ctxt(&self) -> bool {
- self.inside_canonicalization_ctxt.get()
- }
-
- pub fn set_canonicalization_ctxt(&self) -> CanonicalizationCtxtGuard<'_, 'tcx> {
- let prev_ctxt = self.inside_canonicalization_ctxt();
- self.inside_canonicalization_ctxt.set(true);
- CanonicalizationCtxtGuard { prev_ctxt, infcx: self }
- }
-
- fn set_canonicalization_ctxt_to(&self, ctxt: bool) {
- self.inside_canonicalization_ctxt.set(ctxt);
- }
-}
-
-pub struct CanonicalizationCtxtGuard<'cx, 'tcx> {
- prev_ctxt: bool,
- infcx: &'cx InferCtxt<'tcx>,
-}
-
-impl<'cx, 'tcx> Drop for CanonicalizationCtxtGuard<'cx, 'tcx> {
- fn drop(&mut self) {
- self.infcx.set_canonicalization_ctxt_to(self.prev_ctxt)
- }
}
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 9f7b26b87..d3fd01b96 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -21,22 +21,20 @@
//! thing we relate in chalk are basically domain goals and their
//! constituents)
-use crate::infer::InferCtxt;
-use crate::infer::{ConstVarValue, ConstVariableValue};
-use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::traits::{Obligation, PredicateObligations};
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::FnMutDelegate;
-use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
+use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
use rustc_span::{Span, Symbol};
use std::fmt::Debug;
-use std::ops::ControlFlow;
-use super::combine::ObligationEmittingRelation;
+use crate::infer::combine::ObligationEmittingRelation;
+use crate::infer::generalize::{self, Generalization};
+use crate::infer::InferCtxt;
+use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::traits::{Obligation, PredicateObligations};
pub struct TypeRelating<'me, 'tcx, D>
where
@@ -115,11 +113,6 @@ pub trait TypeRelatingDelegate<'tcx> {
fn forbid_inference_vars() -> bool;
}
-#[derive(Clone, Debug, Default)]
-struct BoundRegionScope<'tcx> {
- map: FxHashMap<ty::BoundRegion, ty::Region<'tcx>>,
-}
-
#[derive(Copy, Clone)]
struct UniversallyQuantified(bool);
@@ -204,7 +197,7 @@ where
_ => (),
}
- let generalized_ty = self.generalize_value(value_ty, vid)?;
+ let generalized_ty = self.generalize(value_ty, vid)?;
debug!("relate_ty_var: generalized_ty = {:?}", generalized_ty);
if D::forbid_inference_vars() {
@@ -223,23 +216,15 @@ where
result
}
- fn generalize_value<T: Relate<'tcx>>(
- &mut self,
- value: T,
- for_vid: ty::TyVid,
- ) -> RelateResult<'tcx, T> {
- let universe = self.infcx.probe_ty_var(for_vid).unwrap_err();
-
- let mut generalizer = TypeGeneralizer {
- infcx: self.infcx,
- delegate: &mut self.delegate,
- first_free_index: ty::INNERMOST,
- ambient_variance: self.ambient_variance,
- for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
- universe,
- };
-
- generalizer.relate(value, value)
+ fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
+ let Generalization { value: ty, needs_wf: _ } = generalize::generalize(
+ self.infcx,
+ &mut self.delegate,
+ ty,
+ for_vid,
+ self.ambient_variance,
+ )?;
+ Ok(ty)
}
fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
@@ -488,13 +473,7 @@ where
}
if a == b {
- // Subtle: if a or b has a bound variable that we are lazily
- // substituting, then even if a == b, it could be that the values we
- // will substitute for those bound variables are *not* the same, and
- // hence returning `Ok(a)` is incorrect.
- if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
- return Ok(a);
- }
+ return Ok(a);
}
match (a.kind(), b.kind()) {
@@ -512,16 +491,22 @@ where
(
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
- ) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b).or_else(|err| {
- self.tcx().sess.delay_span_bug(
- self.delegate.span(),
- "failure to relate an opaque to itself should result in an error later on",
- );
- if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
- }),
+ ) if a_def_id == b_def_id || infcx.tcx.trait_solver_next() => {
+ infcx.super_combine_tys(self, a, b).or_else(|err| {
+ // This behavior is only there for the old solver, the new solver
+ // shouldn't ever fail. Instead, it unconditionally emits an
+ // alias-relate goal.
+ assert!(!self.tcx().trait_solver_next());
+ self.tcx().sess.delay_span_bug(
+ self.delegate.span(),
+ "failure to relate an opaque to itself should result in an error later on",
+ );
+ if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
+ })
+ }
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
- if def_id.is_local() =>
+ if def_id.is_local() && !self.tcx().trait_solver_next() =>
{
self.relate_opaques(a, b)
}
@@ -725,287 +710,3 @@ where
})]);
}
}
-
-/// When we encounter a binder like `for<..> fn(..)`, we actually have
-/// to walk the `fn` value to find all the values bound by the `for`
-/// (these are not explicitly present in the ty representation right
-/// now). This visitor handles that: it descends the type, tracking
-/// binder depth, and finds late-bound regions targeting the
-/// `for<..`>. For each of those, it creates an entry in
-/// `bound_region_scope`.
-struct ScopeInstantiator<'me, 'tcx> {
- next_region: &'me mut dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
- // The debruijn index of the scope we are instantiating.
- target_index: ty::DebruijnIndex,
- bound_region_scope: &'me mut BoundRegionScope<'tcx>,
-}
-
-impl<'me, 'tcx> TypeVisitor<TyCtxt<'tcx>> for ScopeInstantiator<'me, 'tcx> {
- fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
- &mut self,
- t: &ty::Binder<'tcx, T>,
- ) -> ControlFlow<Self::BreakTy> {
- self.target_index.shift_in(1);
- t.super_visit_with(self);
- self.target_index.shift_out(1);
-
- ControlFlow::Continue(())
- }
-
- fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
- let ScopeInstantiator { bound_region_scope, next_region, .. } = self;
-
- match *r {
- ty::ReLateBound(debruijn, br) if debruijn == self.target_index => {
- bound_region_scope.map.entry(br).or_insert_with(|| next_region(br));
- }
-
- _ => {}
- }
-
- ControlFlow::Continue(())
- }
-}
-
-/// The "type generalizer" is used when handling inference variables.
-///
-/// The basic strategy for handling a constraint like `?A <: B` is to
-/// apply a "generalization strategy" to the type `B` -- this replaces
-/// all the lifetimes in the type `B` with fresh inference
-/// variables. (You can read more about the strategy in this [blog
-/// post].)
-///
-/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
-/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
-/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
-/// establishes `'0: 'x` as a constraint.
-///
-/// As a side-effect of this generalization procedure, we also replace
-/// all the bound regions that we have traversed with concrete values,
-/// so that the resulting generalized type is independent from the
-/// scopes.
-///
-/// [blog post]: https://is.gd/0hKvIr
-struct TypeGeneralizer<'me, 'tcx, D>
-where
- D: TypeRelatingDelegate<'tcx>,
-{
- infcx: &'me InferCtxt<'tcx>,
-
- delegate: &'me mut D,
-
- /// After we generalize this type, we are going to relate it to
- /// some other type. What will be the variance at this point?
- ambient_variance: ty::Variance,
-
- first_free_index: ty::DebruijnIndex,
-
- /// The vid of the type variable that is in the process of being
- /// instantiated. If we find this within the value we are folding,
- /// that means we would have created a cyclic value.
- for_vid_sub_root: ty::TyVid,
-
- /// The universe of the type variable that is in the process of being
- /// instantiated. If we find anything that this universe cannot name,
- /// we reject the relation.
- universe: ty::UniverseIndex,
-}
-
-impl<'tcx, D> TypeRelation<'tcx> for TypeGeneralizer<'_, 'tcx, D>
-where
- D: TypeRelatingDelegate<'tcx>,
-{
- fn tcx(&self) -> TyCtxt<'tcx> {
- self.infcx.tcx
- }
-
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.delegate.param_env()
- }
-
- fn tag(&self) -> &'static str {
- "nll::generalizer"
- }
-
- fn a_is_expected(&self) -> bool {
- true
- }
-
- fn relate_with_variance<T: Relate<'tcx>>(
- &mut self,
- variance: ty::Variance,
- _info: ty::VarianceDiagInfo<'tcx>,
- a: T,
- b: T,
- ) -> RelateResult<'tcx, T> {
- debug!(
- "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})",
- variance, a, b
- );
-
- let old_ambient_variance = self.ambient_variance;
- self.ambient_variance = self.ambient_variance.xform(variance);
-
- debug!(
- "TypeGeneralizer::relate_with_variance: ambient_variance = {:?}",
- self.ambient_variance
- );
-
- let r = self.relate(a, b)?;
-
- self.ambient_variance = old_ambient_variance;
-
- debug!("TypeGeneralizer::relate_with_variance: r={:?}", r);
-
- Ok(r)
- }
-
- fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
- use crate::infer::type_variable::TypeVariableValue;
-
- debug!("TypeGeneralizer::tys(a={:?})", a);
-
- match *a.kind() {
- ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
- if D::forbid_inference_vars() =>
- {
- bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
- }
-
- ty::Infer(ty::TyVar(vid)) => {
- let mut inner = self.infcx.inner.borrow_mut();
- let variables = &mut inner.type_variables();
- let vid = variables.root_var(vid);
- let sub_vid = variables.sub_root_var(vid);
- if sub_vid == self.for_vid_sub_root {
- // If sub-roots are equal, then `for_vid` and
- // `vid` are related via subtyping.
- debug!("TypeGeneralizer::tys: occurs check failed");
- Err(TypeError::Mismatch)
- } else {
- match variables.probe(vid) {
- TypeVariableValue::Known { value: u } => {
- drop(variables);
- self.relate(u, u)
- }
- TypeVariableValue::Unknown { universe: _universe } => {
- if self.ambient_variance == ty::Bivariant {
- // FIXME: we may need a WF predicate (related to #54105).
- }
-
- let origin = *variables.var_origin(vid);
-
- // Replacing with a new variable in the universe `self.universe`,
- // it will be unified later with the original type variable in
- // the universe `_universe`.
- let new_var_id = variables.new_var(self.universe, origin);
-
- let u = self.tcx().mk_ty_var(new_var_id);
- debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
- Ok(u)
- }
- }
- }
- }
-
- ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
- // No matter what mode we are in,
- // integer/floating-point types must be equal to be
- // relatable.
- Ok(a)
- }
-
- ty::Placeholder(placeholder) => {
- if self.universe.cannot_name(placeholder.universe) {
- debug!(
- "TypeGeneralizer::tys: root universe {:?} cannot name\
- placeholder in universe {:?}",
- self.universe, placeholder.universe
- );
- Err(TypeError::Mismatch)
- } else {
- Ok(a)
- }
- }
-
- _ => relate::super_relate_tys(self, a, a),
- }
- }
-
- fn regions(
- &mut self,
- a: ty::Region<'tcx>,
- _: ty::Region<'tcx>,
- ) -> RelateResult<'tcx, ty::Region<'tcx>> {
- debug!("TypeGeneralizer::regions(a={:?})", a);
-
- if let ty::ReLateBound(debruijn, _) = *a && debruijn < self.first_free_index {
- return Ok(a);
- }
-
- // For now, we just always create a fresh region variable to
- // replace all the regions in the source type. In the main
- // type checker, we special case the case where the ambient
- // variance is `Invariant` and try to avoid creating a fresh
- // region variable, but since this comes up so much less in
- // NLL (only when users use `_` etc) it is much less
- // important.
- //
- // As an aside, since these new variables are created in
- // `self.universe` universe, this also serves to enforce the
- // universe scoping rules.
- //
- // FIXME(#54105) -- if the ambient variance is bivariant,
- // though, we may however need to check well-formedness or
- // risk a problem like #41677 again.
-
- let replacement_region_vid = self.delegate.generalize_existential(self.universe);
-
- Ok(replacement_region_vid)
- }
-
- fn consts(
- &mut self,
- a: ty::Const<'tcx>,
- _: ty::Const<'tcx>,
- ) -> RelateResult<'tcx, ty::Const<'tcx>> {
- match a.kind() {
- ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
- bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
- }
- ty::ConstKind::Infer(InferConst::Var(vid)) => {
- let mut inner = self.infcx.inner.borrow_mut();
- let variable_table = &mut inner.const_unification_table();
- let var_value = variable_table.probe_value(vid);
- match var_value.val.known() {
- Some(u) => self.relate(u, u),
- None => {
- let new_var_id = variable_table.new_key(ConstVarValue {
- origin: var_value.origin,
- val: ConstVariableValue::Unknown { universe: self.universe },
- });
- Ok(self.tcx().mk_const(new_var_id, a.ty()))
- }
- }
- }
- ty::ConstKind::Unevaluated(..) if self.tcx().lazy_normalization() => Ok(a),
- _ => relate::super_relate_consts(self, a, a),
- }
- }
-
- fn binders<T>(
- &mut self,
- a: ty::Binder<'tcx, T>,
- _: ty::Binder<'tcx, T>,
- ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
- where
- T: Relate<'tcx>,
- {
- debug!("TypeGeneralizer::binders(a={:?})", a);
-
- self.first_free_index.shift_in(1);
- let result = self.relate(a.skip_binder(), a.skip_binder())?;
- self.first_free_index.shift_out(1);
- Ok(a.rebind(result))
- }
-}
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 3a0a0494a..9d5ec228d 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -1,14 +1,14 @@
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use super::{DefineOpaqueTypes, InferResult};
use crate::errors::OpaqueHiddenTypeDiag;
-use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
-use crate::traits;
+use crate::infer::{InferCtxt, InferOk};
+use crate::traits::{self, PredicateObligation};
use hir::def_id::{DefId, LocalDefId};
use hir::OpaqueTyOrigin;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::Lrc;
use rustc_hir as hir;
-use rustc_middle::traits::ObligationCause;
+use rustc_middle::traits::{DefiningAnchor, ObligationCause};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::GenericArgKind;
@@ -48,12 +48,18 @@ impl<'tcx> InferCtxt<'tcx> {
span: Span,
param_env: ty::ParamEnv<'tcx>,
) -> InferOk<'tcx, T> {
+ // We handle opaque types differently in the new solver.
+ if self.tcx.trait_solver_next() {
+ return InferOk { value, obligations: vec![] };
+ }
+
if !value.has_opaque_types() {
return InferOk { value, obligations: vec![] };
}
+
let mut obligations = vec![];
let replace_opaque_type = |def_id: DefId| {
- def_id.as_local().map_or(false, |def_id| self.opaque_type_origin(def_id).is_some())
+ def_id.as_local().is_some_and(|def_id| self.opaque_type_origin(def_id).is_some())
};
let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx,
@@ -149,7 +155,7 @@ impl<'tcx> InferCtxt<'tcx> {
// no one encounters it in practice.
// It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
// where it is of no concern, so we only check for TAITs.
- if let Some(OpaqueTyOrigin::TyAlias) =
+ if let Some(OpaqueTyOrigin::TyAlias { .. }) =
b_def_id.as_local().and_then(|b_def_id| self.opaque_type_origin(b_def_id))
{
self.tcx.sess.emit_err(OpaqueHiddenTypeDiag {
@@ -381,8 +387,12 @@ impl<'tcx> InferCtxt<'tcx> {
// Anonymous `impl Trait`
hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
// Named `type Foo = impl Bar;`
- hir::OpaqueTyOrigin::TyAlias => {
- may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
+ hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
+ if in_assoc_ty {
+ self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id)
+ } else {
+ may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
+ }
}
};
in_definition_scope.then_some(origin)
@@ -392,12 +402,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// defining scope.
#[instrument(skip(self), level = "trace", ret)]
fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin {
- match self.tcx.hir().expect_item(def_id).kind {
- hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
- ref itemkind => {
- bug!("weird opaque type: {:?}, {:#?}", def_id, itemkind)
- }
- }
+ self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin
}
}
@@ -522,30 +527,69 @@ impl<'tcx> InferCtxt<'tcx> {
origin: hir::OpaqueTyOrigin,
a_is_expected: bool,
) -> InferResult<'tcx, ()> {
- let tcx = self.tcx;
- let OpaqueTypeKey { def_id, substs } = opaque_type_key;
-
// Ideally, we'd get the span where *this specific `ty` came
// from*, but right now we just use the span from the overall
// value being folded. In simple cases like `-> impl Foo`,
// these are the same span, but not in cases like `-> (impl
// Foo, impl Bar)`.
let span = cause.span;
-
- let mut obligations = vec![];
let prev = self.inner.borrow_mut().opaque_types().register(
- OpaqueTypeKey { def_id, substs },
+ opaque_type_key,
OpaqueHiddenType { ty: hidden_ty, span },
origin,
);
- if let Some(prev) = prev {
- obligations = self
- .at(&cause, param_env)
+ let mut obligations = if let Some(prev) = prev {
+ self.at(&cause, param_env)
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
- .obligations;
- }
+ .obligations
+ } else {
+ Vec::new()
+ };
+
+ self.add_item_bounds_for_hidden_type(
+ opaque_type_key,
+ cause,
+ param_env,
+ hidden_ty,
+ &mut obligations,
+ );
+
+ Ok(InferOk { value: (), obligations })
+ }
- let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());
+ /// Registers an opaque's hidden type -- only should be used when the opaque
+ /// can be defined. For something more fallible -- checks the anchors, tries
+ /// to unify opaques in both dirs, etc. -- use `InferCtxt::handle_opaque_type`.
+ pub fn register_hidden_type_in_new_solver(
+ &self,
+ opaque_type_key: OpaqueTypeKey<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ hidden_ty: Ty<'tcx>,
+ ) -> InferResult<'tcx, ()> {
+ assert!(self.tcx.trait_solver_next());
+ let origin = self
+ .opaque_type_origin(opaque_type_key.def_id)
+ .expect("should be called for defining usages only");
+ self.register_hidden_type(
+ opaque_type_key,
+ ObligationCause::dummy(),
+ param_env,
+ hidden_ty,
+ origin,
+ true,
+ )
+ }
+
+ pub fn add_item_bounds_for_hidden_type(
+ &self,
+ OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>,
+ cause: ObligationCause<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ hidden_ty: Ty<'tcx>,
+ obligations: &mut Vec<PredicateObligation<'tcx>>,
+ ) {
+ let tcx = self.tcx;
+ let item_bounds = tcx.explicit_item_bounds(def_id);
for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
let predicate = predicate.fold_with(&mut BottomUpFolder {
@@ -554,16 +598,18 @@ impl<'tcx> InferCtxt<'tcx> {
// We can't normalize associated types from `rustc_infer`,
// but we can eagerly register inference variables for them.
// FIXME(RPITIT): Don't replace RPITITs with inference vars.
+ // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
ty::Alias(ty::Projection, projection_ty)
if !projection_ty.has_escaping_bound_vars()
- && !tcx.is_impl_trait_in_trait(projection_ty.def_id) =>
+ && !tcx.is_impl_trait_in_trait(projection_ty.def_id)
+ && !tcx.trait_solver_next() =>
{
self.infer_projection(
param_env,
projection_ty,
cause.clone(),
0,
- &mut obligations,
+ obligations,
)
}
// Replace all other mentions of the same opaque type with the hidden type,
@@ -574,6 +620,7 @@ impl<'tcx> InferCtxt<'tcx> {
hidden_ty
}
// FIXME(RPITIT): This can go away when we move to associated types
+ // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
ty::Alias(
ty::Projection,
ty::AliasTy { def_id: def_id2, substs: substs2, .. },
@@ -588,10 +635,10 @@ impl<'tcx> InferCtxt<'tcx> {
predicate.kind().skip_binder()
{
if projection.term.references_error() {
- // No point on adding these obligations since there's a type error involved.
- return Ok(InferOk { value: (), obligations: vec![] });
+ // No point on adding any obligations since there's a type error involved.
+ obligations.clear();
+ return;
}
- trace!("{:#?}", projection.term);
}
// Require that the predicate holds for the concrete type.
debug!(?predicate);
@@ -602,7 +649,6 @@ impl<'tcx> InferCtxt<'tcx> {
predicate,
));
}
- Ok(InferOk { value: (), obligations })
}
}
diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs
index ae4b85c87..a0f6d7eca 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/table.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs
@@ -42,7 +42,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.delay_span_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 ff23087fe..cb63d2f18 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -143,7 +143,7 @@ fn compute_components<'tcx>(
// through and constrain Pi.
let mut subcomponents = smallvec![];
let mut subvisited = SsoHashSet::new();
- compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
+ compute_alias_components_recursive(tcx, ty, &mut subcomponents, &mut subvisited);
out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
}
}
@@ -193,7 +193,43 @@ fn compute_components<'tcx>(
///
/// This should not be used to get the components of `parent` itself.
/// Use [push_outlives_components] instead.
-pub(super) fn compute_components_recursive<'tcx>(
+pub(super) fn compute_alias_components_recursive<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ alias_ty: Ty<'tcx>,
+ out: &mut SmallVec<[Component<'tcx>; 4]>,
+ visited: &mut SsoHashSet<GenericArg<'tcx>>,
+) {
+ let ty::Alias(kind, alias_ty) = alias_ty.kind() else { bug!() };
+ let opt_variances = if *kind == ty::Opaque { tcx.variances_of(alias_ty.def_id) } else { &[] };
+ for (index, child) in alias_ty.substs.iter().enumerate() {
+ if opt_variances.get(index) == Some(&ty::Bivariant) {
+ continue;
+ }
+ if !visited.insert(child) {
+ continue;
+ }
+ match child.unpack() {
+ GenericArgKind::Type(ty) => {
+ compute_components(tcx, ty, out, visited);
+ }
+ GenericArgKind::Lifetime(lt) => {
+ // Ignore late-bound regions.
+ if !lt.is_late_bound() {
+ out.push(Component::Region(lt));
+ }
+ }
+ GenericArgKind::Const(_) => {
+ compute_components_recursive(tcx, child, out, visited);
+ }
+ }
+ }
+}
+
+/// Collect [Component]s for *all* the substs of `parent`.
+///
+/// This should not be used to get the components of `parent` itself.
+/// Use [push_outlives_components] instead.
+fn compute_components_recursive<'tcx>(
tcx: TyCtxt<'tcx>,
parent: GenericArg<'tcx>,
out: &mut SmallVec<[Component<'tcx>; 4]>,
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 9a9a1696b..8a44d5031 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -61,7 +61,7 @@ impl<'tcx> InferCtxt<'tcx> {
};
let lexical_region_resolutions = LexicalRegionResolutions {
- values: rustc_index::vec::IndexVec::from_elem_n(
+ values: rustc_index::IndexVec::from_elem_n(
crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
var_infos.len(),
),
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index ccf11c61b..9c20c814b 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -256,7 +256,7 @@ where
// this point it never will be
self.tcx.sess.delay_span_bug(
origin.span(),
- &format!("unresolved inference variable in outlives: {:?}", v),
+ format!("unresolved inference variable in outlives: {:?}", v),
);
}
}
@@ -344,12 +344,14 @@ where
// the problem is to add `T: 'r`, which isn't true. So, if there are no
// inference variables, we use a verify constraint instead of adding
// edges, which winds up enforcing the same condition.
+ let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque;
if approx_env_bounds.is_empty()
&& trait_bounds.is_empty()
- && (alias_ty.needs_infer() || alias_ty.kind(self.tcx) == ty::Opaque)
+ && (alias_ty.has_infer() || is_opaque)
{
debug!("no declared bounds");
- self.substs_must_outlive(alias_ty.substs, origin, region);
+ let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));
+ self.substs_must_outlive(alias_ty.substs, origin, region, opt_variances);
return;
}
@@ -395,22 +397,31 @@ where
self.delegate.push_verify(origin, GenericKind::Alias(alias_ty), region, verify_bound);
}
+ #[instrument(level = "debug", skip(self))]
fn substs_must_outlive(
&mut self,
substs: SubstsRef<'tcx>,
origin: infer::SubregionOrigin<'tcx>,
region: ty::Region<'tcx>,
+ opt_variances: Option<&[ty::Variance]>,
) {
let constraint = origin.to_constraint_category();
- for k in substs {
+ for (index, k) in substs.iter().enumerate() {
match k.unpack() {
GenericArgKind::Lifetime(lt) => {
- self.delegate.push_sub_region_constraint(
- origin.clone(),
- region,
- lt,
- constraint,
- );
+ let variance = if let Some(variances) = opt_variances {
+ variances[index]
+ } else {
+ ty::Invariant
+ };
+ if variance == ty::Invariant {
+ self.delegate.push_sub_region_constraint(
+ origin.clone(),
+ region,
+ lt,
+ constraint,
+ );
+ }
}
GenericArgKind::Type(ty) => {
self.type_must_outlive(origin.clone(), ty, region, constraint);
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 01f900f05..cd2462d3c 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -13,9 +13,11 @@ use crate::infer::region_constraints::VerifyIfEq;
/// Given a "verify-if-eq" type test like:
///
-/// exists<'a...> {
-/// verify_if_eq(some_type, bound_region)
-/// }
+/// ```rust,ignore (pseudo-Rust)
+/// exists<'a...> {
+/// verify_if_eq(some_type, bound_region)
+/// }
+/// ```
///
/// and the type `test_ty` that the type test is being tested against,
/// returns:
@@ -185,7 +187,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
} else if pattern == value {
Ok(pattern)
} else {
- relate::super_relate_tys(self, pattern, value)
+ relate::structurally_relate_tys(self, pattern, value)
}
}
@@ -199,7 +201,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
if pattern == value {
Ok(pattern)
} else {
- relate::super_relate_consts(self, pattern, value)
+ relate::structurally_relate_consts(self, pattern, value)
}
}
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index bae246418..c2bf0f3db 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -1,4 +1,4 @@
-use crate::infer::outlives::components::{compute_components_recursive, Component};
+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;
@@ -130,7 +130,12 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// see the extensive comment in projection_must_outlive
let recursive_bound = {
let mut components = smallvec![];
- compute_components_recursive(self.tcx, alias_ty_as_ty.into(), &mut components, visited);
+ compute_alias_components_recursive(
+ self.tcx,
+ alias_ty_as_ty.into(),
+ &mut components,
+ visited,
+ );
self.bound_from_components(&components, visited)
};
@@ -174,7 +179,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// this point it never will be
self.tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP,
- &format!("unresolved inference variable in outlives: {:?}", v),
+ format!("unresolved inference variable in outlives: {:?}", v),
);
// add a bound that never holds
VerifyBound::AnyBound(vec![])
@@ -272,7 +277,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
///
/// It will not, however, work for higher-ranked bounds like:
///
- /// ```compile_fail,E0311
+ /// ```ignore(this does compile today, previously was marked as `compile_fail,E0311`)
/// trait Foo<'a, 'b>
/// where for<'x> <Self as Foo<'x, 'b>>::Bar: 'x
/// {
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 b8ba98fc0..89cfc9ea3 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::{
graph::{scc::Sccs, vec_graph::VecGraph},
undo_log::UndoLogs,
};
-use rustc_index::vec::Idx;
+use rustc_index::Idx;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::RelateResult;
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 7b272dfd2..c7a307b89 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -12,7 +12,7 @@ use rustc_data_structures::intern::Interned;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::undo_log::UndoLogs;
use rustc_data_structures::unify as ut;
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
use rustc_middle::ty::ReStatic;
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -217,7 +217,7 @@ pub enum VerifyBound<'tcx> {
/// and supplies a bound if it ended up being relevant. It's used in situations
/// like this:
///
-/// ```rust
+/// ```rust,ignore (pseudo-Rust)
/// fn foo<'a, 'b, T: SomeTrait<'a>>
/// where
/// <T as SomeTrait<'a>>::Item: 'b
@@ -232,7 +232,7 @@ pub enum VerifyBound<'tcx> {
/// In the [`VerifyBound`], this struct is enclosed in `Binder` to account
/// for cases like
///
-/// ```rust
+/// ```rust,ignore (pseudo-Rust)
/// where for<'a> <T as SomeTrait<'a>::Item: 'a
/// ```
///
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 4f49f4165..3c41e8b37 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -213,7 +213,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
}
fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
- if !t.needs_infer() {
+ if !t.has_infer() {
Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
let t = self.infcx.shallow_resolve(t);
@@ -243,7 +243,7 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
}
fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
- if !c.needs_infer() {
+ if !c.has_infer() {
Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects...
} else {
let c = self.infcx.shallow_resolve(c);
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 0dd73a6e9..ceafafb55 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -1,4 +1,4 @@
-use super::combine::{CombineFields, RelationDir};
+use super::combine::CombineFields;
use super::{DefineOpaqueTypes, ObligationEmittingRelation, SubregionOrigin};
use crate::traits::{Obligation, PredicateObligations};
@@ -108,11 +108,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
Ok(a)
}
(&ty::Infer(TyVar(a_id)), _) => {
- self.fields.instantiate(b, RelationDir::SupertypeOf, a_id, !self.a_is_expected)?;
+ self.fields.instantiate(b, ty::Contravariant, a_id, !self.a_is_expected)?;
Ok(a)
}
(_, &ty::Infer(TyVar(b_id))) => {
- self.fields.instantiate(a, RelationDir::SubtypeOf, b_id, self.a_is_expected)?;
+ self.fields.instantiate(a, ty::Covariant, b_id, self.a_is_expected)?;
Ok(a)
}
@@ -131,7 +131,8 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
(&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
- && def_id.is_local() =>
+ && def_id.is_local()
+ && !self.tcx().trait_solver_next() =>
{
self.fields.obligations.extend(
infcx
@@ -210,7 +211,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
where
T: Relate<'tcx>,
{
- // A binder is always a subtype of itself if it's structually equal to itself
+ // A binder is always a subtype of itself if it's structurally equal to itself
if a == b {
return Ok(a);
}