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.rs190
1 files changed, 93 insertions, 97 deletions
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index cd99fc312..fca32b73d 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -6,6 +6,7 @@ pub use self::RegionVariableOrigin::*;
pub use self::SubregionOrigin::*;
pub use self::ValuePairs::*;
pub use combine::ObligationEmittingRelation;
+use rustc_data_structures::undo_log::UndoLogs;
use self::opaque_types::OpaqueTypeStorage;
pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
@@ -251,14 +252,13 @@ pub struct InferCtxt<'tcx> {
/// solving is left to borrowck instead.
pub considering_regions: bool,
- pub inner: RefCell<InferCtxtInner<'tcx>>,
-
/// If set, this flag causes us to skip the 'leak check' during
/// higher-ranked subtyping operations. This flag is a temporary one used
/// to manage the removal of the leak-check: for the time being, we still run the
- /// leak-check, but we issue warnings. This flag can only be set to true
- /// when entering a snapshot.
- skip_leak_check: Cell<bool>,
+ /// leak-check, but we issue warnings.
+ skip_leak_check: bool,
+
+ pub inner: RefCell<InferCtxtInner<'tcx>>,
/// Once region inference is done, the values for each variable.
lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
@@ -298,9 +298,6 @@ pub struct InferCtxt<'tcx> {
// FIXME(matthewjasper) Merge into `tainted_by_errors`
err_count_on_creation: usize,
- /// This flag is true while there is an active snapshot.
- in_snapshot: Cell<bool>,
-
/// What is the innermost universe we have created? Starts out as
/// `UniverseIndex::root()` but grows from there as we enter
/// universal quantifiers.
@@ -331,6 +328,8 @@ 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,
+
+ next_trait_solver: bool,
}
/// See the `error_reporting` module for more details.
@@ -543,8 +542,12 @@ pub struct InferCtxtBuilder<'tcx> {
tcx: TyCtxt<'tcx>,
defining_use_anchor: DefiningAnchor,
considering_regions: bool,
+ skip_leak_check: bool,
/// Whether we are in coherence mode.
intercrate: bool,
+ /// Whether we should use the new trait solver in the local inference context,
+ /// which affects things like which solver is used in `predicate_may_hold`.
+ next_trait_solver: bool,
}
pub trait TyCtxtInferExt<'tcx> {
@@ -557,7 +560,9 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
tcx: self,
defining_use_anchor: DefiningAnchor::Error,
considering_regions: true,
+ skip_leak_check: false,
intercrate: false,
+ next_trait_solver: self.next_trait_solver_globally(),
}
}
}
@@ -574,6 +579,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
self
}
+ pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self {
+ self.next_trait_solver = next_trait_solver;
+ self
+ }
+
pub fn intercrate(mut self, intercrate: bool) -> Self {
self.intercrate = intercrate;
self
@@ -584,6 +594,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
self
}
+ pub fn skip_leak_check(mut self, skip_leak_check: bool) -> Self {
+ self.skip_leak_check = skip_leak_check;
+ self
+ }
+
/// Given a canonical value `C` as a starting point, create an
/// inference context that contains each of the bound values
/// within instantiated as a fresh variable. The `f` closure is
@@ -605,11 +620,19 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
}
pub fn build(&mut self) -> InferCtxt<'tcx> {
- let InferCtxtBuilder { tcx, defining_use_anchor, considering_regions, intercrate } = *self;
+ let InferCtxtBuilder {
+ tcx,
+ defining_use_anchor,
+ considering_regions,
+ skip_leak_check,
+ intercrate,
+ next_trait_solver,
+ } = *self;
InferCtxt {
tcx,
defining_use_anchor,
considering_regions,
+ skip_leak_check,
inner: RefCell::new(InferCtxtInner::new()),
lexical_region_resolutions: RefCell::new(None),
selection_cache: Default::default(),
@@ -618,10 +641,9 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
reported_closure_mismatch: Default::default(),
tainted_by_errors: Cell::new(None),
err_count_on_creation: tcx.sess.err_count(),
- in_snapshot: Cell::new(false),
- skip_leak_check: Cell::new(false),
universe: Cell::new(ty::UniverseIndex::ROOT),
intercrate,
+ next_trait_solver,
}
}
}
@@ -654,10 +676,13 @@ pub struct CombinedSnapshot<'tcx> {
undo_snapshot: Snapshot<'tcx>,
region_constraints_snapshot: RegionSnapshot,
universe: ty::UniverseIndex,
- was_in_snapshot: bool,
}
impl<'tcx> InferCtxt<'tcx> {
+ pub fn next_trait_solver(&self) -> bool {
+ self.next_trait_solver
+ }
+
/// Creates a `TypeErrCtxt` for emitting various inference errors.
/// During typeck, use `FnCtxt::err_ctxt` instead.
pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
@@ -673,10 +698,6 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
- pub fn is_in_snapshot(&self) -> bool {
- self.in_snapshot.get()
- }
-
pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
t.fold_with(&mut self.freshener())
}
@@ -704,19 +725,19 @@ impl<'tcx> InferCtxt<'tcx> {
.type_variables()
.unsolved_variables()
.into_iter()
- .map(|t| self.tcx.mk_ty_var(t))
+ .map(|t| Ty::new_var(self.tcx, t))
.collect();
vars.extend(
(0..inner.int_unification_table().len())
.map(|i| ty::IntVid { index: i as u32 })
.filter(|&vid| inner.int_unification_table().probe_value(vid).is_none())
- .map(|v| self.tcx.mk_int_var(v)),
+ .map(|v| Ty::new_int_var(self.tcx, v)),
);
vars.extend(
(0..inner.float_unification_table().len())
.map(|i| ty::FloatVid { index: i as u32 })
.filter(|&vid| inner.float_unification_table().probe_value(vid).is_none())
- .map(|v| self.tcx.mk_float_var(v)),
+ .map(|v| Ty::new_float_var(self.tcx, v)),
);
vars
}
@@ -737,31 +758,30 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
+ pub fn in_snapshot(&self) -> bool {
+ UndoLogs::<UndoLog<'tcx>>::in_snapshot(&self.inner.borrow_mut().undo_log)
+ }
+
+ pub fn num_open_snapshots(&self) -> usize {
+ UndoLogs::<UndoLog<'tcx>>::num_open_snapshots(&self.inner.borrow_mut().undo_log)
+ }
+
fn start_snapshot(&self) -> CombinedSnapshot<'tcx> {
debug!("start_snapshot()");
- let in_snapshot = self.in_snapshot.replace(true);
-
let mut inner = self.inner.borrow_mut();
CombinedSnapshot {
undo_snapshot: inner.undo_log.start_snapshot(),
region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
universe: self.universe(),
- was_in_snapshot: in_snapshot,
}
}
#[instrument(skip(self, snapshot), level = "debug")]
fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'tcx>) {
- let CombinedSnapshot {
- undo_snapshot,
- region_constraints_snapshot,
- universe,
- was_in_snapshot,
- } = snapshot;
-
- self.in_snapshot.set(was_in_snapshot);
+ let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot;
+
self.universe.set(universe);
let mut inner = self.inner.borrow_mut();
@@ -771,14 +791,8 @@ impl<'tcx> InferCtxt<'tcx> {
#[instrument(skip(self, snapshot), level = "debug")]
fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) {
- let CombinedSnapshot {
- undo_snapshot,
- region_constraints_snapshot: _,
- universe: _,
- was_in_snapshot,
- } = snapshot;
-
- self.in_snapshot.set(was_in_snapshot);
+ let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, universe: _ } =
+ snapshot;
self.inner.borrow_mut().commit(undo_snapshot);
}
@@ -815,32 +829,9 @@ impl<'tcx> InferCtxt<'tcx> {
r
}
- /// If `should_skip` is true, then execute `f` then unroll any bindings it creates.
- #[instrument(skip(self, f), level = "debug")]
- pub fn probe_maybe_skip_leak_check<R, F>(&self, should_skip: bool, f: F) -> R
- where
- F: FnOnce(&CombinedSnapshot<'tcx>) -> R,
- {
- let snapshot = self.start_snapshot();
- let was_skip_leak_check = self.skip_leak_check.get();
- if should_skip {
- self.skip_leak_check.set(true);
- }
- let r = f(&snapshot);
- self.rollback_to("probe", snapshot);
- self.skip_leak_check.set(was_skip_leak_check);
- r
- }
-
- /// Scan the constraints produced since `snapshot` began and returns:
- ///
- /// - `None` -- if none of them involves "region outlives" constraints.
- /// - `Some(true)` -- if there are `'a: 'b` constraints where `'a` or `'b` is a placeholder.
- /// - `Some(false)` -- if there are `'a: 'b` constraints but none involve placeholders.
- pub fn region_constraints_added_in_snapshot(
- &self,
- snapshot: &CombinedSnapshot<'tcx>,
- ) -> Option<bool> {
+ /// Scan the constraints produced since `snapshot` and check whether
+ /// we added any region constraints.
+ pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool {
self.inner
.borrow_mut()
.unwrap_region_constraints()
@@ -987,7 +978,7 @@ impl<'tcx> InferCtxt<'tcx> {
}
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
- self.tcx.mk_ty_var(self.next_ty_var_id(origin))
+ Ty::new_var(self.tcx, self.next_ty_var_id(origin))
}
pub fn next_ty_var_id_in_universe(
@@ -1004,11 +995,11 @@ impl<'tcx> InferCtxt<'tcx> {
universe: ty::UniverseIndex,
) -> Ty<'tcx> {
let vid = self.next_ty_var_id_in_universe(origin, universe);
- self.tcx.mk_ty_var(vid)
+ Ty::new_var(self.tcx, vid)
}
pub fn next_const_var(&self, ty: Ty<'tcx>, origin: ConstVariableOrigin) -> ty::Const<'tcx> {
- self.tcx.mk_const(self.next_const_var_id(origin), ty)
+ ty::Const::new_var(self.tcx, self.next_const_var_id(origin), ty)
}
pub fn next_const_var_in_universe(
@@ -1022,7 +1013,7 @@ impl<'tcx> InferCtxt<'tcx> {
.borrow_mut()
.const_unification_table()
.new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } });
- self.tcx.mk_const(vid, ty)
+ ty::Const::new_var(self.tcx, vid, ty)
}
pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid<'tcx> {
@@ -1037,7 +1028,7 @@ impl<'tcx> InferCtxt<'tcx> {
}
pub fn next_int_var(&self) -> Ty<'tcx> {
- self.tcx.mk_int_var(self.next_int_var_id())
+ Ty::new_int_var(self.tcx, self.next_int_var_id())
}
fn next_float_var_id(&self) -> FloatVid {
@@ -1045,7 +1036,7 @@ impl<'tcx> InferCtxt<'tcx> {
}
pub fn next_float_var(&self) -> Ty<'tcx> {
- self.tcx.mk_float_var(self.next_float_var_id())
+ Ty::new_float_var(self.tcx, self.next_float_var_id())
}
/// Creates a fresh region variable with the next available index.
@@ -1065,7 +1056,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_re_var(region_var)
+ ty::Region::new_var(self.tcx, region_var)
}
/// Return the universe that the region `r` was created in. For
@@ -1119,13 +1110,13 @@ impl<'tcx> InferCtxt<'tcx> {
TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeParameterDefinition(
param.name,
- Some(param.def_id),
+ param.def_id,
),
span,
},
);
- self.tcx.mk_ty_var(ty_var_id).into()
+ Ty::new_var(self.tcx, ty_var_id).into()
}
GenericParamDefKind::Const { .. } => {
let origin = ConstVariableOrigin {
@@ -1140,15 +1131,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)
- .no_bound_vars()
- .expect("const parameter types cannot be generic"),
- )
- .into()
+ ty::Const::new_var(
+ self.tcx,
+ const_var_id,
+ self.tcx
+ .type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ )
+ .into()
}
}
}
@@ -1206,15 +1197,15 @@ impl<'tcx> InferCtxt<'tcx> {
.var_origin(vid)
}
- /// Takes ownership of the list of variable regions. This implies
- /// that all the region constraints have already been taken, and
- /// 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.
+ /// Clone the list of variable regions. This is used only during NLL processing
+ /// to put the set of region variables into the NLL region context.
pub fn get_region_var_origins(&self) -> VarInfos {
let mut inner = self.inner.borrow_mut();
let (var_infos, data) = inner
.region_constraint_storage
+ // We clone instead of taking because borrowck still wants to use
+ // the inference context after calling this for diagnostics
+ // and the new trait solver.
.clone()
.expect("regions already resolved")
.with_log(&mut inner.undo_log)
@@ -1274,7 +1265,7 @@ impl<'tcx> InferCtxt<'tcx> {
if let Some(value) = inner.int_unification_table().probe_value(vid) {
value.to_type(self.tcx)
} else {
- self.tcx.mk_int_var(inner.int_unification_table().find(vid))
+ Ty::new_int_var(self.tcx, inner.int_unification_table().find(vid))
}
}
@@ -1285,7 +1276,7 @@ impl<'tcx> InferCtxt<'tcx> {
if let Some(value) = inner.float_unification_table().probe_value(vid) {
value.to_type(self.tcx)
} else {
- self.tcx.mk_float_var(inner.float_unification_table().find(vid))
+ Ty::new_float_var(self.tcx, inner.float_unification_table().find(vid))
}
}
@@ -1468,6 +1459,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// universes. Updates `self.universe` to that new universe.
pub fn create_next_universe(&self) -> ty::UniverseIndex {
let u = self.universe.get().next_universe();
+ debug!("create_next_universe {u:?}");
self.universe.set(u);
u
}
@@ -1480,7 +1472,7 @@ impl<'tcx> InferCtxt<'tcx> {
span: Option<Span>,
) -> Result<ty::Const<'tcx>, ErrorHandled> {
match self.const_eval_resolve(param_env, unevaluated, span) {
- Ok(Some(val)) => Ok(self.tcx.mk_const(val, ty)),
+ Ok(Some(val)) => Ok(ty::Const::new_value(self.tcx, val, ty)),
Ok(None) => {
let tcx = self.tcx;
let def_id = unevaluated.def;
@@ -1953,13 +1945,16 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
self.idx += 1;
idx
};
- self.tcx.mk_placeholder(ty::PlaceholderType {
- universe: ty::UniverseIndex::ROOT,
- bound: ty::BoundTy {
- var: ty::BoundVar::from_u32(idx),
- kind: ty::BoundTyKind::Anon,
+ Ty::new_placeholder(
+ self.tcx,
+ ty::PlaceholderType {
+ universe: ty::UniverseIndex::ROOT,
+ bound: ty::BoundTy {
+ var: ty::BoundVar::from_u32(idx),
+ kind: ty::BoundTyKind::Anon,
+ },
},
- })
+ )
} else {
t.super_fold_with(self)
}
@@ -1972,7 +1967,8 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
if ty.has_non_region_param() || ty.has_non_region_infer() {
bug!("const `{c}`'s type should not reference params or types");
}
- self.tcx.mk_const(
+ ty::Const::new_placeholder(
+ self.tcx,
ty::PlaceholderConst {
universe: ty::UniverseIndex::ROOT,
bound: ty::BoundVar::from_u32({