1
Fork 0

Don't use lift to detect local types

This commit is contained in:
John Kåre Alsaker 2019-05-31 10:23:22 +02:00
parent d3e2cec292
commit c9325181d6
15 changed files with 122 additions and 84 deletions

View file

@ -1456,7 +1456,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// Even if the type may have no inference variables, during // Even if the type may have no inference variables, during
// type-checking closure types are in local tables only. // type-checking closure types are in local tables only.
if !self.in_progress_tables.is_some() || !ty.has_closure_types() { 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); return ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span);
} }
} }

View file

@ -465,9 +465,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
) -> bool { ) -> bool {
self.infcx.map(|infcx| infcx.type_is_copy_modulo_regions(param_env, ty, span)) self.infcx.map(|infcx| infcx.type_is_copy_modulo_regions(param_env, ty, span))
.or_else(|| { .or_else(|| {
self.tcx.lift_to_global(&(param_env, ty)).map(|(param_env, ty)| { if (param_env, ty).has_local_value() {
ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span) None
}) } else {
Some(ty.is_copy_modulo_regions(self.tcx, param_env, span))
}
}) })
.unwrap_or(true) .unwrap_or(true)
} }

View file

@ -37,6 +37,10 @@ impl ErrorHandled {
} }
} }
CloneTypeFoldableImpls! {
ErrorHandled,
}
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>; pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>; pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;

View file

@ -461,41 +461,35 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
} }
ty::Predicate::ConstEvaluatable(def_id, substs) => { ty::Predicate::ConstEvaluatable(def_id, substs) => {
match self.selcx.tcx().lift_to_global(&obligation.param_env) { if obligation.param_env.has_local_value() {
None => {
ProcessResult::Unchanged ProcessResult::Unchanged
} } else {
Some(param_env) => { if !substs.has_local_value() {
match self.selcx.tcx().lift_to_global(&substs) { let instance = ty::Instance::resolve(
Some(substs) => { self.selcx.tcx().global_tcx(),
let instance = ty::Instance::resolve( obligation.param_env,
self.selcx.tcx().global_tcx(), def_id,
param_env, substs,
def_id, );
substs, if let Some(instance) = instance {
); let cid = GlobalId {
if let Some(instance) = instance { instance,
let cid = GlobalId { promoted: None,
instance, };
promoted: None, match self.selcx.tcx().at(obligation.cause.span)
}; .const_eval(obligation.param_env.and(cid)) {
match self.selcx.tcx().at(obligation.cause.span) Ok(_) => ProcessResult::Changed(vec![]),
.const_eval(param_env.and(cid)) { Err(err) => ProcessResult::Error(
Ok(_) => ProcessResult::Changed(vec![]), CodeSelectionError(ConstEvalFailure(err)))
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 {
ProcessResult::Error(CodeSelectionError(
ConstEvalFailure(ErrorHandled::TooGeneric)
))
} }
} else {
pending_obligation.stalled_on = substs.types().collect();
ProcessResult::Unchanged
} }
} }
} }

View file

@ -457,6 +457,16 @@ pub enum SelectionError<'tcx> {
Overflow, 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 struct FulfillmentError<'tcx> {
pub obligation: PredicateObligation<'tcx>, pub obligation: PredicateObligation<'tcx>,
pub code: FulfillmentErrorCode<'tcx> pub code: FulfillmentErrorCode<'tcx>
@ -782,13 +792,11 @@ fn do_normalize_predicates<'tcx>(
return Err(ErrorReported) return Err(ErrorReported)
} }
}; };
if predicates.has_local_value() {
match tcx.lift_to_global(&predicates) { // FIXME: shouldn't we, you know, actually report an error here? or an ICE?
Some(predicates) => Ok(predicates), Err(ErrorReported)
None => { } else {
// FIXME: shouldn't we, you know, actually report an error here? or an ICE? Ok(predicates)
Err(ErrorReported)
}
} }
}) })
} }

View file

@ -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> { fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ConstValue::Unevaluated(def_id, substs) = constant.val { if let ConstValue::Unevaluated(def_id, substs) = constant.val {
let tcx = self.selcx.tcx().global_tcx(); 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() { if substs.needs_infer() || substs.has_placeholders() {
let identity_substs = InternalSubsts::identity_for_item(tcx, def_id); let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); 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 { } 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); let instance = ty::Instance::resolve(tcx, param_env, def_id, substs);
if let Some(instance) = instance { if let Some(instance) = instance {
let cid = GlobalId { let cid = GlobalId {

View file

@ -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> { fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
if let ConstValue::Unevaluated(def_id, substs) = constant.val { if let ConstValue::Unevaluated(def_id, substs) = constant.val {
let tcx = self.infcx.tcx.global_tcx(); 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() { if substs.needs_infer() || substs.has_placeholders() {
let identity_substs = InternalSubsts::identity_for_item(tcx, def_id); let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); 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 { } 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); let instance = ty::Instance::resolve(tcx, param_env, def_id, substs);
if let Some(instance) = instance { if let Some(instance) = instance {
let cid = GlobalId { let cid = GlobalId {

View file

@ -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> { struct SelectionCandidateSet<'tcx> {
// a list of candidates that definitely apply to the current // a list of candidates that definitely apply to the current
// obligation (meaning: types unify). // obligation (meaning: types unify).
@ -818,27 +835,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::Predicate::ConstEvaluatable(def_id, substs) => { ty::Predicate::ConstEvaluatable(def_id, substs) => {
let tcx = self.tcx(); let tcx = self.tcx();
match tcx.lift_to_global(&(obligation.param_env, substs)) { if !(obligation.param_env, substs).has_local_value() {
Some((param_env, substs)) => { let param_env = obligation.param_env;
let instance = let instance =
ty::Instance::resolve(tcx.global_tcx(), param_env, def_id, substs); ty::Instance::resolve(tcx, param_env, def_id, substs);
if let Some(instance) = instance { if let Some(instance) = instance {
let cid = GlobalId { let cid = GlobalId {
instance, instance,
promoted: None, promoted: None,
}; };
match self.tcx().const_eval(param_env.and(cid)) { match self.tcx().const_eval(param_env.and(cid)) {
Ok(_) => Ok(EvaluatedToOk), Ok(_) => Ok(EvaluatedToOk),
Err(_) => Ok(EvaluatedToErr), Err(_) => Ok(EvaluatedToErr),
}
} else {
Ok(EvaluatedToErr)
} }
} else {
Ok(EvaluatedToErr)
} }
None => { } else {
// Inference variables still left in param_env or substs. // Inference variables still left in param_env or substs.
Ok(EvaluatedToAmbig) Ok(EvaluatedToAmbig)
}
} }
} }
} }
@ -1172,7 +1187,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
if self.can_use_global_caches(param_env) { 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!( debug!(
"insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global", "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global",
trait_ref, result, trait_ref, result,
@ -1645,8 +1660,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if let Err(Overflow) = candidate { if let Err(Overflow) = candidate {
// Don't cache overflow globally; we only produce this // Don't cache overflow globally; we only produce this
// in certain modes. // in certain modes.
} else if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) { } else if !trait_ref.has_local_value() {
if let Some(candidate) = tcx.lift_to_global(&candidate) { if !candidate.has_local_value() {
debug!( debug!(
"insert_candidate_cache(trait_ref={:?}, candidate={:?}) global", "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
trait_ref, candidate, trait_ref, candidate,

View file

@ -42,10 +42,10 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
} }
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) { if ty.has_local_value() {
self.tcx.erase_regions_ty(ty_lifted)
} else {
ty.super_fold_with(self) ty.super_fold_with(self)
} else {
self.tcx.erase_regions_ty(ty)
} }
} }

View file

@ -91,6 +91,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
fn has_infer_types(&self) -> bool { fn has_infer_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER) 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 { fn needs_infer(&self) -> bool {
self.has_type_flags( self.has_type_flags(
TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER | TypeFlags::HAS_CT_INFER 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 { struct HasTypeFlagsVisitor {
flags: ty::TypeFlags, flags: ty::TypeFlags,
} }

View file

@ -550,7 +550,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
if let ConstValue::Unevaluated(def_id, substs) = x.val { if let ConstValue::Unevaluated(def_id, substs) = x.val {
// FIXME(eddyb) get the right param_env. // FIXME(eddyb) get the right param_env.
let param_env = ty::ParamEnv::empty(); 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( let instance = ty::Instance::resolve(
tcx.global_tcx(), tcx.global_tcx(),
param_env, param_env,

View file

@ -821,6 +821,13 @@ EnumTypeFoldableImpl! {
} where T: TypeFoldable<'tcx> } where T: TypeFoldable<'tcx>
} }
EnumTypeFoldableImpl! {
impl<'tcx, T, E> TypeFoldable<'tcx> for Result<T, E> {
(Ok)(a),
(Err)(a),
} where T: TypeFoldable<'tcx>, E: TypeFoldable<'tcx>,
}
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> { impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self { fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
Rc::new((**self).fold_with(folder)) Rc::new((**self).fold_with(folder))

View file

@ -809,7 +809,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> Option<ClosureOutlivesSubject<'tcx>> { ) -> Option<ClosureOutlivesSubject<'tcx>> {
let tcx = infcx.tcx; let tcx = infcx.tcx;
let gcx = tcx.global_tcx();
debug!("try_promote_type_test_subject(ty = {:?})", ty); 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); debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
// `lift_to_global` will only fail if we failed to promote some region. // `has_local_value` will only be true if we failed to promote some region.
gcx.lift_to_global(&ty)?; if ty.has_local_value() {
return None;
}
Some(ClosureOutlivesSubject::Ty(ty)) Some(ClosureOutlivesSubject::Ty(ty))
} }

View file

@ -3,7 +3,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par
use crate::hir::def_id::DefId; use crate::hir::def_id::DefId;
use rustc::traits::{self, ObligationCauseCode}; 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::ty::subst::{Subst, InternalSubsts};
use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc::mir::interpret::ConstValue; use rustc::mir::interpret::ConstValue;
@ -261,14 +261,15 @@ fn check_type_defn<'tcx, F>(
let needs_drop_copy = || { let needs_drop_copy = || {
packed && { packed && {
let ty = variant.fields.last().unwrap().ty; let ty = variant.fields.last().unwrap().ty;
fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx) let ty = fcx.tcx.erase_regions(&ty);
.map(|ty| ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))) if ty.has_local_value() {
.unwrap_or_else(|| {
fcx_tcx.sess.delay_span_bug( fcx_tcx.sess.delay_span_bug(
item.span, &format!("inference variables in {:?}", ty)); item.span, &format!("inference variables in {:?}", ty));
// Just treat unresolved type expression as if it needs drop. // Just treat unresolved type expression as if it needs drop.
true true
}) } else {
ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))
}
} }
}; };
let all_sized = let all_sized =

View file

@ -592,10 +592,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 { let new = ty::ResolvedOpaqueTy {
concrete_type: definition_ty, concrete_type: definition_ty,
substs, substs: opaque_defn.substs,
}; };
let old = self.tables let old = self.tables
@ -617,7 +617,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
} else { } else {
self.tcx().sess.delay_span_bug( self.tcx().sess.delay_span_bug(
span, span,
"cannot lift `opaque_defn` substs to global type context", "`opaque_defn` is a local value",
); );
} }
} }