Skip to content

Commit 692a931

Browse files
committed
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.
1 parent 5d2a60c commit 692a931

File tree

14 files changed

+146
-38
lines changed

14 files changed

+146
-38
lines changed

src/librustc/ich/impls_mir.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,8 @@ for mir::StatementKind<'gcx> {
277277
op.hash_stable(hcx, hasher);
278278
places.hash_stable(hcx, hasher);
279279
}
280-
mir::StatementKind::UserAssertTy(ref ty, ref local) => {
281-
ty.hash_stable(hcx, hasher);
280+
mir::StatementKind::UserAssertTy(ref c_ty, ref local) => {
281+
c_ty.hash_stable(hcx, hasher);
282282
local.hash_stable(hcx, hasher);
283283
}
284284
mir::StatementKind::Nop => {}

src/librustc/infer/canonical.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
3434
use infer::{InferCtxt, InferOk, InferResult, RegionVariableOrigin, TypeVariableOrigin};
3535
use rustc_data_structures::indexed_vec::Idx;
36+
use serialize::UseSpecializedDecodable;
3637
use std::fmt::Debug;
3738
use std::ops::Index;
3839
use syntax::codemap::Span;
@@ -49,14 +50,16 @@ use rustc_data_structures::fx::FxHashMap;
4950
/// A "canonicalized" type `V` is one where all free inference
5051
/// variables have been rewriten to "canonical vars". These are
5152
/// numbered starting from 0 in order of first appearance.
52-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
53+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
5354
pub struct Canonical<'gcx, V> {
5455
pub variables: CanonicalVarInfos<'gcx>,
5556
pub value: V,
5657
}
5758

5859
pub type CanonicalVarInfos<'gcx> = &'gcx Slice<CanonicalVarInfo>;
5960

61+
impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> { }
62+
6063
/// A set of values corresponding to the canonical variables from some
6164
/// `Canonical`. You can give these values to
6265
/// `canonical_value.substitute` to substitute them into the canonical
@@ -69,7 +72,7 @@ pub type CanonicalVarInfos<'gcx> = &'gcx Slice<CanonicalVarInfo>;
6972
/// You can also use `infcx.fresh_inference_vars_for_canonical_vars`
7073
/// to get back a `CanonicalVarValues` containing fresh inference
7174
/// variables.
72-
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
75+
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
7376
pub struct CanonicalVarValues<'tcx> {
7477
pub var_values: IndexVec<CanonicalVar, Kind<'tcx>>,
7578
}
@@ -78,15 +81,15 @@ pub struct CanonicalVarValues<'tcx> {
7881
/// canonical value. This is sufficient information for code to create
7982
/// a copy of the canonical value in some other inference context,
8083
/// with fresh inference variables replacing the canonical values.
81-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
84+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
8285
pub struct CanonicalVarInfo {
8386
pub kind: CanonicalVarKind,
8487
}
8588

8689
/// Describes the "kind" of the canonical variable. This is a "kind"
8790
/// in the type-theory sense of the term -- i.e., a "meta" type system
8891
/// that analyzes type-like values.
89-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
92+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
9093
pub enum CanonicalVarKind {
9194
/// Some kind of type inference variable.
9295
Ty(CanonicalTyVarKind),
@@ -100,7 +103,7 @@ pub enum CanonicalVarKind {
100103
/// 22.) can only be instantiated with integral/float types (e.g.,
101104
/// usize or f32). In order to faithfully reproduce a type, we need to
102105
/// know what set of types a given type variable can be unified with.
103-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
106+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
104107
pub enum CanonicalTyVarKind {
105108
/// General type variable `?T` that can be unified with arbitrary types.
106109
General,
@@ -855,11 +858,14 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g
855858
}
856859

857860
CloneTypeFoldableAndLiftImpls! {
861+
::infer::canonical::Certainty,
862+
::infer::canonical::CanonicalVarInfo,
863+
::infer::canonical::CanonicalVarKind,
864+
}
865+
866+
CloneTypeFoldableImpls! {
858867
for <'tcx> {
859-
::infer::canonical::Certainty,
860-
::infer::canonical::CanonicalVarInfo,
861868
::infer::canonical::CanonicalVarInfos<'tcx>,
862-
::infer::canonical::CanonicalVarKind,
863869
}
864870
}
865871

@@ -870,6 +876,13 @@ BraceStructTypeFoldableImpl! {
870876
} where C: TypeFoldable<'tcx>
871877
}
872878

879+
BraceStructLiftImpl! {
880+
impl<'a, 'tcx, T> Lift<'tcx> for Canonical<'a, T> {
881+
type Lifted = Canonical<'tcx, T::Lifted>;
882+
variables, value
883+
} where T: Lift<'tcx>
884+
}
885+
873886
impl<'tcx> CanonicalVarValues<'tcx> {
874887
fn iter<'a>(&'a self) -> impl Iterator<Item = Kind<'tcx>> + 'a {
875888
self.var_values.iter().cloned()

src/librustc/mir/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use hir::def_id::DefId;
2727
use mir::visit::MirVisitable;
2828
use mir::interpret::{Value, PrimVal};
2929
use ty::subst::{Subst, Substs};
30-
use ty::{self, AdtDef, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
30+
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
3131
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
3232
use ty::TypeAndMut;
3333
use util::ppaux;
@@ -1260,7 +1260,7 @@ pub enum StatementKind<'tcx> {
12601260
///
12611261
/// Here we would insert a `UserAssertTy<(T, U)>(y)` instruction to check that the type of `y`
12621262
/// is the right thing.
1263-
UserAssertTy(Ty<'tcx>, Local),
1263+
UserAssertTy(CanonicalTy<'tcx>, Local),
12641264

12651265
/// No-op. Useful for deleting instructions without affecting statement indices.
12661266
Nop,
@@ -1333,7 +1333,8 @@ impl<'tcx> Debug for Statement<'tcx> {
13331333
InlineAsm { ref asm, ref outputs, ref inputs } => {
13341334
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
13351335
},
1336-
UserAssertTy(ref ty, ref local) => write!(fmt, "UserAssertTy({:?}, {:?})", ty, local),
1336+
UserAssertTy(ref c_ty, ref local) => write!(fmt, "UserAssertTy({:?}, {:?})",
1337+
c_ty, local),
13371338
Nop => write!(fmt, "nop"),
13381339
}
13391340
}

src/librustc/mir/visit.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use hir::def_id::DefId;
1212
use ty::subst::Substs;
13-
use ty::{ClosureSubsts, Region, Ty, GeneratorInterior};
13+
use ty::{CanonicalTy, ClosureSubsts, Region, Ty, GeneratorInterior};
1414
use mir::*;
1515
use syntax_pos::Span;
1616

@@ -145,10 +145,10 @@ macro_rules! make_mir_visitor {
145145
}
146146

147147
fn visit_user_assert_ty(&mut self,
148-
ty: & $($mutability)* Ty<'tcx>,
148+
c_ty: & $($mutability)* CanonicalTy<'tcx>,
149149
local: & $($mutability)* Local,
150150
location: Location) {
151-
self.super_user_assert_ty(ty, local, location);
151+
self.super_user_assert_ty(c_ty, local, location);
152152
}
153153

154154
fn visit_place(&mut self,
@@ -383,9 +383,9 @@ macro_rules! make_mir_visitor {
383383
self.visit_operand(input, location);
384384
}
385385
}
386-
StatementKind::UserAssertTy(ref $($mutability)* ty,
386+
StatementKind::UserAssertTy(ref $($mutability)* c_ty,
387387
ref $($mutability)* local) => {
388-
self.visit_user_assert_ty(ty, local, location);
388+
self.visit_user_assert_ty(c_ty, local, location);
389389
}
390390
StatementKind::Nop => {}
391391
}
@@ -631,10 +631,9 @@ macro_rules! make_mir_visitor {
631631
}
632632

633633
fn super_user_assert_ty(&mut self,
634-
ty: & $($mutability)* Ty<'tcx>,
634+
_c_ty: & $($mutability)* CanonicalTy<'tcx>,
635635
local: & $($mutability)* Local,
636636
location: Location) {
637-
self.visit_ty(ty, TyContext::Location(location));
638637
self.visit_local(local, PlaceContext::Validate, location);
639638
}
640639

src/librustc/ty/context.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use ty::layout::{LayoutDetails, TargetDataLayout};
4848
use ty::maps;
4949
use ty::steal::Steal;
5050
use ty::BindingMode;
51+
use ty::CanonicalTy;
5152
use util::nodemap::{NodeMap, DefIdSet, ItemLocalMap};
5253
use util::nodemap::{FxHashMap, FxHashSet};
5354
use rustc_data_structures::accumulate_vec::AccumulateVec;
@@ -344,6 +345,9 @@ pub struct TypeckTables<'tcx> {
344345
/// method calls, including those of overloaded operators.
345346
type_dependent_defs: ItemLocalMap<Def>,
346347

348+
/// Stores the canonicalized types provided by the user.
349+
user_provided_tys: ItemLocalMap<CanonicalTy<'tcx>>,
350+
347351
/// Stores the types for various nodes in the AST. Note that this table
348352
/// is not guaranteed to be populated until after typeck. See
349353
/// typeck::check::fn_ctxt for details.
@@ -420,6 +424,7 @@ impl<'tcx> TypeckTables<'tcx> {
420424
TypeckTables {
421425
local_id_root,
422426
type_dependent_defs: ItemLocalMap(),
427+
user_provided_tys: ItemLocalMap(),
423428
node_types: ItemLocalMap(),
424429
node_substs: ItemLocalMap(),
425430
adjustments: ItemLocalMap(),
@@ -461,6 +466,20 @@ impl<'tcx> TypeckTables<'tcx> {
461466
}
462467
}
463468

469+
pub fn user_provided_tys(&self) -> LocalTableInContext<CanonicalTy<'tcx>> {
470+
LocalTableInContext {
471+
local_id_root: self.local_id_root,
472+
data: &self.user_provided_tys
473+
}
474+
}
475+
476+
pub fn user_provided_tys_mut(&mut self) -> LocalTableInContextMut<CanonicalTy<'tcx>> {
477+
LocalTableInContextMut {
478+
local_id_root: self.local_id_root,
479+
data: &mut self.user_provided_tys
480+
}
481+
}
482+
464483
pub fn node_types(&self) -> LocalTableInContext<Ty<'tcx>> {
465484
LocalTableInContext {
466485
local_id_root: self.local_id_root,
@@ -685,6 +704,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
685704
let ty::TypeckTables {
686705
local_id_root,
687706
ref type_dependent_defs,
707+
ref user_provided_tys,
688708
ref node_types,
689709
ref node_substs,
690710
ref adjustments,
@@ -704,6 +724,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
704724

705725
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
706726
type_dependent_defs.hash_stable(hcx, hasher);
727+
user_provided_tys.hash_stable(hcx, hasher);
707728
node_types.hash_stable(hcx, hasher);
708729
node_substs.hash_stable(hcx, hasher);
709730
adjustments.hash_stable(hcx, hasher);
@@ -1635,6 +1656,24 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Predicate<'a>> {
16351656
}
16361657
}
16371658

1659+
impl<'a, 'tcx> Lift<'tcx> for &'a Slice<CanonicalVarInfo> {
1660+
type Lifted = &'tcx Slice<CanonicalVarInfo>;
1661+
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
1662+
if self.len() == 0 {
1663+
return Some(Slice::empty());
1664+
}
1665+
if tcx.interners.arena.in_arena(*self as *const _) {
1666+
return Some(unsafe { mem::transmute(*self) });
1667+
}
1668+
// Also try in the global tcx if we're not that.
1669+
if !tcx.is_global() {
1670+
self.lift_to_tcx(tcx.global_tcx())
1671+
} else {
1672+
None
1673+
}
1674+
}
1675+
}
1676+
16381677
pub mod tls {
16391678
use super::{CtxtInterners, GlobalCtxt, TyCtxt};
16401679

src/librustc/ty/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use hir::map::DefPathData;
2121
use hir::svh::Svh;
2222
use ich::Fingerprint;
2323
use ich::StableHashingContext;
24+
use infer::canonical::{Canonical, Canonicalize};
2425
use middle::const_val::ConstVal;
2526
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
2627
use middle::privacy::AccessLevels;
@@ -554,6 +555,17 @@ pub type Ty<'tcx> = &'tcx TyS<'tcx>;
554555
impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {}
555556
impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {}
556557

558+
pub type CanonicalTy<'gcx> = Canonical<'gcx, Ty<'gcx>>;
559+
560+
impl <'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for Ty<'tcx> {
561+
type Canonicalized = CanonicalTy<'gcx>;
562+
563+
fn intern(_gcx: TyCtxt<'_, 'gcx, 'gcx>,
564+
value: Canonical<'gcx, Self::Lifted>) -> Self::Canonicalized {
565+
value
566+
}
567+
}
568+
557569
/// A wrapper for slices with the additional invariant
558570
/// that the slice is interned and no other slice with
559571
/// the same contents can exist in the same context.

src/librustc_mir/borrow_check/nll/constraint_generation.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc::mir::Place::Projection;
1515
use rustc::mir::{Local, PlaceProjection, ProjectionElem};
1616
use rustc::mir::visit::TyContext;
1717
use rustc::infer::InferCtxt;
18-
use rustc::ty::{self, ClosureSubsts, Ty};
18+
use rustc::ty::{self, CanonicalTy, ClosureSubsts};
1919
use rustc::ty::subst::Substs;
2020
use rustc::ty::fold::TypeFoldable;
2121

@@ -107,7 +107,8 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
107107
self.super_rvalue(rvalue, location);
108108
}
109109

110-
fn visit_user_assert_ty(&mut self, _ty: &Ty<'tcx>, _local: &Local, _location: Location) { }
110+
fn visit_user_assert_ty(&mut self, _c_ty: &CanonicalTy<'tcx>,
111+
_local: &Local, _location: Location) { }
111112
}
112113

113114
impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {

src/librustc_mir/borrow_check/nll/renumber.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use rustc::ty::subst::Substs;
12-
use rustc::ty::{self, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable};
12+
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable};
1313
use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind};
1414
use rustc::mir::visit::{MutVisitor, TyContext};
1515
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
@@ -118,7 +118,7 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
118118
debug!("visit_closure_substs: substs={:?}", substs);
119119
}
120120

121-
fn visit_user_assert_ty(&mut self, _ty: &mut Ty<'tcx>, _local: &mut Local,
121+
fn visit_user_assert_ty(&mut self, _c_ty: &mut CanonicalTy<'tcx>, _local: &mut Local,
122122
_location: Location) {
123123
// User-assert-ty statements represent types that the user added explicitly.
124124
// We don't want to erase the regions from these types: rather, we want to

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -761,12 +761,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
761761
);
762762
};
763763
}
764-
StatementKind::UserAssertTy(ref ty, ref local) => {
764+
StatementKind::UserAssertTy(ref c_ty, ref local) => {
765765
let local_ty = mir.local_decls()[*local].ty;
766+
let (ty, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
767+
stmt.source_info.span, c_ty);
766768
debug!("check_stmt: user_assert_ty ty={:?} local_ty={:?}", ty, local_ty);
767-
if let Err(terr) =
768-
self.eq_types(ty, local_ty, location.at_self())
769-
{
769+
if let Err(terr) = self.eq_types(ty, local_ty, location.at_self()) {
770770
span_mirbug!(
771771
self,
772772
stmt,

src/librustc_mir/build/matches/mod.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
145145
end_block.unit()
146146
}
147147

148-
pub fn user_assert_ty(&mut self, block: BasicBlock, ty: Ty<'tcx>, var: NodeId, span: Span) {
148+
pub fn user_assert_ty(&mut self, block: BasicBlock, hir_id: hir::HirId,
149+
var: NodeId, span: Span) {
149150
let local_id = self.var_indices[&var];
150151
let source_info = self.source_info(span);
151-
self.cfg.push(block, Statement {
152-
source_info,
153-
kind: StatementKind::UserAssertTy(ty, local_id),
154-
});
152+
153+
debug!("user_assert_ty: local_id={:?}", hir_id.local_id);
154+
if let Some(c_ty) = self.hir.tables.user_provided_tys().get(hir_id) {
155+
debug!("user_assert_ty: c_ty={:?}", c_ty);
156+
self.cfg.push(block, Statement {
157+
source_info,
158+
kind: StatementKind::UserAssertTy(*c_ty, local_id),
159+
});
160+
}
155161
}
156162

157163
pub fn expr_into_pattern(&mut self,
158164
mut block: BasicBlock,
159-
ty: Option<Ty<'tcx>>,
165+
ty: Option<hir::HirId>,
160166
irrefutable_pat: Pattern<'tcx>,
161167
initializer: ExprRef<'tcx>)
162168
-> BlockAnd<()> {

src/librustc_mir/hair/cx/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
7676
first_statement_index: region::FirstStatementIndex::new(index),
7777
});
7878

79-
let ty = local.ty.clone().map(|ty| cx.tables().node_id_to_type(ty.hir_id));
79+
let ty = local.ty.clone().map(|ty| ty.hir_id);
8080
let pattern = cx.pattern_from_hir(&local.pat);
8181
result.push(StmtRef::Mirror(Box::new(Stmt {
8282
kind: StmtKind::Let {

src/librustc_mir/hair/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub enum StmtKind<'tcx> {
9797
pattern: Pattern<'tcx>,
9898

9999
/// let pat: <TY> = init ...
100-
ty: Option<Ty<'tcx>>,
100+
ty: Option<hir::HirId>,
101101

102102
/// let pat: ty = <INIT> ...
103103
initializer: Option<ExprRef<'tcx>>,

0 commit comments

Comments
 (0)