summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_infer/src/infer/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_infer/src/infer/mod.rs')
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs199
1 files changed, 94 insertions, 105 deletions
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index f0e42c1fc..bd1f96635 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -4,6 +4,7 @@ pub use self::LateBoundRegionConversionTime::*;
pub use self::RegionVariableOrigin::*;
pub use self::SubregionOrigin::*;
pub use self::ValuePairs::*;
+pub use combine::ObligationEmittingRelation;
use self::opaque_types::OpaqueTypeStorage;
pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
@@ -28,9 +29,9 @@ use rustc_middle::ty::fold::BoundVarReplacerDelegate;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
pub use rustc_middle::ty::IntVarValue;
-use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt};
use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
@@ -155,7 +156,7 @@ pub struct InferCtxtInner<'tcx> {
undo_log: InferCtxtUndoLogs<'tcx>,
/// Caches for opaque type inference.
- pub opaque_type_storage: OpaqueTypeStorage<'tcx>,
+ opaque_type_storage: OpaqueTypeStorage<'tcx>,
}
impl<'tcx> InferCtxtInner<'tcx> {
@@ -194,41 +195,17 @@ impl<'tcx> InferCtxtInner<'tcx> {
}
#[inline]
- fn int_unification_table(
- &mut self,
- ) -> ut::UnificationTable<
- ut::InPlace<
- ty::IntVid,
- &mut ut::UnificationStorage<ty::IntVid>,
- &mut InferCtxtUndoLogs<'tcx>,
- >,
- > {
+ fn int_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::IntVid> {
self.int_unification_storage.with_log(&mut self.undo_log)
}
#[inline]
- fn float_unification_table(
- &mut self,
- ) -> ut::UnificationTable<
- ut::InPlace<
- ty::FloatVid,
- &mut ut::UnificationStorage<ty::FloatVid>,
- &mut InferCtxtUndoLogs<'tcx>,
- >,
- > {
+ fn float_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::FloatVid> {
self.float_unification_storage.with_log(&mut self.undo_log)
}
#[inline]
- fn const_unification_table(
- &mut self,
- ) -> ut::UnificationTable<
- ut::InPlace<
- ty::ConstVid<'tcx>,
- &mut ut::UnificationStorage<ty::ConstVid<'tcx>>,
- &mut InferCtxtUndoLogs<'tcx>,
- >,
- > {
+ fn const_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::ConstVid<'tcx>> {
self.const_unification_storage.with_log(&mut self.undo_log)
}
@@ -263,7 +240,7 @@ pub struct InferCtxt<'tcx> {
/// short lived InferCtxt within queries. The opaque type obligations are forwarded
/// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
///
- /// It is default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
+ /// Its default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
/// might come up during inference or typeck.
pub defining_use_anchor: DefiningAnchor,
@@ -616,7 +593,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
canonical: &Canonical<'tcx, T>,
) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>)
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let infcx = self.build();
let (value, subst) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
@@ -696,7 +673,7 @@ impl<'tcx> InferCtxt<'tcx> {
self.in_snapshot.get()
}
- pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T {
+ pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
t.fold_with(&mut self.freshener())
}
@@ -879,30 +856,20 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup);
}
- pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx>
+ pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
where
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
- self.probe(|_| {
- self.at(origin, param_env).sub(a, b).map(|InferOk { obligations: _, .. }| {
- // Ignore obligations, since we are unrolling
- // everything anyway.
- })
- })
+ self.probe(|_| self.at(origin, param_env).sub(a, b).is_ok())
}
- pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx>
+ pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
where
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
- self.probe(|_| {
- self.at(origin, param_env).eq(a, b).map(|InferOk { obligations: _, .. }| {
- // Ignore obligations, since we are unrolling
- // everything anyway.
- })
- })
+ self.probe(|_| self.at(origin, param_env).eq(a, b).is_ok())
}
#[instrument(skip(self), level = "debug")]
@@ -995,7 +962,7 @@ impl<'tcx> InferCtxt<'tcx> {
Ok(self.commit_if_ok(|_snapshot| {
let ty::SubtypePredicate { a_is_expected, a, b } =
- self.replace_bound_vars_with_placeholders(predicate);
+ self.instantiate_binder_with_placeholders(predicate);
let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
@@ -1008,7 +975,7 @@ impl<'tcx> InferCtxt<'tcx> {
cause: &traits::ObligationCause<'tcx>,
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
) {
- let ty::OutlivesPredicate(r_a, r_b) = self.replace_bound_vars_with_placeholders(predicate);
+ let ty::OutlivesPredicate(r_a, r_b) = self.instantiate_binder_with_placeholders(predicate);
let origin =
SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span));
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
@@ -1102,7 +1069,7 @@ impl<'tcx> InferCtxt<'tcx> {
) -> ty::Region<'tcx> {
let region_var =
self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, origin);
- self.tcx.mk_region(ty::ReVar(region_var))
+ self.tcx.mk_re_var(region_var)
}
/// Return the universe that the region `r` was created in. For
@@ -1120,11 +1087,13 @@ impl<'tcx> InferCtxt<'tcx> {
}
/// Just a convenient wrapper of `next_region_var` for using during NLL.
+ #[instrument(skip(self), level = "debug")]
pub fn next_nll_region_var(&self, origin: NllRegionVariableOrigin) -> ty::Region<'tcx> {
self.next_region_var(RegionVariableOrigin::Nll(origin))
}
/// Just a convenient wrapper of `next_region_var` for using during NLL.
+ #[instrument(skip(self), level = "debug")]
pub fn next_nll_region_var_in_universe(
&self,
origin: NllRegionVariableOrigin,
@@ -1175,7 +1144,15 @@ impl<'tcx> InferCtxt<'tcx> {
origin,
val: ConstVariableValue::Unknown { universe: self.universe() },
});
- self.tcx.mk_const(const_var_id, self.tcx.type_of(param.def_id)).into()
+ self.tcx
+ .mk_const(
+ const_var_id,
+ self.tcx
+ .type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ )
+ .into()
}
}
}
@@ -1370,7 +1347,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// will be resolving them as well, e.g. in a loop).
pub fn shallow_resolve<T>(&self, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
value.fold_with(&mut ShallowResolver { infcx: self })
}
@@ -1387,10 +1364,10 @@ impl<'tcx> InferCtxt<'tcx> {
/// at will.
pub fn resolve_vars_if_possible<T>(&self, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
- if !value.needs_infer() {
- return value; // Avoid duplicated subst-folding.
+ if !value.has_non_region_infer() {
+ return value;
}
let mut r = resolve::OpportunisticVarResolver::new(self);
value.fold_with(&mut r)
@@ -1398,7 +1375,7 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn resolve_numeric_literals_with_default<T>(&self, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
if !value.needs_infer() {
return value; // Avoid duplicated subst-folding.
@@ -1413,7 +1390,7 @@ impl<'tcx> InferCtxt<'tcx> {
value: &T,
) -> Option<(ty::Term<'tcx>, Option<Span>)>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
value.visit_with(&mut resolve::UnresolvedTypeOrConstFinder::new(self)).break_value()
}
@@ -1428,17 +1405,14 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
- pub fn fully_resolve<T: TypeFoldable<'tcx>>(&self, value: T) -> FixupResult<'tcx, T> {
- /*!
- * Attempts to resolve all type/region/const variables in
- * `value`. Region inference must have been run already (e.g.,
- * by calling `resolve_regions_and_report_errors`). If some
- * variable was never unified, an `Err` results.
- *
- * This method is idempotent, but it not typically not invoked
- * except during the writeback phase.
- */
-
+ /// Attempts to resolve all type/region/const variables in
+ /// `value`. Region inference must have been run already (e.g.,
+ /// by calling `resolve_regions_and_report_errors`). If some
+ /// variable was never unified, an `Err` results.
+ ///
+ /// This method is idempotent, but it not typically not invoked
+ /// except during the writeback phase.
+ 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()),
@@ -1447,14 +1421,21 @@ impl<'tcx> InferCtxt<'tcx> {
value
}
- pub fn replace_bound_vars_with_fresh_vars<T>(
+ // Instantiates the bound variables in a given binder with fresh inference
+ // variables in the current universe.
+ //
+ // Use this method if you'd like to find some substitution of the binder's
+ // variables (e.g. during a method call). If there isn't a [`LateBoundRegionConversionTime`]
+ // that corresponds to your use case, consider whether or not you should
+ // use [`InferCtxt::instantiate_binder_with_placeholders`] instead.
+ pub fn instantiate_binder_with_fresh_vars<T>(
&self,
span: Span,
lbrct: LateBoundRegionConversionTime,
value: ty::Binder<'tcx, T>,
) -> T
where
- T: TypeFoldable<'tcx> + Copy,
+ T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
if let Some(inner) = value.no_bound_vars() {
return inner;
@@ -1746,7 +1727,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// in this case. The typechecker should only ever report type errors involving mismatched
// types using one of these methods, and should not call span_err directly for such
// errors.
-
pub fn type_error_struct_with_diag<M>(
&self,
sp: Span,
@@ -1844,8 +1824,8 @@ struct InferenceLiteralEraser<'tcx> {
tcx: TyCtxt<'tcx>,
}
-impl<'tcx> TypeFolder<'tcx> for InferenceLiteralEraser<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceLiteralEraser<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
@@ -1862,17 +1842,41 @@ struct ShallowResolver<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
}
-impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ShallowResolver<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
/// If `ty` is a type variable of some kind, resolve it one level
/// (but do not resolve types found in the result). If `typ` is
/// not a type variable, just return it unmodified.
+ #[inline]
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- match *ty.kind() {
- ty::Infer(ty::TyVar(v)) => {
+ if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
+ }
+
+ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
+ if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
+ self.infcx
+ .inner
+ .borrow_mut()
+ .const_unification_table()
+ .probe_value(vid)
+ .val
+ .known()
+ .unwrap_or(ct)
+ } else {
+ ct
+ }
+ }
+}
+
+impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
+ // This is separate from `fold_ty` to keep that method small and inlinable.
+ #[inline(never)]
+ fn fold_infer_ty(&mut self, v: InferTy) -> Option<Ty<'tcx>> {
+ match v {
+ ty::TyVar(v) => {
// Not entirely obvious: if `typ` is a type variable,
// it can be resolved to an int/float variable, which
// can then be recursively resolved, hence the
@@ -1886,41 +1890,26 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
// Note: if these two lines are combined into one we get
// dynamic borrow errors on `self.inner`.
let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
- known.map_or(ty, |t| self.fold_ty(t))
+ known.map(|t| self.fold_ty(t))
}
- ty::Infer(ty::IntVar(v)) => self
+ ty::IntVar(v) => self
.infcx
.inner
.borrow_mut()
.int_unification_table()
.probe_value(v)
- .map_or(ty, |v| v.to_type(self.infcx.tcx)),
+ .map(|v| v.to_type(self.infcx.tcx)),
- ty::Infer(ty::FloatVar(v)) => self
+ ty::FloatVar(v) => self
.infcx
.inner
.borrow_mut()
.float_unification_table()
.probe_value(v)
- .map_or(ty, |v| v.to_type(self.infcx.tcx)),
-
- _ => ty,
- }
- }
+ .map(|v| v.to_type(self.infcx.tcx)),
- fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
- if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
- self.infcx
- .inner
- .borrow_mut()
- .const_unification_table()
- .probe_value(vid)
- .val
- .known()
- .unwrap_or(ct)
- } else {
- ct
+ ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
}
}
}
@@ -2044,24 +2033,24 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
) -> SubstsRef<'tcx> {
struct ReplaceParamAndInferWithPlaceholder<'tcx> {
tcx: TyCtxt<'tcx>,
- idx: usize,
+ idx: u32,
}
- impl<'tcx> TypeFolder<'tcx> for ReplaceParamAndInferWithPlaceholder<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceParamAndInferWithPlaceholder<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Infer(_) = t.kind() {
- self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+ self.tcx.mk_placeholder(ty::PlaceholderType {
universe: ty::UniverseIndex::ROOT,
- name: ty::BoundVar::from_usize({
+ name: ty::BoundTyKind::Anon({
let idx = self.idx;
self.idx += 1;
idx
}),
- }))
+ })
} else {
t.super_fold_with(self)
}
@@ -2077,7 +2066,7 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
self.tcx.mk_const(
ty::PlaceholderConst {
universe: ty::UniverseIndex::ROOT,
- name: ty::BoundVar::from_usize({
+ name: ty::BoundVar::from_u32({
let idx = self.idx;
self.idx += 1;
idx