Skip to content

Commit 3ca7c22

Browse files
committed
Stop writing directly to the final type/method/vtable sidetables from astconv
and from typeck, which is verboten. We are supposed to write inference results into the FnCtxt and then these get copied over in writeback. Add assertions that no inference by-products are added to this table. Fixes #3888 Fixes #4036 Fixes #4492
1 parent 6f2783d commit 3ca7c22

File tree

13 files changed

+137
-42
lines changed

13 files changed

+137
-42
lines changed

src/librustc/middle/trans/base.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,8 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
15811581
param_substs: Option<@param_substs>,
15821582
sp: Option<span>) -> fn_ctxt
15831583
{
1584+
for param_substs.each |p| { p.validate(); }
1585+
15841586
debug!("new_fn_ctxt_w_id(path=%s, id=%?, impl_id=%?, \
15851587
param_substs=%s",
15861588
path_str(ccx.sess, path),

src/librustc/middle/trans/callee.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ pub fn trans_fn_ref_with_vtables(
228228
vtables);
229229
let _indenter = indenter();
230230

231+
fail_unless!(type_params.all(|t| !ty::type_needs_infer(*t)));
232+
231233
// Polytype of the function item (may have type params)
232234
let fn_tpt = ty::lookup_item_type(tcx, def_id);
233235

src/librustc/middle/trans/common.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,13 @@ pub struct param_substs {
250250
self_ty: Option<ty::t>
251251
}
252252

253+
pub impl param_substs {
254+
fn validate(&self) {
255+
for self.tys.each |t| { fail_unless!(!ty::type_needs_infer(*t)); }
256+
for self.self_ty.each |t| { fail_unless!(!ty::type_needs_infer(*t)); }
257+
}
258+
}
259+
253260
pub fn param_substs_to_str(tcx: ty::ctxt, substs: &param_substs) -> ~str {
254261
fmt!("param_substs {tys:%?, vtables:%?, bounds:%?}",
255262
substs.tys.map(|t| ty_to_str(tcx, *t)),
@@ -1372,6 +1379,13 @@ pub fn expr_ty_adjusted(bcx: block, ex: @ast::expr) -> ty::t {
13721379
pub fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] {
13731380
let tcx = bcx.tcx();
13741381
let params = ty::node_id_to_type_params(tcx, id);
1382+
1383+
if !params.all(|t| !ty::type_needs_infer(*t)) {
1384+
bcx.sess().bug(
1385+
fmt!("Type parameters for node %d include inference types: %s",
1386+
id, str::connect(params.map(|t| bcx.ty_to_str(*t)), ",")));
1387+
}
1388+
13751389
match bcx.fcx.param_substs {
13761390
Some(substs) => {
13771391
do vec::map(params) |t| {

src/librustc/middle/trans/meth.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ pub fn trans_static_method_callee(bcx: block,
327327
328328
match vtbls[bound_index] {
329329
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
330+
fail_unless!(rcvr_substs.all(|t| !ty::type_needs_infer(*t)));
330331
331332
let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
332333
let callee_substs = combine_impl_and_methods_tps(

src/librustc/middle/trans/monomorphize.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
4747
impl_did_opt: Option<ast::def_id>,
4848
ref_id: Option<ast::node_id>) ->
4949
(ValueRef, bool) {
50+
fail_unless!(real_substs.all(|t| !ty::type_needs_infer(*t)));
5051
let _icx = ccx.insn_ctxt("monomorphic_fn");
5152
let mut must_cast = false;
5253
let substs = vec::map(real_substs, |t| {

src/librustc/middle/typeck/astconv.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use middle::ty::{ty_param_substs_and_ty};
6060
use middle::ty;
6161
use middle::typeck::rscope::{in_binding_rscope};
6262
use middle::typeck::rscope::{region_scope, type_rscope, RegionError};
63-
use middle::typeck::{CrateCtxt, write_substs_to_tcx, write_ty_to_tcx};
63+
use middle::typeck::{CrateCtxt};
6464

6565
use core::result;
6666
use core::vec;
@@ -186,19 +186,15 @@ pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
186186
self: &AC,
187187
rscope: &RS,
188188
did: ast::def_id,
189-
path: @ast::path,
190-
path_id: ast::node_id)
191-
-> ty_param_substs_and_ty {
189+
path: @ast::path)
190+
-> ty_param_substs_and_ty
191+
{
192192
// Look up the polytype of the item and then substitute the provided types
193193
// for any type/region parameters.
194-
let tcx = self.tcx();
195194
let ty::ty_param_substs_and_ty {
196195
substs: substs,
197196
ty: ty
198197
} = ast_path_to_substs_and_ty(self, rscope, did, path);
199-
write_ty_to_tcx(tcx, path_id, ty);
200-
write_substs_to_tcx(tcx, path_id, /*bad*/copy substs.tps);
201-
202198
ty_param_substs_and_ty { substs: substs, ty: ty }
203199
}
204200

@@ -368,7 +364,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
368364
};
369365
match a_def {
370366
ast::def_ty(did) | ast::def_struct(did) => {
371-
ast_path_to_ty(self, rscope, did, path, id).ty
367+
ast_path_to_ty(self, rscope, did, path).ty
372368
}
373369
ast::def_prim_ty(nty) => {
374370
match nty {

src/librustc/middle/typeck/check/mod.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ use middle::typeck::rscope::{RegionError};
104104
use middle::typeck::rscope::{in_binding_rscope, region_scope, type_rscope};
105105
use middle::typeck::rscope;
106106
use middle::typeck::{isr_alist, lookup_def_ccx, method_map_entry};
107+
use middle::typeck::{method_map, vtable_map};
107108
use middle::typeck::{method_origin, method_self, method_trait, no_params};
108109
use middle::typeck::{require_same_types};
109110
use util::common::{block_query, indenter, loop_query};
@@ -160,9 +161,13 @@ pub struct SelfInfo {
160161
pub struct inherited {
161162
infcx: @mut infer::InferCtxt,
162163
locals: HashMap<ast::node_id, ty::t>,
164+
165+
// Temporary tables:
163166
node_types: HashMap<ast::node_id, ty::t>,
164167
node_type_substs: HashMap<ast::node_id, ty::substs>,
165-
adjustments: HashMap<ast::node_id, @ty::AutoAdjustment>
168+
adjustments: HashMap<ast::node_id, @ty::AutoAdjustment>,
169+
method_map: method_map,
170+
vtable_map: vtable_map,
166171
}
167172

168173
pub enum FnKind {
@@ -220,7 +225,9 @@ pub fn blank_inherited(ccx: @mut CrateCtxt) -> @inherited {
220225
locals: HashMap(),
221226
node_types: oldmap::HashMap(),
222227
node_type_substs: oldmap::HashMap(),
223-
adjustments: oldmap::HashMap()
228+
adjustments: oldmap::HashMap(),
229+
method_map: oldmap::HashMap(),
230+
vtable_map: oldmap::HashMap(),
224231
}
225232
}
226233

@@ -1357,7 +1364,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
13571364
CheckTraitsAndInherentMethods,
13581365
AutoderefReceiver) {
13591366
Some(ref entry) => {
1360-
let method_map = fcx.ccx.method_map;
1367+
let method_map = fcx.inh.method_map;
13611368
method_map.insert(expr.id, (*entry));
13621369
}
13631370
None => {
@@ -1429,7 +1436,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
14291436
deref_args, CheckTraitsOnly, autoderef_receiver) {
14301437
Some(ref origin) => {
14311438
let method_ty = fcx.node_ty(op_ex.callee_id);
1432-
let method_map = fcx.ccx.method_map;
1439+
let method_map = fcx.inh.method_map;
14331440
method_map.insert(op_ex.id, *origin);
14341441
check_call_inner(fcx, op_ex.span,
14351442
op_ex.id, method_ty,

src/librustc/middle/typeck/check/regionck.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ pub fn visit_expr(expr: @ast::expr, &&rcx: @mut Rcx, v: rvt) {
215215
// `constrain_auto_ref()` on all exprs. But that causes a
216216
// lot of spurious errors because of how the region
217217
// hierarchy is setup.
218-
if rcx.fcx.ccx.method_map.contains_key(&callee.id) {
218+
if rcx.fcx.inh.method_map.contains_key(&callee.id) {
219219
match callee.node {
220220
ast::expr_field(base, _, _) => {
221221
constrain_auto_ref(rcx, base);
@@ -713,7 +713,7 @@ pub mod guarantor {
713713
ast::expr_repeat(*) |
714714
ast::expr_vec(*) => {
715715
fail_unless!(!ty::expr_is_lval(
716-
rcx.fcx.tcx(), rcx.fcx.ccx.method_map, expr));
716+
rcx.fcx.tcx(), rcx.fcx.inh.method_map, expr));
717717
None
718718
}
719719
}
@@ -765,7 +765,7 @@ pub mod guarantor {
765765
let _i = ::util::common::indenter();
766766

767767
let guarantor = {
768-
if rcx.fcx.ccx.method_map.contains_key(&expr.id) {
768+
if rcx.fcx.inh.method_map.contains_key(&expr.id) {
769769
None
770770
} else {
771771
guarantor(rcx, expr)

src/librustc/middle/typeck/check/vtable.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -486,13 +486,12 @@ pub fn connect_trait_tps(vcx: &VtableContext,
486486
}
487487
}
488488
489-
pub fn insert_vtables(ccx: @mut CrateCtxt,
489+
pub fn insert_vtables(fcx: @mut FnCtxt,
490490
callee_id: ast::node_id,
491491
vtables: vtable_res) {
492492
debug!("insert_vtables(callee_id=%d, vtables=%?)",
493-
callee_id, vtables.map(|v| v.to_str(ccx.tcx)));
494-
let vtable_map = ccx.vtable_map;
495-
vtable_map.insert(callee_id, vtables);
493+
callee_id, vtables.map(|v| v.to_str(fcx.tcx())));
494+
fcx.inh.vtable_map.insert(callee_id, vtables);
496495
}
497496
498497
pub fn location_info_for_expr(expr: @ast::expr) -> LocationInfo {
@@ -529,8 +528,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
529528
let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
530529
item_ty.bounds, substs, is_early);
531530
if !is_early {
532-
let vtable_map = cx.vtable_map;
533-
vtable_map.insert(ex.id, vtbls);
531+
insert_vtables(fcx, ex.id, vtbls);
534532
}
535533
}
536534
}
@@ -543,10 +541,10 @@ pub fn early_resolve_expr(ex: @ast::expr,
543541
}
544542
545543
// Must resolve bounds on methods with bounded params
546-
ast::expr_field(*) | ast::expr_binary(*) |
544+
ast::expr_binary(*) |
547545
ast::expr_unary(*) | ast::expr_assign_op(*) |
548546
ast::expr_index(*) | ast::expr_method_call(*) => {
549-
match ty::method_call_bounds(cx.tcx, cx.method_map, ex.id) {
547+
match ty::method_call_bounds(cx.tcx, fcx.inh.method_map, ex.id) {
550548
Some(bounds) => {
551549
if has_trait_bounds(/*bad*/copy *bounds) {
552550
let callee_id = match ex.node {
@@ -559,7 +557,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
559557
let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
560558
bounds, &substs, is_early);
561559
if !is_early {
562-
insert_vtables(cx, callee_id, vtbls);
560+
insert_vtables(fcx, callee_id, vtbls);
563561
}
564562
}
565563
}
@@ -599,10 +597,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
599597
// vtable (that is: "ex has vtable
600598
// <vtable>")
601599
if !is_early {
602-
let vtable_map =
603-
cx.vtable_map;
604-
vtable_map.insert(ex.id,
605-
@~[vtable]);
600+
insert_vtables(fcx, ex.id, @~[vtable]);
606601
}
607602
}
608603
None => {

src/librustc/middle/typeck/check/writeback.rs

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ use middle::typeck::check::{FnCtxt, SelfInfo};
2121
use middle::typeck::infer::{force_all, resolve_all, resolve_region};
2222
use middle::typeck::infer::{resolve_type};
2323
use middle::typeck::infer;
24-
use middle::typeck::method_map_entry;
24+
use middle::typeck::{method_map_entry};
25+
use middle::typeck::{vtable_origin, vtable_static, vtable_param};
2526
use middle::typeck::{vtable_param, write_substs_to_tcx};
2627
use middle::typeck::{write_ty_to_tcx};
2728
use util::ppaux;
@@ -51,21 +52,60 @@ fn resolve_type_vars_in_type(fcx: @mut FnCtxt, sp: span, typ: ty::t)
5152
}
5253
}
5354

55+
fn resolve_type_vars_in_types(fcx: @mut FnCtxt, sp: span, tys: &[ty::t])
56+
-> ~[ty::t] {
57+
tys.map(|t| {
58+
match resolve_type_vars_in_type(fcx, sp, *t) {
59+
Some(t1) => t1,
60+
None => ty::mk_err(fcx.ccx.tcx)
61+
}
62+
})
63+
}
64+
5465
fn resolve_method_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) {
5566
// Resolve any method map entry
56-
match fcx.ccx.method_map.find(&id) {
67+
match fcx.inh.method_map.find(&id) {
5768
None => {}
5869
Some(ref mme) => {
5970
for resolve_type_vars_in_type(fcx, sp, mme.self_arg.ty).each |t| {
6071
let method_map = fcx.ccx.method_map;
61-
method_map.insert(id,
62-
method_map_entry {
63-
self_arg: arg {
64-
mode: mme.self_arg.mode,
65-
ty: *t
66-
},
67-
.. *mme
68-
});
72+
let new_entry = method_map_entry {
73+
self_arg: arg {mode: mme.self_arg.mode, ty: *t },
74+
..*mme
75+
};
76+
debug!("writeback::resolve_method_map_entry(id=%?, \
77+
new_entry=%?)",
78+
id, new_entry);
79+
method_map.insert(id, new_entry);
80+
}
81+
}
82+
}
83+
}
84+
85+
fn resolve_vtable_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) {
86+
// Resolve any method map entry
87+
match fcx.inh.vtable_map.find(&id) {
88+
None => {}
89+
Some(origins) => {
90+
let r_origins = @origins.map(|o| resolve_origin(fcx, sp, o));
91+
let vtable_map = fcx.ccx.vtable_map;
92+
vtable_map.insert(id, r_origins);
93+
debug!("writeback::resolve_vtable_map_entry(id=%d, vtables=%?)",
94+
id, r_origins.map(|v| v.to_str(fcx.tcx())));
95+
}
96+
}
97+
98+
fn resolve_origin(fcx: @mut FnCtxt,
99+
sp: span,
100+
origin: &vtable_origin) -> vtable_origin {
101+
match origin {
102+
&vtable_static(def_id, ref tys, origins) => {
103+
let r_tys = resolve_type_vars_in_types(fcx, sp, *tys);
104+
let r_origins = @origins.map(|o| resolve_origin(fcx, sp, o));
105+
vtable_static(def_id, r_tys, r_origins)
106+
}
107+
&vtable_param(n, b) => {
108+
vtable_param(n, b)
69109
}
70110
}
71111
}
@@ -185,6 +225,8 @@ fn visit_expr(e: @ast::expr, &&wbcx: @mut WbCtxt, v: wb_vt) {
185225
resolve_type_vars_for_node(wbcx, e.span, e.id);
186226
resolve_method_map_entry(wbcx.fcx, e.span, e.id);
187227
resolve_method_map_entry(wbcx.fcx, e.span, e.callee_id);
228+
resolve_vtable_map_entry(wbcx.fcx, e.span, e.id);
229+
resolve_vtable_map_entry(wbcx.fcx, e.span, e.callee_id);
188230
match e.node {
189231
ast::expr_fn_block(ref decl, _) => {
190232
for vec::each(decl.inputs) |input| {

src/librustc/middle/typeck/collect.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ use middle::typeck::astconv;
4242
use middle::typeck::infer;
4343
use middle::typeck::rscope::*;
4444
use middle::typeck::rscope;
45-
use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
45+
use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx,
46+
write_tpt_to_tcx};
4647
use util::common::{indenter, pluralize};
4748
use util::ppaux;
4849

@@ -807,8 +808,10 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt, t: @ast::trait_ref,
807808

808809
match lookup_def_tcx(ccx.tcx, t.path.span, t.ref_id) {
809810
ast::def_ty(t_id) => {
810-
let tpt = astconv::ast_path_to_ty(ccx, &rscope, t_id, t.path,
811-
t.ref_id);
811+
let tpt = astconv::ast_path_to_ty(ccx, &rscope, t_id, t.path);
812+
813+
write_tpt_to_tcx(ccx.tcx, t.ref_id, &tpt);
814+
812815
match ty::get(tpt.ty).sty {
813816
ty::ty_trait(*) => {
814817
(t_id, tpt)

src/librustc/middle/typeck/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ pub enum vtable_origin {
142142
vtable_res is the vtable itself
143143
*/
144144
vtable_static(ast::def_id, ~[ty::t], vtable_res),
145+
145146
/*
146147
Dynamic vtable, comes from a parameter that has a bound on it:
147148
fn foo<T:quux,baz,bar>(a: T) -- a's vtable would have a
@@ -184,6 +185,7 @@ pub struct CrateCtxt {
184185
// Functions that write types into the node type table
185186
pub fn write_ty_to_tcx(tcx: ty::ctxt, node_id: ast::node_id, ty: ty::t) {
186187
debug!("write_ty_to_tcx(%d, %s)", node_id, ppaux::ty_to_str(tcx, ty));
188+
fail_unless!(!ty::type_needs_infer(ty));
187189
tcx.node_types.insert(node_id as uint, ty);
188190
}
189191
pub fn write_substs_to_tcx(tcx: ty::ctxt,
@@ -192,9 +194,18 @@ pub fn write_substs_to_tcx(tcx: ty::ctxt,
192194
if substs.len() > 0u {
193195
debug!("write_substs_to_tcx(%d, %?)", node_id,
194196
substs.map(|t| ppaux::ty_to_str(tcx, *t)));
197+
fail_unless!(substs.all(|t| !ty::type_needs_infer(*t)));
195198
tcx.node_type_substs.insert(node_id, substs);
196199
}
197200
}
201+
pub fn write_tpt_to_tcx(tcx: ty::ctxt,
202+
node_id: ast::node_id,
203+
tpt: &ty::ty_param_substs_and_ty) {
204+
write_ty_to_tcx(tcx, node_id, tpt.ty);
205+
if !tpt.substs.tps.is_empty() {
206+
write_substs_to_tcx(tcx, node_id, copy tpt.substs.tps);
207+
}
208+
}
198209

199210
pub fn lookup_def_tcx(tcx: ty::ctxt, sp: span, id: ast::node_id) -> ast::def {
200211
match tcx.def_map.find(&id) {

0 commit comments

Comments
 (0)