UserAssertTy can handle inference variables.
This commit modifies the UserAssertTy statement to take a canonicalized type rather than a regular type so that we can handle the case where the user provided type contains a inference variable.
This commit is contained in:
parent
5d2a60c57e
commit
692a931887
@ -277,8 +277,8 @@ for mir::StatementKind<'gcx> {
|
||||
op.hash_stable(hcx, hasher);
|
||||
places.hash_stable(hcx, hasher);
|
||||
}
|
||||
mir::StatementKind::UserAssertTy(ref ty, ref local) => {
|
||||
ty.hash_stable(hcx, hasher);
|
||||
mir::StatementKind::UserAssertTy(ref c_ty, ref local) => {
|
||||
c_ty.hash_stable(hcx, hasher);
|
||||
local.hash_stable(hcx, hasher);
|
||||
}
|
||||
mir::StatementKind::Nop => {}
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
use infer::{InferCtxt, InferOk, InferResult, RegionVariableOrigin, TypeVariableOrigin};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use serialize::UseSpecializedDecodable;
|
||||
use std::fmt::Debug;
|
||||
use std::ops::Index;
|
||||
use syntax::codemap::Span;
|
||||
@ -49,7 +50,7 @@ use rustc_data_structures::fx::FxHashMap;
|
||||
/// A "canonicalized" type `V` is one where all free inference
|
||||
/// variables have been rewriten to "canonical vars". These are
|
||||
/// numbered starting from 0 in order of first appearance.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
|
||||
pub struct Canonical<'gcx, V> {
|
||||
pub variables: CanonicalVarInfos<'gcx>,
|
||||
pub value: V,
|
||||
@ -57,6 +58,8 @@ pub struct Canonical<'gcx, V> {
|
||||
|
||||
pub type CanonicalVarInfos<'gcx> = &'gcx Slice<CanonicalVarInfo>;
|
||||
|
||||
impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> { }
|
||||
|
||||
/// A set of values corresponding to the canonical variables from some
|
||||
/// `Canonical`. You can give these values to
|
||||
/// `canonical_value.substitute` to substitute them into the canonical
|
||||
@ -69,7 +72,7 @@ pub type CanonicalVarInfos<'gcx> = &'gcx Slice<CanonicalVarInfo>;
|
||||
/// You can also use `infcx.fresh_inference_vars_for_canonical_vars`
|
||||
/// to get back a `CanonicalVarValues` containing fresh inference
|
||||
/// variables.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
|
||||
pub struct CanonicalVarValues<'tcx> {
|
||||
pub var_values: IndexVec<CanonicalVar, Kind<'tcx>>,
|
||||
}
|
||||
@ -78,7 +81,7 @@ pub struct CanonicalVarValues<'tcx> {
|
||||
/// canonical value. This is sufficient information for code to create
|
||||
/// a copy of the canonical value in some other inference context,
|
||||
/// with fresh inference variables replacing the canonical values.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
|
||||
pub struct CanonicalVarInfo {
|
||||
pub kind: CanonicalVarKind,
|
||||
}
|
||||
@ -86,7 +89,7 @@ pub struct CanonicalVarInfo {
|
||||
/// Describes the "kind" of the canonical variable. This is a "kind"
|
||||
/// in the type-theory sense of the term -- i.e., a "meta" type system
|
||||
/// that analyzes type-like values.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
|
||||
pub enum CanonicalVarKind {
|
||||
/// Some kind of type inference variable.
|
||||
Ty(CanonicalTyVarKind),
|
||||
@ -100,7 +103,7 @@ pub enum CanonicalVarKind {
|
||||
/// 22.) can only be instantiated with integral/float types (e.g.,
|
||||
/// usize or f32). In order to faithfully reproduce a type, we need to
|
||||
/// know what set of types a given type variable can be unified with.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
|
||||
pub enum CanonicalTyVarKind {
|
||||
/// General type variable `?T` that can be unified with arbitrary types.
|
||||
General,
|
||||
@ -855,11 +858,14 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g
|
||||
}
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! {
|
||||
::infer::canonical::Certainty,
|
||||
::infer::canonical::CanonicalVarInfo,
|
||||
::infer::canonical::CanonicalVarKind,
|
||||
}
|
||||
|
||||
CloneTypeFoldableImpls! {
|
||||
for <'tcx> {
|
||||
::infer::canonical::Certainty,
|
||||
::infer::canonical::CanonicalVarInfo,
|
||||
::infer::canonical::CanonicalVarInfos<'tcx>,
|
||||
::infer::canonical::CanonicalVarKind,
|
||||
}
|
||||
}
|
||||
|
||||
@ -870,6 +876,13 @@ BraceStructTypeFoldableImpl! {
|
||||
} where C: TypeFoldable<'tcx>
|
||||
}
|
||||
|
||||
BraceStructLiftImpl! {
|
||||
impl<'a, 'tcx, T> Lift<'tcx> for Canonical<'a, T> {
|
||||
type Lifted = Canonical<'tcx, T::Lifted>;
|
||||
variables, value
|
||||
} where T: Lift<'tcx>
|
||||
}
|
||||
|
||||
impl<'tcx> CanonicalVarValues<'tcx> {
|
||||
fn iter<'a>(&'a self) -> impl Iterator<Item = Kind<'tcx>> + 'a {
|
||||
self.var_values.iter().cloned()
|
||||
|
@ -27,7 +27,7 @@ use hir::def_id::DefId;
|
||||
use mir::visit::MirVisitable;
|
||||
use mir::interpret::{Value, PrimVal};
|
||||
use ty::subst::{Subst, Substs};
|
||||
use ty::{self, AdtDef, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
|
||||
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
|
||||
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use ty::TypeAndMut;
|
||||
use util::ppaux;
|
||||
@ -1260,7 +1260,7 @@ pub enum StatementKind<'tcx> {
|
||||
///
|
||||
/// Here we would insert a `UserAssertTy<(T, U)>(y)` instruction to check that the type of `y`
|
||||
/// is the right thing.
|
||||
UserAssertTy(Ty<'tcx>, Local),
|
||||
UserAssertTy(CanonicalTy<'tcx>, Local),
|
||||
|
||||
/// No-op. Useful for deleting instructions without affecting statement indices.
|
||||
Nop,
|
||||
@ -1333,7 +1333,8 @@ impl<'tcx> Debug for Statement<'tcx> {
|
||||
InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
|
||||
},
|
||||
UserAssertTy(ref ty, ref local) => write!(fmt, "UserAssertTy({:?}, {:?})", ty, local),
|
||||
UserAssertTy(ref c_ty, ref local) => write!(fmt, "UserAssertTy({:?}, {:?})",
|
||||
c_ty, local),
|
||||
Nop => write!(fmt, "nop"),
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use ty::subst::Substs;
|
||||
use ty::{ClosureSubsts, Region, Ty, GeneratorInterior};
|
||||
use ty::{CanonicalTy, ClosureSubsts, Region, Ty, GeneratorInterior};
|
||||
use mir::*;
|
||||
use syntax_pos::Span;
|
||||
|
||||
@ -145,10 +145,10 @@ macro_rules! make_mir_visitor {
|
||||
}
|
||||
|
||||
fn visit_user_assert_ty(&mut self,
|
||||
ty: & $($mutability)* Ty<'tcx>,
|
||||
c_ty: & $($mutability)* CanonicalTy<'tcx>,
|
||||
local: & $($mutability)* Local,
|
||||
location: Location) {
|
||||
self.super_user_assert_ty(ty, local, location);
|
||||
self.super_user_assert_ty(c_ty, local, location);
|
||||
}
|
||||
|
||||
fn visit_place(&mut self,
|
||||
@ -383,9 +383,9 @@ macro_rules! make_mir_visitor {
|
||||
self.visit_operand(input, location);
|
||||
}
|
||||
}
|
||||
StatementKind::UserAssertTy(ref $($mutability)* ty,
|
||||
StatementKind::UserAssertTy(ref $($mutability)* c_ty,
|
||||
ref $($mutability)* local) => {
|
||||
self.visit_user_assert_ty(ty, local, location);
|
||||
self.visit_user_assert_ty(c_ty, local, location);
|
||||
}
|
||||
StatementKind::Nop => {}
|
||||
}
|
||||
@ -631,10 +631,9 @@ macro_rules! make_mir_visitor {
|
||||
}
|
||||
|
||||
fn super_user_assert_ty(&mut self,
|
||||
ty: & $($mutability)* Ty<'tcx>,
|
||||
_c_ty: & $($mutability)* CanonicalTy<'tcx>,
|
||||
local: & $($mutability)* Local,
|
||||
location: Location) {
|
||||
self.visit_ty(ty, TyContext::Location(location));
|
||||
self.visit_local(local, PlaceContext::Validate, location);
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ use ty::layout::{LayoutDetails, TargetDataLayout};
|
||||
use ty::maps;
|
||||
use ty::steal::Steal;
|
||||
use ty::BindingMode;
|
||||
use ty::CanonicalTy;
|
||||
use util::nodemap::{NodeMap, DefIdSet, ItemLocalMap};
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::accumulate_vec::AccumulateVec;
|
||||
@ -344,6 +345,9 @@ pub struct TypeckTables<'tcx> {
|
||||
/// method calls, including those of overloaded operators.
|
||||
type_dependent_defs: ItemLocalMap<Def>,
|
||||
|
||||
/// Stores the canonicalized types provided by the user.
|
||||
user_provided_tys: ItemLocalMap<CanonicalTy<'tcx>>,
|
||||
|
||||
/// Stores the types for various nodes in the AST. Note that this table
|
||||
/// is not guaranteed to be populated until after typeck. See
|
||||
/// typeck::check::fn_ctxt for details.
|
||||
@ -420,6 +424,7 @@ impl<'tcx> TypeckTables<'tcx> {
|
||||
TypeckTables {
|
||||
local_id_root,
|
||||
type_dependent_defs: ItemLocalMap(),
|
||||
user_provided_tys: ItemLocalMap(),
|
||||
node_types: ItemLocalMap(),
|
||||
node_substs: ItemLocalMap(),
|
||||
adjustments: ItemLocalMap(),
|
||||
@ -461,6 +466,20 @@ impl<'tcx> TypeckTables<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn user_provided_tys(&self) -> LocalTableInContext<CanonicalTy<'tcx>> {
|
||||
LocalTableInContext {
|
||||
local_id_root: self.local_id_root,
|
||||
data: &self.user_provided_tys
|
||||
}
|
||||
}
|
||||
|
||||
pub fn user_provided_tys_mut(&mut self) -> LocalTableInContextMut<CanonicalTy<'tcx>> {
|
||||
LocalTableInContextMut {
|
||||
local_id_root: self.local_id_root,
|
||||
data: &mut self.user_provided_tys
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_types(&self) -> LocalTableInContext<Ty<'tcx>> {
|
||||
LocalTableInContext {
|
||||
local_id_root: self.local_id_root,
|
||||
@ -685,6 +704,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
|
||||
let ty::TypeckTables {
|
||||
local_id_root,
|
||||
ref type_dependent_defs,
|
||||
ref user_provided_tys,
|
||||
ref node_types,
|
||||
ref node_substs,
|
||||
ref adjustments,
|
||||
@ -704,6 +724,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
|
||||
|
||||
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
||||
type_dependent_defs.hash_stable(hcx, hasher);
|
||||
user_provided_tys.hash_stable(hcx, hasher);
|
||||
node_types.hash_stable(hcx, hasher);
|
||||
node_substs.hash_stable(hcx, hasher);
|
||||
adjustments.hash_stable(hcx, hasher);
|
||||
@ -1635,6 +1656,24 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Predicate<'a>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for &'a Slice<CanonicalVarInfo> {
|
||||
type Lifted = &'tcx Slice<CanonicalVarInfo>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
||||
if self.len() == 0 {
|
||||
return Some(Slice::empty());
|
||||
}
|
||||
if tcx.interners.arena.in_arena(*self as *const _) {
|
||||
return Some(unsafe { mem::transmute(*self) });
|
||||
}
|
||||
// Also try in the global tcx if we're not that.
|
||||
if !tcx.is_global() {
|
||||
self.lift_to_tcx(tcx.global_tcx())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod tls {
|
||||
use super::{CtxtInterners, GlobalCtxt, TyCtxt};
|
||||
|
||||
|
@ -21,6 +21,7 @@ use hir::map::DefPathData;
|
||||
use hir::svh::Svh;
|
||||
use ich::Fingerprint;
|
||||
use ich::StableHashingContext;
|
||||
use infer::canonical::{Canonical, Canonicalize};
|
||||
use middle::const_val::ConstVal;
|
||||
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
|
||||
use middle::privacy::AccessLevels;
|
||||
@ -554,6 +555,17 @@ pub type Ty<'tcx> = &'tcx TyS<'tcx>;
|
||||
impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {}
|
||||
impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {}
|
||||
|
||||
pub type CanonicalTy<'gcx> = Canonical<'gcx, Ty<'gcx>>;
|
||||
|
||||
impl <'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for Ty<'tcx> {
|
||||
type Canonicalized = CanonicalTy<'gcx>;
|
||||
|
||||
fn intern(_gcx: TyCtxt<'_, 'gcx, 'gcx>,
|
||||
value: Canonical<'gcx, Self::Lifted>) -> Self::Canonicalized {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper for slices with the additional invariant
|
||||
/// that the slice is interned and no other slice with
|
||||
/// the same contents can exist in the same context.
|
||||
|
@ -15,7 +15,7 @@ use rustc::mir::Place::Projection;
|
||||
use rustc::mir::{Local, PlaceProjection, ProjectionElem};
|
||||
use rustc::mir::visit::TyContext;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::ty::{self, ClosureSubsts, Ty};
|
||||
use rustc::ty::{self, CanonicalTy, ClosureSubsts};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
|
||||
@ -107,7 +107,8 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
|
||||
self.super_rvalue(rvalue, location);
|
||||
}
|
||||
|
||||
fn visit_user_assert_ty(&mut self, _ty: &Ty<'tcx>, _local: &Local, _location: Location) { }
|
||||
fn visit_user_assert_ty(&mut self, _c_ty: &CanonicalTy<'tcx>,
|
||||
_local: &Local, _location: Location) { }
|
||||
}
|
||||
|
||||
impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable};
|
||||
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable};
|
||||
use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind};
|
||||
use rustc::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
|
||||
@ -118,7 +118,7 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
|
||||
debug!("visit_closure_substs: substs={:?}", substs);
|
||||
}
|
||||
|
||||
fn visit_user_assert_ty(&mut self, _ty: &mut Ty<'tcx>, _local: &mut Local,
|
||||
fn visit_user_assert_ty(&mut self, _c_ty: &mut CanonicalTy<'tcx>, _local: &mut Local,
|
||||
_location: Location) {
|
||||
// User-assert-ty statements represent types that the user added explicitly.
|
||||
// We don't want to erase the regions from these types: rather, we want to
|
||||
|
@ -761,12 +761,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
);
|
||||
};
|
||||
}
|
||||
StatementKind::UserAssertTy(ref ty, ref local) => {
|
||||
StatementKind::UserAssertTy(ref c_ty, ref local) => {
|
||||
let local_ty = mir.local_decls()[*local].ty;
|
||||
let (ty, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
|
||||
stmt.source_info.span, c_ty);
|
||||
debug!("check_stmt: user_assert_ty ty={:?} local_ty={:?}", ty, local_ty);
|
||||
if let Err(terr) =
|
||||
self.eq_types(ty, local_ty, location.at_self())
|
||||
{
|
||||
if let Err(terr) = self.eq_types(ty, local_ty, location.at_self()) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
stmt,
|
||||
|
@ -145,18 +145,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
end_block.unit()
|
||||
}
|
||||
|
||||
pub fn user_assert_ty(&mut self, block: BasicBlock, ty: Ty<'tcx>, var: NodeId, span: Span) {
|
||||
pub fn user_assert_ty(&mut self, block: BasicBlock, hir_id: hir::HirId,
|
||||
var: NodeId, span: Span) {
|
||||
let local_id = self.var_indices[&var];
|
||||
let source_info = self.source_info(span);
|
||||
self.cfg.push(block, Statement {
|
||||
source_info,
|
||||
kind: StatementKind::UserAssertTy(ty, local_id),
|
||||
});
|
||||
|
||||
debug!("user_assert_ty: local_id={:?}", hir_id.local_id);
|
||||
if let Some(c_ty) = self.hir.tables.user_provided_tys().get(hir_id) {
|
||||
debug!("user_assert_ty: c_ty={:?}", c_ty);
|
||||
self.cfg.push(block, Statement {
|
||||
source_info,
|
||||
kind: StatementKind::UserAssertTy(*c_ty, local_id),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expr_into_pattern(&mut self,
|
||||
mut block: BasicBlock,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
ty: Option<hir::HirId>,
|
||||
irrefutable_pat: Pattern<'tcx>,
|
||||
initializer: ExprRef<'tcx>)
|
||||
-> BlockAnd<()> {
|
||||
|
@ -76,7 +76,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
first_statement_index: region::FirstStatementIndex::new(index),
|
||||
});
|
||||
|
||||
let ty = local.ty.clone().map(|ty| cx.tables().node_id_to_type(ty.hir_id));
|
||||
let ty = local.ty.clone().map(|ty| ty.hir_id);
|
||||
let pattern = cx.pattern_from_hir(&local.pat);
|
||||
result.push(StmtRef::Mirror(Box::new(Stmt {
|
||||
kind: StmtKind::Let {
|
||||
|
@ -97,7 +97,7 @@ pub enum StmtKind<'tcx> {
|
||||
pattern: Pattern<'tcx>,
|
||||
|
||||
/// let pat: <TY> = init ...
|
||||
ty: Option<Ty<'tcx>>,
|
||||
ty: Option<hir::HirId>,
|
||||
|
||||
/// let pat: ty = <INIT> ...
|
||||
initializer: Option<ExprRef<'tcx>>,
|
||||
|
@ -960,10 +960,19 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
|
||||
// Add explicitly-declared locals.
|
||||
fn visit_local(&mut self, local: &'gcx hir::Local) {
|
||||
let o_ty = match local.ty {
|
||||
Some(ref ty) => Some(self.fcx.to_ty(&ty)),
|
||||
None => None
|
||||
Some(ref ty) => {
|
||||
let o_ty = self.fcx.to_ty(&ty);
|
||||
|
||||
let (c_ty, _orig_values) = self.fcx.inh.infcx.canonicalize_query(&o_ty);
|
||||
debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty);
|
||||
self.fcx.tables.borrow_mut().user_provided_tys_mut().insert(ty.hir_id, c_ty);
|
||||
|
||||
Some(o_ty)
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
self.assign(local.span, local.id, o_ty);
|
||||
|
||||
debug!("Local variable {:?} is assigned type {}",
|
||||
local.pat,
|
||||
self.fcx.ty_to_string(
|
||||
|
@ -46,6 +46,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
wbcx.visit_anon_types();
|
||||
wbcx.visit_cast_types();
|
||||
wbcx.visit_free_region_map();
|
||||
wbcx.visit_user_provided_tys();
|
||||
|
||||
let used_trait_imports = mem::replace(
|
||||
&mut self.tables.borrow_mut().used_trait_imports,
|
||||
@ -341,6 +342,33 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
self.tables.free_region_map = free_region_map;
|
||||
}
|
||||
|
||||
fn visit_user_provided_tys(&mut self) {
|
||||
let fcx_tables = self.fcx.tables.borrow();
|
||||
debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
|
||||
let common_local_id_root = fcx_tables.local_id_root.unwrap();
|
||||
|
||||
for (&local_id, c_ty) in fcx_tables.user_provided_tys().iter() {
|
||||
let hir_id = hir::HirId {
|
||||
owner: common_local_id_root.index,
|
||||
local_id,
|
||||
};
|
||||
|
||||
let c_ty = if let Some(c_ty) = self.tcx().lift_to_global(c_ty) {
|
||||
c_ty
|
||||
} else {
|
||||
span_bug!(
|
||||
hir_id.to_span(&self.fcx.tcx),
|
||||
"writeback: `{:?}` missing from the global type context",
|
||||
c_ty
|
||||
);
|
||||
};
|
||||
|
||||
self.tables
|
||||
.user_provided_tys_mut()
|
||||
.insert(hir_id, c_ty.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_anon_types(&mut self) {
|
||||
let gcx = self.tcx().global_tcx();
|
||||
for (&def_id, anon_defn) in self.fcx.anon_types.borrow().iter() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user