use super::{InferCtxt, FixupError, FixupResult, Span, type_variable::TypeVariableOrigin};
-use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
+use crate::mir::interpret::ConstValue;
+use crate::ty::{self, Ty, Const, TyCtxt, TypeFoldable, InferConst, TypeFlags};
use crate::ty::fold::{TypeFolder, TypeVisitor};
///////////////////////////////////////////////////////////////////////////
-// OPPORTUNISTIC TYPE RESOLVER
+// OPPORTUNISTIC VAR RESOLVER
-/// The opportunistic type resolver can be used at any time. It simply replaces
-/// type variables that have been unified with the things they have
+/// The opportunistic resolver can be used at any time. It simply replaces
+/// type/const variables that have been unified with the things they have
/// been unified with (similar to `shallow_resolve`, but deep). This is
/// useful for printing messages etc but also required at various
/// points for correctness.
-pub struct OpportunisticTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+pub struct OpportunisticVarResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
}
-impl<'a, 'gcx, 'tcx> OpportunisticTypeResolver<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> OpportunisticVarResolver<'a, 'gcx, 'tcx> {
#[inline]
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
- OpportunisticTypeResolver { infcx }
+ OpportunisticVarResolver { infcx }
}
}
-impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeResolver<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticVarResolver<'a, 'gcx, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
self.infcx.tcx
}
if !t.has_infer_types() {
t // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
- let t0 = self.infcx.shallow_resolve(t);
- t0.super_fold_with(self)
+ let t = self.infcx.shallow_resolve(t);
+ t.super_fold_with(self)
+ }
+ }
+
+ fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> {
+ if !ct.has_type_flags(TypeFlags::HAS_CT_INFER) {
+ ct // micro-optimize -- if there is nothing in this const that this fold affects...
+ } else {
+ let ct = self.infcx.shallow_resolve(ct);
+ ct.super_fold_with(self)
}
}
}
r,
}
}
+
+ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+ if !ct.needs_infer() {
+ ct // micro-optimize -- if there is nothing in this const that this fold affects...
+ } else {
+ let c0 = self.infcx.shallow_resolve(ct);
+ c0.super_fold_with(self)
+ }
+ }
}
///////////////////////////////////////////////////////////////////////////
/// their concrete results. If any variable cannot be replaced (never unified, etc)
/// then an `Err` result is returned.
pub fn fully_resolve<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
- value: &T) -> FixupResult<T>
+ value: &T) -> FixupResult<'tcx, T>
where T : TypeFoldable<'tcx>
{
let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
// `err` field is not enforcable otherwise.
struct FullTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- err: Option<FixupError>,
+ err: Option<FixupError<'tcx>>,
}
impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx> {
_ => r,
}
}
+
+ fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+ if !c.needs_infer() && !ty::keep_local(&c) {
+ c // micro-optimize -- if there is nothing in this const that this fold affects...
+ // ^ we need to have the `keep_local` check to un-default
+ // defaulted tuples.
+ } else {
+ let c = self.infcx.shallow_resolve(c);
+ match c.val {
+ ConstValue::Infer(InferConst::Var(vid)) => {
+ self.err = Some(FixupError::UnresolvedConst(vid));
+ return self.tcx().consts.err;
+ }
+ ConstValue::Infer(InferConst::Fresh(_)) => {
+ bug!("Unexpected const in full const resolver: {:?}", c);
+ }
+ _ => {}
+ }
+ c.super_fold_with(self)
+ }
+ }
}