Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't use lift to detect local types #61871

Merged
merged 2 commits into from
Jul 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @rust-lang/compiler I think it might be better if we stop referring to these as "local values" and instead use something more like .has_infer_vars()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has_infer_types already exist and is a different property.

return ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/infer/outlives/free_region_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ pub struct FreeRegionMap<'tcx> {
}

impl<'tcx> FreeRegionMap<'tcx> {
pub fn elements(&self) -> impl Iterator<Item=&Region<'tcx>> {
self.relation.elements()
}

pub fn is_empty(&self) -> bool {
self.relation.is_empty()
}
Expand Down
8 changes: 5 additions & 3 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, if self.infcx is None, this case should be impossible - it's plausible this code is unnecessarily defensive and lift_to_global's result could've been unwrap'd all along.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree.

} else {
Some(ty.is_copy_modulo_regions(self.tcx, param_env, span))
}
})
.unwrap_or(true)
}
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ impl ErrorHandled {
}
}

CloneTypeFoldableImpls! {
ErrorHandled,
}

pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;

Expand Down
18 changes: 6 additions & 12 deletions src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,16 +461,13 @@ 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() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the other match -> if change.

ProcessResult::Unchanged
}
Some(param_env) => {
match self.selcx.tcx().lift_to_global(&substs) {
Some(substs) => {
} else {
if !substs.has_local_value() {
let instance = ty::Instance::resolve(
self.selcx.tcx().global_tcx(),
param_env,
obligation.param_env,
def_id,
substs,
);
Expand All @@ -480,7 +477,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
promoted: None,
};
match self.selcx.tcx().at(obligation.cause.span)
.const_eval(param_env.and(cid)) {
.const_eval(obligation.param_env.and(cid)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't wait for this to use erasure and canonicalization instead (@oli-obk and @nikomatsakis are working on that, I think?).

Ok(_) => ProcessResult::Changed(vec![]),
Err(err) => ProcessResult::Error(
CodeSelectionError(ConstEvalFailure(err)))
Expand All @@ -490,17 +487,14 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
ConstEvalFailure(ErrorHandled::TooGeneric)
))
}
},
None => {
} else {
pending_obligation.stalled_on = substs.types().collect();
ProcessResult::Unchanged
}
}
}
}
}
}
}

fn process_backedge<'c, I>(&mut self, cycle: I,
_marker: PhantomData<&'c PendingPredicateObligation<'tcx>>)
Expand Down
18 changes: 13 additions & 5 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -782,13 +792,11 @@ fn do_normalize_predicates<'tcx>(
return Err(ErrorReported)
}
};

match tcx.lift_to_global(&predicates) {
Some(predicates) => Ok(predicates),
None => {
if predicates.has_local_value() {
// FIXME: shouldn't we, you know, actually report an error here? or an ICE?
Err(ErrorReported)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rust-lang/wg-traits This is scary, can we do a crater run with a delay_span_bug in here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eddyb What happened to this?

}
} else {
Ok(predicates)
}
})
}
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 {
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/traits/query/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 {
Expand Down
33 changes: 24 additions & 9 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -818,10 +835,10 @@ 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)) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer if one of two things happened here (and in other places match-ing over lift_to_global results):

  • land a PR on master replacing the matches with if lets (you can just r=me that if you want)
  • keep the match and either use Option::filter or just match on the bool predicate

That is, I would prefer if indentation didn't change (and it only does because of the match -> if change).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you not want indention to change? I like less rightward drift, and I definitely don't like matching on bools.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine to change, I just want to be able to read the diff without mentally pretending nothing changed without checking, where indentation is involved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the indentation to reduce the diffs in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eddyb you can append ?w=1 to the diff url to have whitespace insensitive diffs https://github.com/rust-lang/rust/pull/61871/files?w=1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. I also reordered some branches which that can't deal with though =P

if !(obligation.param_env, substs).has_local_value() {
let param_env = obligation.param_env;
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 {
let cid = GlobalId {
instance,
Expand All @@ -834,15 +851,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} else {
Ok(EvaluatedToErr)
}
}
None => {
} else {
// Inference variables still left in param_env or substs.
Ok(EvaluatedToAmbig)
}
}
}
}
}

fn evaluate_trait_predicate_recursively<'o>(
&mut self,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/ty/erase_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/librustc/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -922,6 +925,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
}
}

// FIXME: Optimize for checking for infer flags
struct HasTypeFlagsVisitor {
flags: ty::TypeFlags,
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
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,
Expand Down
7 changes: 7 additions & 0 deletions src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,13 @@ EnumTypeFoldableImpl! {
} 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> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
Rc::new((**self).fold_with(folder))
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_data_structures/transitive_relation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
self.edges.is_empty()
}

pub fn elements(&self) -> impl Iterator<Item=&T> {
self.elements.iter()
}

fn index(&self, a: &T) -> Option<Index> {
self.map.get(a).cloned()
}
Expand Down
7 changes: 4 additions & 3 deletions src/librustc_mir/borrow_check/nll/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
ty: Ty<'tcx>,
) -> Option<ClosureOutlivesSubject<'tcx>> {
let tcx = infcx.tcx;
let gcx = tcx.global_tcx();

debug!("try_promote_type_test_subject(ty = {:?})", ty);

Expand Down Expand Up @@ -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))
}
Expand Down
11 changes: 6 additions & 5 deletions src/librustc_typeck/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 =
Expand Down
Loading