Skip to content

Commit

Permalink
auto merge of #5467 : nikomatsakis/rust/issues-3888-4036-4492-cannot-…
Browse files Browse the repository at this point in the history
…encode-region-variables, r=nikomatsakis

The basic problem was that vtables were not being resolved.  The fix uncovered another issue, which was that the syntax extensions were not creating method calls properly and were relying on outdated code in typeck, so I fixed that too.  

Resolves issues #3888, #4036, #4492.

r? @catamorphism
  • Loading branch information
bors committed Mar 26, 2013
2 parents bbc4ca1 + 3ca7c22 commit 3f7c74d
Show file tree
Hide file tree
Showing 19 changed files with 276 additions and 207 deletions.
12 changes: 11 additions & 1 deletion src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1579,7 +1579,17 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
id: ast::node_id,
impl_id: Option<ast::def_id>,
param_substs: Option<@param_substs>,
sp: Option<span>) -> fn_ctxt {
sp: Option<span>) -> fn_ctxt
{
for param_substs.each |p| { p.validate(); }
debug!("new_fn_ctxt_w_id(path=%s, id=%?, impl_id=%?, \
param_substs=%s",
path_str(ccx.sess, path),
id,
impl_id,
opt_param_substs_to_str(ccx.tcx, &param_substs));

let llbbs = mk_standard_basic_blocks(llfndecl);
return @mut fn_ctxt_ {
llfn: llfndecl,
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ pub fn trans_fn_ref_with_vtables(
// - `type_params`: values for each of the fn/method's type parameters
// - `vtables`: values for each bound on each of the type parameters

let _icx = bcx.insn_ctxt("trans_fn_with_vtables");
let _icx = bcx.insn_ctxt("trans_fn_ref_with_vtables");
let ccx = bcx.ccx();
let tcx = ccx.tcx;

Expand All @@ -228,6 +228,8 @@ pub fn trans_fn_ref_with_vtables(
vtables);
let _indenter = indenter();

fail_unless!(type_params.all(|t| !ty::type_needs_infer(*t)));

// Polytype of the function item (may have type params)
let fn_tpt = ty::lookup_item_type(tcx, def_id);

Expand Down
21 changes: 20 additions & 1 deletion src/librustc/middle/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,25 @@ pub struct param_substs {
self_ty: Option<ty::t>
}

pub impl param_substs {
fn validate(&self) {
for self.tys.each |t| { fail_unless!(!ty::type_needs_infer(*t)); }
for self.self_ty.each |t| { fail_unless!(!ty::type_needs_infer(*t)); }
}
}

pub fn param_substs_to_str(tcx: ty::ctxt, substs: &param_substs) -> ~str {
fmt!("param_substs {tys:%?, vtables:%?, bounds:%?}",
substs.tys.map(|t| ty_to_str(tcx, *t)),
substs.vtables.map(|vs| vs.map(|v| v.to_str(tcx))),
substs.bounds.map(|b| ty::param_bounds_to_str(tcx, *b)))
}

pub fn opt_param_substs_to_str(tcx: ty::ctxt,
substs: &Option<@param_substs>) -> ~str {
substs.map_default(~"None", |&ps| param_substs_to_str(tcx, ps))
}

// Function context. Every LLVM function we create will have one of
// these.
pub struct fn_ctxt_ {
Expand Down Expand Up @@ -1367,6 +1379,13 @@ pub fn expr_ty_adjusted(bcx: block, ex: @ast::expr) -> ty::t {
pub fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] {
let tcx = bcx.tcx();
let params = ty::node_id_to_type_params(tcx, id);

if !params.all(|t| !ty::type_needs_infer(*t)) {
bcx.sess().bug(
fmt!("Type parameters for node %d include inference types: %s",
id, str::connect(params.map(|t| bcx.ty_to_str(*t)), ",")));
}

match bcx.fcx.param_substs {
Some(substs) => {
do vec::map(params) |t| {
Expand Down Expand Up @@ -1423,7 +1442,7 @@ pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, +vt: typeck::vtable_origin)
}

pub fn find_vtable(tcx: ty::ctxt, ps: &param_substs,
n_param: uint, n_bound: uint)
n_param: uint, n_bound: uint)
-> typeck::vtable_origin {
debug!("find_vtable_in_fn_ctxt(n_param=%u, n_bound=%u, ps=%?)",
n_param, n_bound, param_substs_to_str(tcx, ps));
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/middle/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ pub fn trans_method_callee(bcx: block,
-> Callee {
let _icx = bcx.insn_ctxt("impl::trans_method_callee");

debug!("trans_method_callee(callee_id=%?, self=%s, mentry=%?)",
callee_id, bcx.expr_to_str(self), mentry);

// Replace method_self with method_static here.
let mut origin = mentry.origin;
match origin {
Expand Down Expand Up @@ -218,6 +221,8 @@ pub fn trans_method_callee(bcx: block,
typeck::method_trait(*) => {}
}

debug!("origin=%?", origin);

match origin {
typeck::method_static(did) => {
let callee_fn = callee::trans_fn_ref(bcx, did, callee_id);
Expand Down Expand Up @@ -322,6 +327,7 @@ pub fn trans_static_method_callee(bcx: block,

match vtbls[bound_index] {
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
fail_unless!(rcvr_substs.all(|t| !ty::type_needs_infer(*t)));

let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
let callee_substs = combine_impl_and_methods_tps(
Expand Down
7 changes: 5 additions & 2 deletions src/librustc/middle/trans/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
impl_did_opt: Option<ast::def_id>,
ref_id: Option<ast::node_id>) ->
(ValueRef, bool) {
fail_unless!(real_substs.all(|t| !ty::type_needs_infer(*t)));
let _icx = ccx.insn_ctxt("monomorphic_fn");
let mut must_cast = false;
let substs = vec::map(real_substs, |t| {
Expand All @@ -67,9 +68,11 @@ pub fn monomorphic_fn(ccx: @CrateContext,
must_cast = true;
}

debug!("monomorphic_fn(fn_id=%? (%s), real_substs=%?, substs=%?, \
hash_id = %?",
debug!("monomorphic_fn(fn_id=%? (%s), vtables=%?, \
real_substs=%?, substs=%?, \
hash_id = %?",
fn_id, ty::item_path_str(ccx.tcx, fn_id),
vtables,
real_substs.map(|s| ty_to_str(ccx.tcx, *s)),
substs.map(|s| ty_to_str(ccx.tcx, *s)), hash_id);

Expand Down
14 changes: 5 additions & 9 deletions src/librustc/middle/typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ use middle::ty::{ty_param_substs_and_ty};
use middle::ty;
use middle::typeck::rscope::{in_binding_rscope};
use middle::typeck::rscope::{region_scope, type_rscope, RegionError};
use middle::typeck::{CrateCtxt, write_substs_to_tcx, write_ty_to_tcx};
use middle::typeck::{CrateCtxt};

use core::result;
use core::vec;
Expand Down Expand Up @@ -186,19 +186,15 @@ pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
did: ast::def_id,
path: @ast::path,
path_id: ast::node_id)
-> ty_param_substs_and_ty {
path: @ast::path)
-> ty_param_substs_and_ty
{
// Look up the polytype of the item and then substitute the provided types
// for any type/region parameters.
let tcx = self.tcx();
let ty::ty_param_substs_and_ty {
substs: substs,
ty: ty
} = ast_path_to_substs_and_ty(self, rscope, did, path);
write_ty_to_tcx(tcx, path_id, ty);
write_substs_to_tcx(tcx, path_id, /*bad*/copy substs.tps);

ty_param_substs_and_ty { substs: substs, ty: ty }
}

Expand Down Expand Up @@ -368,7 +364,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
};
match a_def {
ast::def_ty(did) | ast::def_struct(did) => {
ast_path_to_ty(self, rscope, did, path, id).ty
ast_path_to_ty(self, rscope, did, path).ty
}
ast::def_prim_ty(nty) => {
match nty {
Expand Down
77 changes: 32 additions & 45 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ use middle::typeck::rscope::{RegionError};
use middle::typeck::rscope::{in_binding_rscope, region_scope, type_rscope};
use middle::typeck::rscope;
use middle::typeck::{isr_alist, lookup_def_ccx, method_map_entry};
use middle::typeck::{method_map, vtable_map};
use middle::typeck::{method_origin, method_self, method_trait, no_params};
use middle::typeck::{require_same_types};
use util::common::{block_query, indenter, loop_query};
Expand Down Expand Up @@ -160,9 +161,13 @@ pub struct SelfInfo {
pub struct inherited {
infcx: @mut infer::InferCtxt,
locals: HashMap<ast::node_id, ty::t>,

// Temporary tables:
node_types: HashMap<ast::node_id, ty::t>,
node_type_substs: HashMap<ast::node_id, ty::substs>,
adjustments: HashMap<ast::node_id, @ty::AutoAdjustment>
adjustments: HashMap<ast::node_id, @ty::AutoAdjustment>,
method_map: method_map,
vtable_map: vtable_map,
}

pub enum FnKind {
Expand Down Expand Up @@ -220,7 +225,9 @@ pub fn blank_inherited(ccx: @mut CrateCtxt) -> @inherited {
locals: HashMap(),
node_types: oldmap::HashMap(),
node_type_substs: oldmap::HashMap(),
adjustments: oldmap::HashMap()
adjustments: oldmap::HashMap(),
method_map: oldmap::HashMap(),
vtable_map: oldmap::HashMap(),
}
}

Expand Down Expand Up @@ -1321,13 +1328,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
sugar: ast::CallSugar) {
// Index expressions need to be handled separately, to inform them
// that they appear in call position.
match f.node {
ast::expr_field(ref base, ref field, ref tys) => {
check_field(fcx, f, true, *base, *field, *tys)
}
_ => check_expr(fcx, f)
};

let mut bot = check_expr(fcx, f);
check_call_or_method(fcx,
sp,
call_expr_id,
Expand Down Expand Up @@ -1363,7 +1364,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
CheckTraitsAndInherentMethods,
AutoderefReceiver) {
Some(ref entry) => {
let method_map = fcx.ccx.method_map;
let method_map = fcx.inh.method_map;
method_map.insert(expr.id, (*entry));
}
None => {
Expand Down Expand Up @@ -1435,7 +1436,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
deref_args, CheckTraitsOnly, autoderef_receiver) {
Some(ref origin) => {
let method_ty = fcx.node_ty(op_ex.callee_id);
let method_map = fcx.ccx.method_map;
let method_map = fcx.inh.method_map;
method_map.insert(op_ex.id, *origin);
check_call_inner(fcx, op_ex.span,
op_ex.id, method_ty,
Expand Down Expand Up @@ -1689,7 +1690,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
// Check field access expressions
fn check_field(fcx: @mut FnCtxt,
expr: @ast::expr,
is_callee: bool,
base: @ast::expr,
field: ast::ident,
tys: &[@ast::Ty]) {
Expand Down Expand Up @@ -1723,7 +1723,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}

let tps = vec::map(tys, |ty| fcx.to_ty(*ty));

match method::lookup(fcx,
expr,
base,
Expand All @@ -1734,34 +1733,30 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
DontDerefArgs,
CheckTraitsAndInherentMethods,
AutoderefReceiver) {
Some(ref entry) => {
let method_map = fcx.ccx.method_map;
method_map.insert(expr.id, (*entry));

// If we have resolved to a method but this is not in
// a callee position, error
if !is_callee {
tcx.sess.span_err(
expr.span,
~"attempted to take value of method \
(try writing an anonymous function)");
// Add error type for the result
fcx.write_error(expr.id);
}
Some(_) => {
fcx.type_error_message(
expr.span,
|actual| {
fmt!("attempted to take value of method `%s` on type `%s` \
(try writing an anonymous function)",
*tcx.sess.str_of(field), actual)
},
expr_t, None);
}

None => {
fcx.type_error_message(expr.span,
|actual| {
fmt!("attempted access of field `%s` on type `%s`, but \
no field or method with that name was found",
*tcx.sess.str_of(field), actual)
},
expr_t, None);
// Add error type for the result
fcx.write_error(expr.id);
fcx.type_error_message(
expr.span,
|actual| {
fmt!("attempted access of field `%s` on type `%s`, \
but no field with that name was found",
*tcx.sess.str_of(field), actual)
},
expr_t, None);
}
}

fcx.write_error(expr.id);
}

fn check_struct_or_variant_fields(fcx: @mut FnCtxt,
Expand Down Expand Up @@ -2750,15 +2745,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}
}
ast::expr_field(base, field, ref tys) => {
check_field(fcx, expr, false, base, field, * tys);
let base_t = fcx.expr_ty(base);
if ty::type_is_error(base_t) {
fcx.write_error(id);
}
else if ty::type_is_bot(base_t) {
fcx.write_bot(id);
}
// Otherwise, type already got written
check_field(fcx, expr, base, field, *tys);
}
ast::expr_index(base, idx) => {
check_expr(fcx, base);
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/typeck/check/regionck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ pub fn visit_expr(expr: @ast::expr, &&rcx: @mut Rcx, v: rvt) {
// `constrain_auto_ref()` on all exprs. But that causes a
// lot of spurious errors because of how the region
// hierarchy is setup.
if rcx.fcx.ccx.method_map.contains_key(&callee.id) {
if rcx.fcx.inh.method_map.contains_key(&callee.id) {
match callee.node {
ast::expr_field(base, _, _) => {
constrain_auto_ref(rcx, base);
Expand Down Expand Up @@ -713,7 +713,7 @@ pub mod guarantor {
ast::expr_repeat(*) |
ast::expr_vec(*) => {
fail_unless!(!ty::expr_is_lval(
rcx.fcx.tcx(), rcx.fcx.ccx.method_map, expr));
rcx.fcx.tcx(), rcx.fcx.inh.method_map, expr));
None
}
}
Expand Down Expand Up @@ -765,7 +765,7 @@ pub mod guarantor {
let _i = ::util::common::indenter();

let guarantor = {
if rcx.fcx.ccx.method_map.contains_key(&expr.id) {
if rcx.fcx.inh.method_map.contains_key(&expr.id) {
None
} else {
guarantor(rcx, expr)
Expand Down
Loading

0 comments on commit 3f7c74d

Please sign in to comment.