pub use self::RegionVariableOrigin::*;
pub use self::SubregionOrigin::*;
pub use self::ValuePairs::*;
-pub use rustc::ty::IntVarValue;
use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine};
use rustc::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
use rustc::middle::free_region::RegionRelations;
-use rustc::middle::lang_items;
use rustc::middle::region;
use rustc::mir;
use rustc::mir::interpret::ConstEvalResult;
-use rustc::session::config::BorrowckMode;
+use rustc::traits::select;
use rustc::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
use rustc::ty::fold::{TypeFoldable, TypeFolder};
use rustc::ty::relate::RelateResult;
use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
+pub use rustc::ty::IntVarValue;
use rustc::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
use rustc::ty::{ConstVid, FloatVid, IntVid, TyVid};
-
use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc;
use rustc_errors::DiagnosticBuilder;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
+use rustc_session::config::BorrowckMode;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
+
use std::cell::{Cell, Ref, RefCell};
use std::collections::BTreeMap;
use std::fmt;
mod lexical_region_resolve;
mod lub;
pub mod nll_relate;
-pub mod opaque_types;
pub mod outlives;
pub mod region_constraints;
pub mod resolve;
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result"
-/// A flag that is used to suppress region errors. This is normally
-/// false, but sometimes -- when we are doing region checks that the
-/// NLL borrow checker will also do -- it might be set to true.
-#[derive(Copy, Clone, Default, Debug)]
-pub struct SuppressRegionErrors {
- suppressed: bool,
+/// 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)]
+pub enum RegionckMode {
+ /// The default mode: report region errors, don't erase regions.
+ Solve,
+ /// Erase the results of region after solving.
+ Erase {
+ /// A flag that is used to suppress region errors, when we are doing
+ /// region checks that the NLL borrow checker will also do -- it might
+ /// be set to true.
+ suppress_errors: bool,
+ },
+}
+
+impl Default for RegionckMode {
+ fn default() -> Self {
+ RegionckMode::Solve
+ }
}
-impl SuppressRegionErrors {
+impl RegionckMode {
pub fn suppressed(self) -> bool {
- self.suppressed
+ match self {
+ Self::Solve => false,
+ Self::Erase { suppress_errors } => suppress_errors,
+ }
}
/// Indicates that the MIR borrowck will repeat these region
/// checks, so we should ignore errors if NLL is (unconditionally)
/// enabled.
- pub fn when_nll_is_enabled(tcx: TyCtxt<'_>) -> Self {
+ pub fn for_item_body(tcx: TyCtxt<'_>) -> Self {
// FIXME(Centril): Once we actually remove `::Migrate` also make
// this always `true` and then proceed to eliminate the dead code.
match tcx.borrowck_mode() {
// If we're on Migrate mode, report AST region errors
- BorrowckMode::Migrate => SuppressRegionErrors { suppressed: false },
+ BorrowckMode::Migrate => RegionckMode::Erase { suppress_errors: false },
// If we're on MIR, don't report AST region errors as they should be reported by NLL
- BorrowckMode::Mir => SuppressRegionErrors { suppressed: true },
+ BorrowckMode::Mir => RegionckMode::Erase { suppress_errors: true },
}
}
}
/// Caches the results of trait selection. This cache is used
/// for things that have to do with the parameters in scope.
- pub selection_cache: traits::SelectionCache<'tcx>,
+ pub selection_cache: select::SelectionCache<'tcx>,
/// Caches the results of trait evaluation.
- pub evaluation_cache: traits::EvaluationCache<'tcx>,
+ pub evaluation_cache: select::EvaluationCache<'tcx>,
/// the set of predicates on which errors have been reported, to
/// avoid reporting the same error twice.
region_context: DefId,
region_map: ®ion::ScopeTree,
outlives_env: &OutlivesEnvironment<'tcx>,
- suppress: SuppressRegionErrors,
+ mode: RegionckMode,
) {
assert!(
self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(),
"region_obligations not empty: {:#?}",
self.inner.borrow().region_obligations
);
-
- let region_rels = &RegionRelations::new(
- self.tcx,
- region_context,
- region_map,
- outlives_env.free_region_map(),
- );
let (var_infos, data) = self
.inner
.borrow_mut()
.take()
.expect("regions already resolved")
.into_infos_and_data();
+
+ let region_rels = &RegionRelations::new(
+ self.tcx,
+ region_context,
+ region_map,
+ outlives_env.free_region_map(),
+ );
+
let (lexical_region_resolutions, errors) =
- lexical_region_resolve::resolve(region_rels, var_infos, data);
+ lexical_region_resolve::resolve(region_rels, var_infos, data, mode);
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
assert!(old_value.is_none());
// this infcx was in use. This is totally hokey but
// otherwise we have a hard time separating legit region
// errors from silly ones.
- self.report_region_errors(region_map, &errors, suppress);
+ self.report_region_errors(region_map, &errors);
}
}
.verify_generic_bound(origin, kind, a, bound);
}
- pub fn type_is_copy_modulo_regions(
- &self,
- param_env: ty::ParamEnv<'tcx>,
- ty: Ty<'tcx>,
- span: Span,
- ) -> bool {
- let ty = self.resolve_vars_if_possible(&ty);
-
- if !(param_env, ty).has_local_value() {
- return ty.is_copy_modulo_regions(self.tcx, param_env, span);
- }
-
- let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None);
-
- // This can get called from typeck (by euv), and `moves_by_default`
- // rightly refuses to work with inference variables, but
- // moves_by_default has a cache, which we want to use in other
- // cases.
- traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
- }
-
/// Obtains the latest type of the given closure; this may be a
/// closure in the current function, in which case its
/// `ClosureKind` may not yet be known.
closure_sig_ty.fn_sig(self.tcx)
}
- /// Normalizes associated types in `value`, potentially returning
- /// new obligations that must further be processed.
- pub fn partially_normalize_associated_types_in<T>(
- &self,
- span: Span,
- body_id: hir::HirId,
- param_env: ty::ParamEnv<'tcx>,
- value: &T,
- ) -> InferOk<'tcx, T>
- where
- T: TypeFoldable<'tcx>,
- {
- debug!("partially_normalize_associated_types_in(value={:?})", value);
- let mut selcx = traits::SelectionContext::new(self);
- let cause = ObligationCause::misc(span, body_id);
- let traits::Normalized { value, obligations } =
- traits::normalize(&mut selcx, param_env, cause, value);
- debug!(
- "partially_normalize_associated_types_in: result={:?} predicates={:?}",
- value, obligations
- );
- InferOk { value, obligations }
- }
-
/// Clears the selection, evaluation, and projection caches. This is useful when
/// repeatedly attempting to select an `Obligation` while changing only
/// its `ParamEnv`, since `FulfillmentContext` doesn't use probing.