Skip to content

Commit 5a61812

Browse files
committed
auto merge of #11832 : jfager/rust/r5900, r=alexcrichton
I tried a couple of different ways to squash this, and still don't think this is ideal, but I wanted to get it out for feedback. Closes #5900 Closes #9942 There are a few scenarios where the compiler tries to evaluate CastExprs without the corresponding types being available yet in the type context: #10618, #5900, #9942 This PR takes the approach of having eval_const_expr_partial's CastExpr arm fall back to a limited ast_ty_to_ty call that only checks for (a subset of) valid const types, when the direct type lookup fails. It's kind of hacky, so I understand if you don't want to take this as is. I'd need a little mentoring to get this into better shape, as figuring out the proper fix has been a little daunting. I'm also happy if someone else wants to pick this up and run with it. This closes 5900 and 9942, but only moves the goalposts a little on 10618, which now falls over in a later phase of the compiler.
2 parents f478796 + 9b1865a commit 5a61812

File tree

6 files changed

+285
-209
lines changed

6 files changed

+285
-209
lines changed

src/librustc/middle/const_eval.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
use metadata::csearch;
1313
use middle::astencode;
14+
1415
use middle::ty;
16+
use middle::typeck::astconv;
1517
use middle;
1618

1719
use syntax::{ast, ast_map, ast_util};
@@ -445,8 +447,17 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
445447
_ => Err(~"Bad operands for binary")
446448
}
447449
}
448-
ExprCast(base, _) => {
449-
let ety = tcx.expr_ty(e);
450+
ExprCast(base, target_ty) => {
451+
// This tends to get called w/o the type actually having been
452+
// populated in the ctxt, which was causing things to blow up
453+
// (#5900). Fall back to doing a limited lookup to get past it.
454+
let ety = ty::expr_ty_opt(tcx.ty_ctxt(), e)
455+
.or_else(|| astconv::ast_ty_to_prim_ty(tcx.ty_ctxt(), target_ty))
456+
.unwrap_or_else(|| tcx.ty_ctxt().sess.span_fatal(
457+
target_ty.span,
458+
format!("Target type not found for const cast")
459+
));
460+
450461
let base = eval_const_expr_partial(tcx, base);
451462
match base {
452463
Err(_) => base,

src/librustc/middle/ty.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,17 +2669,24 @@ pub fn node_id_to_trait_ref(cx: ctxt, id: ast::NodeId) -> @ty::TraitRef {
26692669
}
26702670

26712671
pub fn node_id_to_type(cx: ctxt, id: ast::NodeId) -> t {
2672-
//printfln!("{:?}/{:?}", id, cx.node_types.len());
2673-
let node_types = cx.node_types.borrow();
2674-
match node_types.get().find(&(id as uint)) {
2675-
Some(&t) => t,
2672+
match node_id_to_type_opt(cx, id) {
2673+
Some(t) => t,
26762674
None => cx.sess.bug(
26772675
format!("node_id_to_type: no type for node `{}`",
26782676
ast_map::node_id_to_str(cx.items, id,
26792677
token::get_ident_interner())))
26802678
}
26812679
}
26822680

2681+
pub fn node_id_to_type_opt(cx: ctxt, id: ast::NodeId) -> Option<t> {
2682+
let node_types = cx.node_types.borrow();
2683+
debug!("id: {:?}, node_types: {:?}", id, node_types);
2684+
match node_types.get().find(&(id as uint)) {
2685+
Some(&t) => Some(t),
2686+
None => None
2687+
}
2688+
}
2689+
26832690
// FIXME(pcwalton): Makes a copy, bleh. Probably better to not do that.
26842691
pub fn node_id_to_type_params(cx: ctxt, id: ast::NodeId) -> ~[t] {
26852692
let node_type_substs = cx.node_type_substs.borrow();
@@ -2850,6 +2857,10 @@ pub fn expr_ty(cx: ctxt, expr: &ast::Expr) -> t {
28502857
return node_id_to_type(cx, expr.id);
28512858
}
28522859

2860+
pub fn expr_ty_opt(cx: ctxt, expr: &ast::Expr) -> Option<t> {
2861+
return node_id_to_type_opt(cx, expr.id);
2862+
}
2863+
28532864
pub fn expr_ty_adjusted(cx: ctxt, expr: &ast::Expr) -> t {
28542865
/*!
28552866
*

0 commit comments

Comments
 (0)