X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_infer%2Fsrc%2Finfer%2Fmod.rs;h=93a067cb5160633e441a632fa43e621a1cb561a1;hb=7f605496e75141b473827f3b8d5cdeb17e9f3408;hp=21208933d43408db98a4408b7cee3c533cc931b2;hpb=ef56a1e9c9c3e1f810429a77a9045321d7d4095c;p=rust.git diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 21208933d43..93a067cb516 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -20,7 +20,7 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; -use rustc_middle::mir::interpret::{ErrorHandled, EvalToConstValueResult}; +use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::traits::select; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; @@ -33,7 +33,6 @@ use rustc_span::Span; use std::cell::{Cell, Ref, RefCell}; -use std::collections::BTreeMap; use std::fmt; use self::combine::CombineFields; @@ -85,20 +84,6 @@ pub struct InferOk<'tcx, T> { ut::InPlace, &'a mut InferCtxtUndoLogs<'tcx>>, >; -/// How we should handle region solving. -/// -/// This is used so that the region values inferred by HIR region solving are -/// not exposed, and so that we can avoid doing work in HIR typeck that MIR -/// typeck will also do. -#[derive(Copy, Clone, Debug, Default)] -pub enum RegionckMode { - /// The default mode: report region errors, don't erase regions. - #[default] - Solve, - /// Erase the results of region after solving. - Erase, -} - /// This type contains all the things within `InferCtxt` that sit within a /// `RefCell` and are involved with taking/rolling back snapshots. Snapshot /// operations are hot enough that we want only one call to `borrow_mut` per @@ -1249,6 +1234,33 @@ pub fn set_tainted_by_errors(&self) { self.tainted_by_errors_flag.set(true) } + pub fn skip_region_resolution(&self) { + let (var_infos, _) = { + let mut inner = self.inner.borrow_mut(); + let inner = &mut *inner; + // Note: `inner.region_obligations` may not be empty, because we + // didn't necessarily call `process_registered_region_obligations`. + // This is okay, because that doesn't introduce new vars. + inner + .region_constraint_storage + .take() + .expect("regions already resolved") + .with_log(&mut inner.undo_log) + .into_infos_and_data() + }; + + let lexical_region_resolutions = LexicalRegionResolutions { + error_region: self.tcx.lifetimes.re_static, + values: rustc_index::vec::IndexVec::from_elem_n( + crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased), + var_infos.len(), + ), + }; + + let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); + assert!(old_value.is_none()); + } + /// Process the region constraints and return any any errors that /// result. After this, no more unification operations should be /// done -- or the compiler will panic -- but it is legal to use @@ -1257,7 +1269,6 @@ pub fn resolve_regions( &self, region_context: DefId, outlives_env: &OutlivesEnvironment<'tcx>, - mode: RegionckMode, ) -> Vec> { let (var_infos, data) = { let mut inner = self.inner.borrow_mut(); @@ -1279,7 +1290,7 @@ pub fn resolve_regions( &RegionRelations::new(self.tcx, region_context, outlives_env.free_region_map()); let (lexical_region_resolutions, errors) = - lexical_region_resolve::resolve(region_rels, var_infos, data, mode); + lexical_region_resolve::resolve(region_rels, var_infos, data); let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); assert!(old_value.is_none()); @@ -1295,9 +1306,8 @@ pub fn resolve_regions_and_report_errors( &self, region_context: DefId, outlives_env: &OutlivesEnvironment<'tcx>, - mode: RegionckMode, ) { - let errors = self.resolve_regions(region_context, outlives_env, mode); + let errors = self.resolve_regions(region_context, outlives_env); if !self.is_tainted_by_errors() { // As a heuristic, just skip reporting region errors @@ -1524,25 +1534,40 @@ pub fn replace_bound_vars_with_fresh_vars( span: Span, lbrct: LateBoundRegionConversionTime, value: ty::Binder<'tcx, T>, - ) -> (T, BTreeMap>) + ) -> T where - T: TypeFoldable<'tcx>, + T: TypeFoldable<'tcx> + Copy, { - let fld_r = - |br: ty::BoundRegion| self.next_region_var(LateBoundRegion(span, br.kind, lbrct)); - let fld_t = |_| { - self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span, + if let Some(inner) = value.no_bound_vars() { + return inner; + } + + let mut region_map = FxHashMap::default(); + let fld_r = |br: ty::BoundRegion| { + *region_map + .entry(br) + .or_insert_with(|| self.next_region_var(LateBoundRegion(span, br.kind, lbrct))) + }; + + let mut ty_map = FxHashMap::default(); + let fld_t = |bt: ty::BoundTy| { + *ty_map.entry(bt).or_insert_with(|| { + self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span, + }) }) }; - let fld_c = |_, ty| { - self.next_const_var( - ty, - ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span }, - ) + let mut ct_map = FxHashMap::default(); + let fld_c = |bc: ty::BoundVar, ty| { + *ct_map.entry(bc).or_insert_with(|| { + self.next_const_var( + ty, + ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span }, + ) + }) }; - self.tcx.replace_bound_vars(value, fld_r, fld_t, fld_c) + self.tcx.replace_bound_vars_uncached(value, fld_r, fld_t, fld_c) } /// See the [`region_constraints::RegionConstraintCollector::verify_generic_bound`] method. @@ -1591,6 +1616,28 @@ pub fn create_next_universe(&self) -> ty::UniverseIndex { u } + pub fn try_const_eval_resolve( + &self, + param_env: ty::ParamEnv<'tcx>, + unevaluated: ty::Unevaluated<'tcx>, + ty: Ty<'tcx>, + span: Option, + ) -> Result, ErrorHandled> { + match self.const_eval_resolve(param_env, unevaluated, span) { + Ok(Some(val)) => Ok(ty::Const::from_value(self.tcx, val, ty)), + Ok(None) => { + let tcx = self.tcx; + let def_id = unevaluated.def.did; + span_bug!( + tcx.def_span(def_id), + "unable to construct a constant value for the unevaluated constant {:?}", + unevaluated + ); + } + Err(err) => Err(err), + } + } + /// Resolves and evaluates a constant. /// /// The constant can be located on a trait like `::C`, in which case the given @@ -1609,7 +1656,7 @@ pub fn const_eval_resolve( param_env: ty::ParamEnv<'tcx>, unevaluated: ty::Unevaluated<'tcx>, span: Option, - ) -> EvalToConstValueResult<'tcx> { + ) -> EvalToValTreeResult<'tcx> { let substs = self.resolve_vars_if_possible(unevaluated.substs); debug!(?substs); @@ -1633,7 +1680,7 @@ pub fn const_eval_resolve( // The return value is the evaluated value which doesn't contain any reference to inference // variables, thus we don't need to substitute back the original values. - self.tcx.const_eval_resolve(param_env_erased, unevaluated, span) + self.tcx.const_eval_resolve_for_typeck(param_env_erased, unevaluated, span) } /// `ty_or_const_infer_var_changed` is equivalent to one of these two: @@ -1729,7 +1776,7 @@ pub fn maybe_from_ty(ty: Ty<'tcx>) -> Option { /// Tries to extract an inference variable from a constant, returns `None` /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`). pub fn maybe_from_const(ct: ty::Const<'tcx>) -> Option { - match ct.val() { + match ct.kind() { ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)), _ => None, } @@ -1808,7 +1855,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val() { + if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() { self.infcx .inner .borrow_mut()