1
Fork 0

Fix use of has_infer_types

* Add a new method `has_infer_types_or_consts` that's used instead most
  of the time, since there's generally no reason to only consider types.
*  Remove use of `has_closure_types`, because closures are no longer
  implicitly linked to the `InferCtxt`.
This commit is contained in:
Matthew Jasper 2020-02-22 14:10:17 +00:00
parent beac68a887
commit ebc86b441d
14 changed files with 37 additions and 61 deletions

View file

@ -90,6 +90,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_infer_types_or_consts(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_CT_INFER)
}
fn has_infer_consts(&self) -> bool { fn has_infer_consts(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_CT_INFER) self.has_type_flags(TypeFlags::HAS_CT_INFER)
} }
@ -114,9 +117,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
fn has_re_placeholders(&self) -> bool { fn has_re_placeholders(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER) self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER)
} }
fn has_closure_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_CLOSURE)
}
/// "Free" regions in this context means that it has any region /// "Free" regions in this context means that it has any region
/// that is not (a) erased or (b) late-bound. /// that is not (a) erased or (b) late-bound.
fn has_free_regions(&self) -> bool { fn has_free_regions(&self) -> bool {

View file

@ -502,7 +502,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
let univariant = |fields: &[TyLayout<'_>], repr: &ReprOptions, kind| { let univariant = |fields: &[TyLayout<'_>], repr: &ReprOptions, kind| {
Ok(tcx.intern_layout(self.univariant_uninterned(ty, fields, repr, kind)?)) Ok(tcx.intern_layout(self.univariant_uninterned(ty, fields, repr, kind)?))
}; };
debug_assert!(!ty.has_infer_types()); debug_assert!(!ty.has_infer_types_or_consts());
Ok(match ty.kind { Ok(match ty.kind {
// Basic scalars. // Basic scalars.
@ -1752,7 +1752,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> { ) -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
debug_assert!(!ty.has_infer_types()); debug_assert!(!ty.has_infer_types_or_consts());
// First try computing a static layout. // First try computing a static layout.
let err = match tcx.layout_of(param_env.and(ty)) { let err = match tcx.layout_of(param_env.and(ty)) {

View file

@ -143,10 +143,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
} }
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !(t.needs_infer() if !t.needs_infer() && !t.has_erasable_regions() {
|| t.has_erasable_regions()
|| (t.has_closure_types() && self.infcx.in_progress_tables.is_some()))
{
return t; return t;
} }

View file

@ -1482,13 +1482,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
) -> bool { ) -> bool {
let ty = self.resolve_vars_if_possible(&ty); let ty = self.resolve_vars_if_possible(&ty);
// 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_none() || !ty.has_closure_types() {
if !(param_env, ty).has_local_value() { if !(param_env, ty).has_local_value() {
return ty.is_copy_modulo_regions(self.tcx, param_env, span); return ty.is_copy_modulo_regions(self.tcx, param_env, span);
} }
}
let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None); let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None);

View file

@ -340,7 +340,7 @@ where
// In NLL, we don't have type inference variables // In NLL, we don't have type inference variables
// floating around, so we can do this rather imprecise // floating around, so we can do this rather imprecise
// variant of the occurs-check. // variant of the occurs-check.
assert!(!generalized_ty.has_infer_types()); assert!(!generalized_ty.has_infer_types_or_consts());
} }
self.infcx.inner.borrow_mut().type_variables.instantiate(vid, generalized_ty); self.infcx.inner.borrow_mut().type_variables.instantiate(vid, generalized_ty);

View file

@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
} }
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !t.has_infer_types() && !t.has_infer_consts() { if !t.has_infer_types_or_consts() {
t // micro-optimize -- if there is nothing in this type that this fold affects... t // micro-optimize -- if there is nothing in this type that this fold affects...
} else { } else {
let t = self.infcx.shallow_resolve(t); let t = self.infcx.shallow_resolve(t);
@ -37,7 +37,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
} }
fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> { fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> {
if !ct.has_infer_consts() { if !ct.has_infer_types_or_consts() {
ct // micro-optimize -- if there is nothing in this const that this fold affects... ct // micro-optimize -- if there is nothing in this const that this fold affects...
} else { } else {
let ct = self.infcx.shallow_resolve(ct); let ct = self.infcx.shallow_resolve(ct);

View file

@ -647,7 +647,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
} }
// Try to report a help message // Try to report a help message
if !trait_ref.has_infer_types() if !trait_ref.has_infer_types_or_consts()
&& self.predicate_can_apply(obligation.param_env, trait_ref) && self.predicate_can_apply(obligation.param_env, trait_ref)
{ {
// If a where-clause may be useful, remind the // If a where-clause may be useful, remind the

View file

@ -471,7 +471,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
return; return;
} }
let trait_ref = self.resolve_vars_if_possible(trait_ref); let trait_ref = self.resolve_vars_if_possible(trait_ref);
if trait_ref.has_infer_types() { if trait_ref.has_infer_types_or_consts() {
// Do not ICE while trying to find if a reborrow would succeed on a trait with // Do not ICE while trying to find if a reborrow would succeed on a trait with
// unresolved bindings. // unresolved bindings.
return; return;

View file

@ -299,7 +299,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
let obligation = &mut pending_obligation.obligation; let obligation = &mut pending_obligation.obligation;
if obligation.predicate.has_infer_types() { if obligation.predicate.has_infer_types_or_consts() {
obligation.predicate = obligation.predicate =
self.selcx.infcx().resolve_vars_if_possible(&obligation.predicate); self.selcx.infcx().resolve_vars_if_possible(&obligation.predicate);
} }
@ -346,16 +346,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
// This is a bit subtle: for the most part, the // This is a bit subtle: for the most part, the
// only reason we can fail to make progress on // only reason we can fail to make progress on
// trait selection is because we don't have enough // trait selection is because we don't have enough
// information about the types in the trait. One // information about the types in the trait.
// exception is that we sometimes haven't decided
// what kind of closure a closure is. *But*, in
// that case, it turns out, the type of the
// closure will also change, because the closure
// also includes references to its upvars as part
// of its type, and those types are resolved at
// the same time.
//
// FIXME(#32286) logic seems false if no upvars
pending_obligation.stalled_on = pending_obligation.stalled_on =
trait_ref_type_vars(self.selcx, data.to_poly_trait_ref()); trait_ref_type_vars(self.selcx, data.to_poly_trait_ref());

View file

@ -213,7 +213,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
result result
); );
if result && (ty.has_infer_types() || ty.has_closure_types()) { if result && ty.has_infer_types_or_consts() {
// Because of inference "guessing", selection can sometimes claim // Because of inference "guessing", selection can sometimes claim
// to succeed while the success requires a guess. To ensure // to succeed while the success requires a guess. To ensure
// this function's result remains infallible, we must confirm // this function's result remains infallible, we must confirm

View file

@ -490,23 +490,15 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
match cache_result { match cache_result {
Ok(()) => {} Ok(()) => {}
Err(ProjectionCacheEntry::Ambiguous) => { Err(ProjectionCacheEntry::Ambiguous) => {
// If we found ambiguity the last time, that generally // If we found ambiguity the last time, that means we will continue
// means we will continue to do so until some type in the // to do so until some type in the key changes (and we know it
// key changes (and we know it hasn't, because we just // hasn't, because we just fully resolved it).
// fully resolved it). One exception though is closure
// types, which can transition from having a fixed kind to
// no kind with no visible change in the key.
//
// FIXME(#32286) refactor this so that closure type
// changes
debug!( debug!(
"opt_normalize_projection_type: \ "opt_normalize_projection_type: \
found cache entry: ambiguous" found cache entry: ambiguous"
); );
if !projection_ty.has_closure_types() {
return None; return None;
} }
}
Err(ProjectionCacheEntry::InProgress) => { Err(ProjectionCacheEntry::InProgress) => {
// If while normalized A::B, we are asked to normalize // If while normalized A::B, we are asked to normalize
// A::B, just return A::B itself. This is a conservative // A::B, just return A::B itself. This is a conservative

View file

@ -84,7 +84,7 @@ fn compute_implied_outlives_bounds<'tcx>(
// to avoids duplicate errors that otherwise show up. // to avoids duplicate errors that otherwise show up.
fulfill_cx.register_predicate_obligations( fulfill_cx.register_predicate_obligations(
infcx, infcx,
obligations.iter().filter(|o| o.predicate.has_infer_types()).cloned(), obligations.iter().filter(|o| o.predicate.has_infer_types_or_consts()).cloned(),
); );
// From the full set of obligations, just filter down to the // From the full set of obligations, just filter down to the

View file

@ -2900,14 +2900,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("resolve_vars_with_obligations(ty={:?})", ty); debug!("resolve_vars_with_obligations(ty={:?})", ty);
// No Infer()? Nothing needs doing. // No Infer()? Nothing needs doing.
if !ty.has_infer_types() && !ty.has_infer_consts() { if !ty.has_infer_types_or_consts() {
debug!("resolve_vars_with_obligations: ty={:?}", ty); debug!("resolve_vars_with_obligations: ty={:?}", ty);
return ty; return ty;
} }
// If `ty` is a type variable, see whether we already know what it is. // If `ty` is a type variable, see whether we already know what it is.
ty = self.resolve_vars_if_possible(&ty); ty = self.resolve_vars_if_possible(&ty);
if !ty.has_infer_types() && !ty.has_infer_consts() { if !ty.has_infer_types_or_consts() {
debug!("resolve_vars_with_obligations: ty={:?}", ty); debug!("resolve_vars_with_obligations: ty={:?}", ty);
return ty; return ty;
} }

View file

@ -1,8 +1,8 @@
error[E0277]: arrays only have std trait implementations for lengths 0..=32 error[E0277]: arrays only have std trait implementations for lengths 0..=32
--> $DIR/into-iter-no-impls-length-33.rs:12:5 --> $DIR/into-iter-no-impls-length-33.rs:12:19
| |
LL | IntoIter::new([0i32; 33]) LL | IntoIter::new([0i32; 33])
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
| |
= note: required by `std::array::IntoIter::<T, N>::new` = note: required by `std::array::IntoIter::<T, N>::new`
@ -19,10 +19,10 @@ LL | IntoIter::new([0i32; 33])
= note: the return type of a function must have a statically known size = note: the return type of a function must have a statically known size
error[E0277]: arrays only have std trait implementations for lengths 0..=32 error[E0277]: arrays only have std trait implementations for lengths 0..=32
--> $DIR/into-iter-no-impls-length-33.rs:18:5 --> $DIR/into-iter-no-impls-length-33.rs:18:19
| |
LL | IntoIter::new([0i32; 33]) LL | IntoIter::new([0i32; 33])
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
| |
= note: required by `std::array::IntoIter::<T, N>::new` = note: required by `std::array::IntoIter::<T, N>::new`
@ -39,10 +39,10 @@ LL | IntoIter::new([0i32; 33])
= note: the return type of a function must have a statically known size = note: the return type of a function must have a statically known size
error[E0277]: arrays only have std trait implementations for lengths 0..=32 error[E0277]: arrays only have std trait implementations for lengths 0..=32
--> $DIR/into-iter-no-impls-length-33.rs:24:5 --> $DIR/into-iter-no-impls-length-33.rs:24:19
| |
LL | IntoIter::new([0i32; 33]) LL | IntoIter::new([0i32; 33])
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
| |
= note: required by `std::array::IntoIter::<T, N>::new` = note: required by `std::array::IntoIter::<T, N>::new`
@ -59,10 +59,10 @@ LL | IntoIter::new([0i32; 33])
= note: the return type of a function must have a statically known size = note: the return type of a function must have a statically known size
error[E0277]: arrays only have std trait implementations for lengths 0..=32 error[E0277]: arrays only have std trait implementations for lengths 0..=32
--> $DIR/into-iter-no-impls-length-33.rs:30:5 --> $DIR/into-iter-no-impls-length-33.rs:30:19
| |
LL | IntoIter::new([0i32; 33]) LL | IntoIter::new([0i32; 33])
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
| |
= note: required by `std::array::IntoIter::<T, N>::new` = note: required by `std::array::IntoIter::<T, N>::new`
@ -79,10 +79,10 @@ LL | IntoIter::new([0i32; 33])
= note: the return type of a function must have a statically known size = note: the return type of a function must have a statically known size
error[E0277]: arrays only have std trait implementations for lengths 0..=32 error[E0277]: arrays only have std trait implementations for lengths 0..=32
--> $DIR/into-iter-no-impls-length-33.rs:36:5 --> $DIR/into-iter-no-impls-length-33.rs:36:19
| |
LL | IntoIter::new([0i32; 33]) LL | IntoIter::new([0i32; 33])
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
| |
= note: required by `std::array::IntoIter::<T, N>::new` = note: required by `std::array::IntoIter::<T, N>::new`
@ -99,10 +99,10 @@ LL | IntoIter::new([0i32; 33])
= note: the return type of a function must have a statically known size = note: the return type of a function must have a statically known size
error[E0277]: arrays only have std trait implementations for lengths 0..=32 error[E0277]: arrays only have std trait implementations for lengths 0..=32
--> $DIR/into-iter-no-impls-length-33.rs:42:5 --> $DIR/into-iter-no-impls-length-33.rs:42:19
| |
LL | IntoIter::new([0i32; 33]) LL | IntoIter::new([0i32; 33])
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
| |
= note: required by `std::array::IntoIter::<T, N>::new` = note: required by `std::array::IntoIter::<T, N>::new`
@ -119,10 +119,10 @@ LL | IntoIter::new([0i32; 33])
= note: the return type of a function must have a statically known size = note: the return type of a function must have a statically known size
error[E0277]: arrays only have std trait implementations for lengths 0..=32 error[E0277]: arrays only have std trait implementations for lengths 0..=32
--> $DIR/into-iter-no-impls-length-33.rs:48:5 --> $DIR/into-iter-no-impls-length-33.rs:48:19
| |
LL | IntoIter::new([0i32; 33]) LL | IntoIter::new([0i32; 33])
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
| |
= note: required by `std::array::IntoIter::<T, N>::new` = note: required by `std::array::IntoIter::<T, N>::new`