diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 9a5c726901fe8..eca1ada851814 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1456,7 +1456,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Even if the type may have no inference variables, during // type-checking closure types are in local tables only. if !self.in_progress_tables.is_some() || !ty.has_closure_types() { - if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) { + if !(param_env, ty).has_local_value() { return ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span); } } diff --git a/src/librustc/infer/outlives/free_region_map.rs b/src/librustc/infer/outlives/free_region_map.rs index 1250995a59c10..c085df6a6e7ab 100644 --- a/src/librustc/infer/outlives/free_region_map.rs +++ b/src/librustc/infer/outlives/free_region_map.rs @@ -11,6 +11,10 @@ pub struct FreeRegionMap<'tcx> { } impl<'tcx> FreeRegionMap<'tcx> { + pub fn elements(&self) -> impl Iterator> { + self.relation.elements() + } + pub fn is_empty(&self) -> bool { self.relation.is_empty() } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index e7253a73bd418..088c862dcb879 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -465,9 +465,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ) -> bool { self.infcx.map(|infcx| infcx.type_is_copy_modulo_regions(param_env, ty, span)) .or_else(|| { - self.tcx.lift_to_global(&(param_env, ty)).map(|(param_env, ty)| { - ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span) - }) + if (param_env, ty).has_local_value() { + None + } else { + Some(ty.is_copy_modulo_regions(self.tcx, param_env, span)) + } }) .unwrap_or(true) } diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 256b3f1015093..7be4a2206f5b8 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -37,6 +37,10 @@ impl ErrorHandled { } } +CloneTypeFoldableImpls! { + ErrorHandled, +} + pub type ConstEvalRawResult<'tcx> = Result, ErrorHandled>; pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>; diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index f106458c7676a..99b5ef3894b9c 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -461,41 +461,35 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { } ty::Predicate::ConstEvaluatable(def_id, substs) => { - match self.selcx.tcx().lift_to_global(&obligation.param_env) { - None => { + if obligation.param_env.has_local_value() { ProcessResult::Unchanged - } - Some(param_env) => { - match self.selcx.tcx().lift_to_global(&substs) { - Some(substs) => { - let instance = ty::Instance::resolve( - self.selcx.tcx().global_tcx(), - param_env, - def_id, - substs, - ); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None, - }; - match self.selcx.tcx().at(obligation.cause.span) - .const_eval(param_env.and(cid)) { - Ok(_) => ProcessResult::Changed(vec![]), - Err(err) => ProcessResult::Error( - CodeSelectionError(ConstEvalFailure(err))) - } - } else { - ProcessResult::Error(CodeSelectionError( - ConstEvalFailure(ErrorHandled::TooGeneric) - )) - } - }, - None => { - pending_obligation.stalled_on = substs.types().collect(); - ProcessResult::Unchanged + } else { + if !substs.has_local_value() { + let instance = ty::Instance::resolve( + self.selcx.tcx().global_tcx(), + obligation.param_env, + def_id, + substs, + ); + if let Some(instance) = instance { + let cid = GlobalId { + instance, + promoted: None, + }; + match self.selcx.tcx().at(obligation.cause.span) + .const_eval(obligation.param_env.and(cid)) { + Ok(_) => ProcessResult::Changed(vec![]), + Err(err) => ProcessResult::Error( + CodeSelectionError(ConstEvalFailure(err))) } + } else { + ProcessResult::Error(CodeSelectionError( + ConstEvalFailure(ErrorHandled::TooGeneric) + )) } + } else { + pending_obligation.stalled_on = substs.types().collect(); + ProcessResult::Unchanged } } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8d17df1e61055..1ca92d79fa5f6 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -457,6 +457,16 @@ pub enum SelectionError<'tcx> { Overflow, } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for SelectionError<'tcx> { + (SelectionError::Unimplemented), + (SelectionError::OutputTypeParameterMismatch)(a, b, c), + (SelectionError::TraitNotObjectSafe)(a), + (SelectionError::ConstEvalFailure)(a), + (SelectionError::Overflow), + } +} + pub struct FulfillmentError<'tcx> { pub obligation: PredicateObligation<'tcx>, pub code: FulfillmentErrorCode<'tcx> @@ -782,13 +792,11 @@ fn do_normalize_predicates<'tcx>( return Err(ErrorReported) } }; - - match tcx.lift_to_global(&predicates) { - Some(predicates) => Ok(predicates), - None => { - // FIXME: shouldn't we, you know, actually report an error here? or an ICE? - Err(ErrorReported) - } + if predicates.has_local_value() { + // FIXME: shouldn't we, you know, actually report an error here? or an ICE? + Err(ErrorReported) + } else { + Ok(predicates) } }) } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 0f4b7aff82bce..8bd8f941fb3dd 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -399,7 +399,8 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { if let ConstValue::Unevaluated(def_id, substs) = constant.val { let tcx = self.selcx.tcx().global_tcx(); - if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) { + let param_env = self.param_env; + if !param_env.has_local_value() { if substs.needs_infer() || substs.has_placeholders() { let identity_substs = InternalSubsts::identity_for_item(tcx, def_id); let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); @@ -414,7 +415,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { } } } else { - if let Some(substs) = self.tcx().lift_to_global(&substs) { + if !substs.has_local_value() { let instance = ty::Instance::resolve(tcx, param_env, def_id, substs); if let Some(instance) = instance { let cid = GlobalId { diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 5dd1b9e3d53f3..55e622e46b966 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -193,7 +193,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { if let ConstValue::Unevaluated(def_id, substs) = constant.val { let tcx = self.infcx.tcx.global_tcx(); - if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) { + let param_env = self.param_env; + if !param_env.has_local_value() { if substs.needs_infer() || substs.has_placeholders() { let identity_substs = InternalSubsts::identity_for_item(tcx, def_id); let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); @@ -208,7 +209,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { } } } else { - if let Some(substs) = self.tcx().lift_to_global(&substs) { + if !substs.has_local_value() { let instance = ty::Instance::resolve(tcx, param_env, def_id, substs); if let Some(instance) = instance { let cid = GlobalId { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 7c4742259ac16..798a25fe7b1bc 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -328,6 +328,23 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> { } } +EnumTypeFoldableImpl! { + impl<'tcx> TypeFoldable<'tcx> for SelectionCandidate<'tcx> { + (SelectionCandidate::BuiltinCandidate) { has_nested }, + (SelectionCandidate::ParamCandidate)(poly_trait_ref), + (SelectionCandidate::ImplCandidate)(def_id), + (SelectionCandidate::AutoImplCandidate)(def_id), + (SelectionCandidate::ProjectionCandidate), + (SelectionCandidate::ClosureCandidate), + (SelectionCandidate::GeneratorCandidate), + (SelectionCandidate::FnPointerCandidate), + (SelectionCandidate::TraitAliasCandidate)(def_id), + (SelectionCandidate::ObjectCandidate), + (SelectionCandidate::BuiltinObjectCandidate), + (SelectionCandidate::BuiltinUnsizeCandidate), + } +} + struct SelectionCandidateSet<'tcx> { // a list of candidates that definitely apply to the current // obligation (meaning: types unify). @@ -818,27 +835,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Predicate::ConstEvaluatable(def_id, substs) => { let tcx = self.tcx(); - match tcx.lift_to_global(&(obligation.param_env, substs)) { - Some((param_env, substs)) => { - let instance = - ty::Instance::resolve(tcx.global_tcx(), param_env, def_id, substs); - if let Some(instance) = instance { - let cid = GlobalId { - instance, - promoted: None, - }; - match self.tcx().const_eval(param_env.and(cid)) { - Ok(_) => Ok(EvaluatedToOk), - Err(_) => Ok(EvaluatedToErr), - } - } else { - Ok(EvaluatedToErr) + if !(obligation.param_env, substs).has_local_value() { + let param_env = obligation.param_env; + let instance = + ty::Instance::resolve(tcx, param_env, def_id, substs); + if let Some(instance) = instance { + let cid = GlobalId { + instance, + promoted: None, + }; + match self.tcx().const_eval(param_env.and(cid)) { + Ok(_) => Ok(EvaluatedToOk), + Err(_) => Ok(EvaluatedToErr), } + } else { + Ok(EvaluatedToErr) } - None => { - // Inference variables still left in param_env or substs. - Ok(EvaluatedToAmbig) - } + } else { + // Inference variables still left in param_env or substs. + Ok(EvaluatedToAmbig) } } } @@ -1172,7 +1187,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if self.can_use_global_caches(param_env) { - if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) { + if !trait_ref.has_local_value() { debug!( "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global", trait_ref, result, @@ -1645,8 +1660,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let Err(Overflow) = candidate { // Don't cache overflow globally; we only produce this // in certain modes. - } else if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) { - if let Some(candidate) = tcx.lift_to_global(&candidate) { + } else if !trait_ref.has_local_value() { + if !candidate.has_local_value() { debug!( "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global", trait_ref, candidate, diff --git a/src/librustc/ty/erase_regions.rs b/src/librustc/ty/erase_regions.rs index 999b4eff85697..3dd1fd100f2a4 100644 --- a/src/librustc/ty/erase_regions.rs +++ b/src/librustc/ty/erase_regions.rs @@ -42,10 +42,10 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) { - self.tcx.erase_regions_ty(ty_lifted) - } else { + if ty.has_local_value() { ty.super_fold_with(self) + } else { + self.tcx.erase_regions_ty(ty) } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 8b98a2916a766..ab7df8e4e845b 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -91,6 +91,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn has_infer_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_INFER) } + fn has_local_value(&self) -> bool { + self.has_type_flags(TypeFlags::KEEP_IN_LOCAL_TCX) + } fn needs_infer(&self) -> bool { self.has_type_flags( TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER | TypeFlags::HAS_CT_INFER @@ -922,6 +925,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { } } +// FIXME: Optimize for checking for infer flags struct HasTypeFlagsVisitor { flags: ty::TypeFlags, } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 46adb7eb2a476..a6bfc2dee613b 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -550,7 +550,7 @@ pub fn super_relate_consts>( if let ConstValue::Unevaluated(def_id, substs) = x.val { // FIXME(eddyb) get the right param_env. let param_env = ty::ParamEnv::empty(); - if let Some(substs) = tcx.lift_to_global(&substs) { + if !substs.has_local_value() { let instance = ty::Instance::resolve( tcx.global_tcx(), param_env, diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 3d8170586c47f..27cd745c20fcb 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -821,6 +821,13 @@ EnumTypeFoldableImpl! { } where T: TypeFoldable<'tcx> } +EnumTypeFoldableImpl! { + impl<'tcx, T, E> TypeFoldable<'tcx> for Result { + (Ok)(a), + (Err)(a), + } where T: TypeFoldable<'tcx>, E: TypeFoldable<'tcx>, +} + impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc { fn super_fold_with>(&self, folder: &mut F) -> Self { Rc::new((**self).fold_with(folder)) diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs index 0974607fabea8..d7cbd1e2e4b47 100644 --- a/src/librustc_data_structures/transitive_relation.rs +++ b/src/librustc_data_structures/transitive_relation.rs @@ -58,6 +58,10 @@ impl TransitiveRelation { self.edges.is_empty() } + pub fn elements(&self) -> impl Iterator { + self.elements.iter() + } + fn index(&self, a: &T) -> Option { self.map.get(a).cloned() } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 41ed564d0f0e1..a4fa1d98255ba 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -809,7 +809,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { ty: Ty<'tcx>, ) -> Option> { let tcx = infcx.tcx; - let gcx = tcx.global_tcx(); debug!("try_promote_type_test_subject(ty = {:?})", ty); @@ -863,8 +862,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { }); debug!("try_promote_type_test_subject: folded ty = {:?}", ty); - // `lift_to_global` will only fail if we failed to promote some region. - gcx.lift_to_global(&ty)?; + // `has_local_value` will only be true if we failed to promote some region. + if ty.has_local_value() { + return None; + } Some(ClosureOutlivesSubject::Ty(ty)) } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 034ff5f834767..d612d042f7f23 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -3,7 +3,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par use crate::hir::def_id::DefId; use rustc::traits::{self, ObligationCauseCode}; -use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate}; +use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate}; use rustc::ty::subst::{Subst, InternalSubsts}; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::mir::interpret::ConstValue; @@ -261,14 +261,15 @@ fn check_type_defn<'tcx, F>( let needs_drop_copy = || { packed && { let ty = variant.fields.last().unwrap().ty; - fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx) - .map(|ty| ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))) - .unwrap_or_else(|| { + let ty = fcx.tcx.erase_regions(&ty); + if ty.has_local_value() { fcx_tcx.sess.delay_span_bug( item.span, &format!("inference variables in {:?}", ty)); // Just treat unresolved type expression as if it needs drop. true - }) + } else { + ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id)) + } } }; let all_sized = diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 6a95dec1c81bc..28711e32a4c51 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -363,10 +363,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } fn visit_free_region_map(&mut self) { - let free_region_map = self.tcx() - .lift_to_global(&self.fcx.tables.borrow().free_region_map); - let free_region_map = free_region_map.expect("all regions in free-region-map are global"); - self.tables.free_region_map = free_region_map; + self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone(); + debug_assert!(!self.tables.free_region_map.elements().any(|r| r.has_local_value())); } fn visit_user_provided_tys(&mut self) { @@ -381,12 +379,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { local_id, }; - let c_ty = if let Some(c_ty) = self.tcx().lift_to_global(c_ty) { - c_ty - } else { + if cfg!(debug_assertions) && c_ty.has_local_value() { span_bug!( hir_id.to_span(self.fcx.tcx), - "writeback: `{:?}` missing from the global type context", + "writeback: `{:?}` is a local value", c_ty ); }; @@ -423,12 +419,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); for (&def_id, c_sig) in fcx_tables.user_provided_sigs.iter() { - let c_sig = if let Some(c_sig) = self.tcx().lift_to_global(c_sig) { - c_sig - } else { + if cfg!(debug_assertions) && c_sig.has_local_value() { span_bug!( self.fcx.tcx.hir().span_if_local(def_id).unwrap(), - "writeback: `{:?}` missing from the global type context", + "writeback: `{:?}` is a local value", c_sig ); }; @@ -592,10 +586,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - if let Some(substs) = self.tcx().lift_to_global(&opaque_defn.substs) { + if !opaque_defn.substs.has_local_value() { let new = ty::ResolvedOpaqueTy { concrete_type: definition_ty, - substs, + substs: opaque_defn.substs, }; let old = self.tables @@ -617,7 +611,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } else { self.tcx().sess.delay_span_bug( span, - "cannot lift `opaque_defn` substs to global type context", + "`opaque_defn` is a local value", ); } } @@ -743,20 +737,19 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - fn resolve(&self, x: &T, span: &dyn Locatable) -> T::Lifted + fn resolve(&self, x: &T, span: &dyn Locatable) -> T where - T: TypeFoldable<'tcx> + ty::Lift<'tcx>, + T: TypeFoldable<'tcx>, { let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body)); - if let Some(lifted) = self.tcx().lift_to_global(&x) { - lifted - } else { + if cfg!(debug_assertions) && x.has_local_value() { span_bug!( span.to_span(self.fcx.tcx), - "writeback: `{:?}` missing from the global type context", + "writeback: `{:?}` is a local value", x ); } + x } }