introduce a Diverging
enum instead of a bool
This commit is contained in:
parent
c1b4824800
commit
7e0ae7d89b
|
@ -22,7 +22,6 @@
|
||||||
// is also useful to track which value is the "expected" value in
|
// is also useful to track which value is the "expected" value in
|
||||||
// terms of error reporting.
|
// terms of error reporting.
|
||||||
|
|
||||||
use super::equate::Equate;
|
|
||||||
use super::glb::Glb;
|
use super::glb::Glb;
|
||||||
use super::lub::Lub;
|
use super::lub::Lub;
|
||||||
use super::sub::Sub;
|
use super::sub::Sub;
|
||||||
|
@ -30,6 +29,7 @@ use super::type_variable::TypeVariableValue;
|
||||||
use super::unify_key::replace_if_possible;
|
use super::unify_key::replace_if_possible;
|
||||||
use super::unify_key::{ConstVarValue, ConstVariableValue};
|
use super::unify_key::{ConstVarValue, ConstVariableValue};
|
||||||
use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||||
|
use super::{equate::Equate, type_variable::Diverging};
|
||||||
use super::{InferCtxt, MiscVariable, TypeTrace};
|
use super::{InferCtxt, MiscVariable, TypeTrace};
|
||||||
|
|
||||||
use crate::traits::{Obligation, PredicateObligations};
|
use crate::traits::{Obligation, PredicateObligations};
|
||||||
|
@ -643,7 +643,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.type_variables()
|
.type_variables()
|
||||||
.new_var(self.for_universe, false, origin);
|
.new_var(self.for_universe, Diverging::NotDiverging, origin);
|
||||||
let u = self.tcx().mk_ty_var(new_var_id);
|
let u = self.tcx().mk_ty_var(new_var_id);
|
||||||
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
|
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
|
||||||
Ok(u)
|
Ok(u)
|
||||||
|
@ -881,7 +881,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
|
||||||
*self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
|
*self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
|
||||||
let new_var_id = self.infcx.inner.borrow_mut().type_variables().new_var(
|
let new_var_id = self.infcx.inner.borrow_mut().type_variables().new_var(
|
||||||
self.for_universe,
|
self.for_universe,
|
||||||
false,
|
Diverging::NotDiverging,
|
||||||
origin,
|
origin,
|
||||||
);
|
);
|
||||||
let u = self.tcx().mk_ty_var(new_var_id);
|
let u = self.tcx().mk_ty_var(new_var_id);
|
||||||
|
|
|
@ -46,7 +46,7 @@ use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, Veri
|
||||||
use self::region_constraints::{
|
use self::region_constraints::{
|
||||||
RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot,
|
RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot,
|
||||||
};
|
};
|
||||||
use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use self::type_variable::{Diverging, TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
|
|
||||||
pub mod at;
|
pub mod at;
|
||||||
pub mod canonical;
|
pub mod canonical;
|
||||||
|
@ -679,10 +679,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
t.fold_with(&mut self.freshener())
|
t.fold_with(&mut self.freshener())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> bool {
|
pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> Diverging {
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
ty::Infer(ty::TyVar(vid)) => self.inner.borrow_mut().type_variables().var_diverges(vid),
|
ty::Infer(ty::TyVar(vid)) => self.inner.borrow_mut().type_variables().var_diverges(vid),
|
||||||
_ => false,
|
_ => Diverging::NotDiverging,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1020,12 +1020,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
|
pub fn next_ty_var_id(&self, diverging: Diverging, origin: TypeVariableOrigin) -> TyVid {
|
||||||
self.inner.borrow_mut().type_variables().new_var(self.universe(), diverging, origin)
|
self.inner.borrow_mut().type_variables().new_var(self.universe(), diverging, origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
||||||
self.tcx.mk_ty_var(self.next_ty_var_id(false, origin))
|
self.tcx.mk_ty_var(self.next_ty_var_id(Diverging::NotDiverging, origin))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_ty_var_in_universe(
|
pub fn next_ty_var_in_universe(
|
||||||
|
@ -1033,12 +1033,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
origin: TypeVariableOrigin,
|
origin: TypeVariableOrigin,
|
||||||
universe: ty::UniverseIndex,
|
universe: ty::UniverseIndex,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let vid = self.inner.borrow_mut().type_variables().new_var(universe, false, origin);
|
let vid = self.inner.borrow_mut().type_variables().new_var(
|
||||||
|
universe,
|
||||||
|
Diverging::NotDiverging,
|
||||||
|
origin,
|
||||||
|
);
|
||||||
self.tcx.mk_ty_var(vid)
|
self.tcx.mk_ty_var(vid)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
|
||||||
self.tcx.mk_ty_var(self.next_ty_var_id(true, origin))
|
self.tcx.mk_ty_var(self.next_ty_var_id(Diverging::Diverges, origin))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_const_var(
|
pub fn next_const_var(
|
||||||
|
@ -1152,7 +1156,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
// as the substitutions for the default, `(T, U)`.
|
// as the substitutions for the default, `(T, U)`.
|
||||||
let ty_var_id = self.inner.borrow_mut().type_variables().new_var(
|
let ty_var_id = self.inner.borrow_mut().type_variables().new_var(
|
||||||
self.universe(),
|
self.universe(),
|
||||||
false,
|
Diverging::NotDiverging,
|
||||||
TypeVariableOrigin {
|
TypeVariableOrigin {
|
||||||
kind: TypeVariableOriginKind::TypeParameterDefinition(
|
kind: TypeVariableOriginKind::TypeParameterDefinition(
|
||||||
param.name,
|
param.name,
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
//! constituents)
|
//! constituents)
|
||||||
|
|
||||||
use crate::infer::combine::ConstEquateRelation;
|
use crate::infer::combine::ConstEquateRelation;
|
||||||
|
use crate::infer::type_variable::Diverging;
|
||||||
use crate::infer::InferCtxt;
|
use crate::infer::InferCtxt;
|
||||||
use crate::infer::{ConstVarValue, ConstVariableValue};
|
use crate::infer::{ConstVarValue, ConstVariableValue};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -920,7 +921,8 @@ where
|
||||||
// Replacing with a new variable in the universe `self.universe`,
|
// Replacing with a new variable in the universe `self.universe`,
|
||||||
// it will be unified later with the original type variable in
|
// it will be unified later with the original type variable in
|
||||||
// the universe `_universe`.
|
// the universe `_universe`.
|
||||||
let new_var_id = variables.new_var(self.universe, false, origin);
|
let new_var_id =
|
||||||
|
variables.new_var(self.universe, Diverging::NotDiverging, origin);
|
||||||
|
|
||||||
let u = self.tcx().mk_ty_var(new_var_id);
|
let u = self.tcx().mk_ty_var(new_var_id);
|
||||||
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
|
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
|
||||||
|
|
|
@ -119,7 +119,13 @@ pub enum TypeVariableOriginKind {
|
||||||
|
|
||||||
pub(crate) struct TypeVariableData {
|
pub(crate) struct TypeVariableData {
|
||||||
origin: TypeVariableOrigin,
|
origin: TypeVariableOrigin,
|
||||||
diverging: bool,
|
diverging: Diverging,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub enum Diverging {
|
||||||
|
NotDiverging,
|
||||||
|
Diverges,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -173,7 +179,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||||
///
|
///
|
||||||
/// Note that this function does not return care whether
|
/// Note that this function does not return care whether
|
||||||
/// `vid` has been unified with something else or not.
|
/// `vid` has been unified with something else or not.
|
||||||
pub fn var_diverges(&self, vid: ty::TyVid) -> bool {
|
pub fn var_diverges(&self, vid: ty::TyVid) -> Diverging {
|
||||||
self.storage.values.get(vid.index as usize).diverging
|
self.storage.values.get(vid.index as usize).diverging
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +244,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
||||||
pub fn new_var(
|
pub fn new_var(
|
||||||
&mut self,
|
&mut self,
|
||||||
universe: ty::UniverseIndex,
|
universe: ty::UniverseIndex,
|
||||||
diverging: bool,
|
diverging: Diverging,
|
||||||
origin: TypeVariableOrigin,
|
origin: TypeVariableOrigin,
|
||||||
) -> ty::TyVid {
|
) -> ty::TyVid {
|
||||||
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
|
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
|
||||||
|
|
|
@ -17,6 +17,7 @@ use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{ExprKind, GenericArg, Node, QPath, TyKind};
|
use rustc_hir::{ExprKind, GenericArg, Node, QPath, TyKind};
|
||||||
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
|
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
|
||||||
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
|
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
|
||||||
|
use rustc_infer::infer::type_variable::Diverging;
|
||||||
use rustc_infer::infer::{InferOk, InferResult};
|
use rustc_infer::infer::{InferOk, InferResult};
|
||||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
||||||
use rustc_middle::ty::fold::TypeFoldable;
|
use rustc_middle::ty::fold::TypeFoldable;
|
||||||
|
@ -656,56 +657,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
_ if self.is_tainted_by_errors() => self.tcx().ty_error(),
|
_ if self.is_tainted_by_errors() => self.tcx().ty_error(),
|
||||||
UnconstrainedInt => self.tcx.types.i32,
|
UnconstrainedInt => self.tcx.types.i32,
|
||||||
UnconstrainedFloat => self.tcx.types.f64,
|
UnconstrainedFloat => self.tcx.types.f64,
|
||||||
Neither if self.type_var_diverges(ty) => self.tcx.mk_diverging_default(),
|
Neither => match self.type_var_diverges(ty) {
|
||||||
Neither => {
|
Diverging::Diverges => self.tcx.mk_diverging_default(),
|
||||||
// This type variable was created from the instantiation of an opaque
|
|
||||||
// type. The fact that we're attempting to perform fallback for it
|
Diverging::NotDiverging => {
|
||||||
// means that the function neither constrained it to a concrete
|
// This type variable was created from the instantiation of an opaque
|
||||||
// type, nor to the opaque type itself.
|
// type. The fact that we're attempting to perform fallback for it
|
||||||
//
|
// means that the function neither constrained it to a concrete
|
||||||
// For example, in this code:
|
// type, nor to the opaque type itself.
|
||||||
//
|
//
|
||||||
//```
|
// For example, in this code:
|
||||||
// type MyType = impl Copy;
|
//
|
||||||
// fn defining_use() -> MyType { true }
|
//```
|
||||||
// fn other_use() -> MyType { defining_use() }
|
// type MyType = impl Copy;
|
||||||
// ```
|
// fn defining_use() -> MyType { true }
|
||||||
//
|
// fn other_use() -> MyType { defining_use() }
|
||||||
// `defining_use` will constrain the instantiated inference
|
// ```
|
||||||
// variable to `bool`, while `other_use` will constrain
|
//
|
||||||
// the instantiated inference variable to `MyType`.
|
// `defining_use` will constrain the instantiated inference
|
||||||
//
|
// variable to `bool`, while `other_use` will constrain
|
||||||
// When we process opaque types during writeback, we
|
// the instantiated inference variable to `MyType`.
|
||||||
// will handle cases like `other_use`, and not count
|
//
|
||||||
// them as defining usages
|
// When we process opaque types during writeback, we
|
||||||
//
|
// will handle cases like `other_use`, and not count
|
||||||
// However, we also need to handle cases like this:
|
// them as defining usages
|
||||||
//
|
//
|
||||||
// ```rust
|
// However, we also need to handle cases like this:
|
||||||
// pub type Foo = impl Copy;
|
//
|
||||||
// fn produce() -> Option<Foo> {
|
// ```rust
|
||||||
// None
|
// pub type Foo = impl Copy;
|
||||||
// }
|
// fn produce() -> Option<Foo> {
|
||||||
// ```
|
// None
|
||||||
//
|
// }
|
||||||
// In the above snippet, the inference variable created by
|
// ```
|
||||||
// instantiating `Option<Foo>` will be completely unconstrained.
|
//
|
||||||
// We treat this as a non-defining use by making the inference
|
// In the above snippet, the inference variable created by
|
||||||
// variable fall back to the opaque type itself.
|
// instantiating `Option<Foo>` will be completely unconstrained.
|
||||||
if let FallbackMode::All = mode {
|
// We treat this as a non-defining use by making the inference
|
||||||
if let Some(opaque_ty) = self.infcx.inner.borrow().opaque_types_vars.get(ty) {
|
// variable fall back to the opaque type itself.
|
||||||
debug!(
|
if let FallbackMode::All = mode {
|
||||||
"fallback_if_possible: falling back opaque type var {:?} to {:?}",
|
if let Some(opaque_ty) = self.infcx.inner.borrow().opaque_types_vars.get(ty)
|
||||||
ty, opaque_ty
|
{
|
||||||
);
|
debug!(
|
||||||
*opaque_ty
|
"fallback_if_possible: falling back opaque type var {:?} to {:?}",
|
||||||
|
ty, opaque_ty
|
||||||
|
);
|
||||||
|
*opaque_ty
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
debug!("fallback_if_possible: defaulting `{:?}` to `{:?}`", ty, fallback);
|
debug!("fallback_if_possible: defaulting `{:?}` to `{:?}`", ty, fallback);
|
||||||
self.demand_eqtype(rustc_span::DUMMY_SP, ty, fallback);
|
self.demand_eqtype(rustc_span::DUMMY_SP, ty, fallback);
|
||||||
|
|
Loading…
Reference in a new issue