Skip to content

Commit 0b3b957

Browse files
committed
rollup merge of #20645: nikomatsakis/rustbook-ice
Conflicts: src/librustc/middle/mem_categorization.rs src/librustc/middle/ty.rs src/librustc_trans/trans/base.rs src/librustc_trans/trans/expr.rs src/librustc_trans/trans/foreign.rs src/librustc_typeck/check/mod.rs
2 parents e0f546a + 2486d93 commit 0b3b957

File tree

23 files changed

+386
-177
lines changed

23 files changed

+386
-177
lines changed

src/librustc/middle/cfg/construct.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
514514

515515
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
516516
let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
517-
if return_ty == ty::FnDiverging {
517+
if return_ty.diverges() {
518518
self.add_node(ast::DUMMY_NODE_ID, &[])
519519
} else {
520520
ret

src/librustc/middle/expr_use_visitor.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
848848
None => {}
849849
Some(method_ty) => {
850850
let cmt = return_if_err!(self.mc.cat_expr_autoderefd(expr, i));
851-
let self_ty = ty::ty_fn_args(method_ty)[0];
851+
852+
// the method call infrastructure should have
853+
// replaced all late-bound regions with variables:
854+
let self_ty = ty::ty_fn_sig(method_ty).input(0);
855+
let self_ty = ty::assert_no_late_bound_regions(self.tcx(), &self_ty);
856+
852857
let (m, r) = match self_ty.sty {
853858
ty::ty_rptr(r, ref m) => (m.mutbl, r),
854859
_ => self.tcx().sess.span_bug(expr.span,

src/librustc/middle/liveness.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ use self::VarKind::*;
112112
use middle::def::*;
113113
use middle::mem_categorization::Typer;
114114
use middle::pat_util;
115+
use middle::region::CodeExtent;
115116
use middle::ty;
116117
use middle::ty::UnboxedClosureTyper;
117118
use lint;
@@ -1149,8 +1150,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
11491150

11501151
ast::ExprCall(ref f, ref args) => {
11511152
let diverges = !self.ir.tcx.is_method_call(expr.id) && {
1152-
let t_ret = ty::ty_fn_ret(ty::expr_ty_adjusted(self.ir.tcx, &**f));
1153-
t_ret == ty::FnDiverging
1153+
ty::ty_fn_ret(ty::expr_ty_adjusted(self.ir.tcx, &**f)).diverges()
11541154
};
11551155
let succ = if diverges {
11561156
self.s.exit_ln
@@ -1164,7 +1164,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
11641164
ast::ExprMethodCall(_, _, ref args) => {
11651165
let method_call = ty::MethodCall::expr(expr.id);
11661166
let method_ty = self.ir.tcx.method_map.borrow().get(&method_call).unwrap().ty;
1167-
let diverges = ty::ty_fn_ret(method_ty) == ty::FnDiverging;
1167+
let diverges = ty::ty_fn_ret(method_ty).diverges();
11681168
let succ = if diverges {
11691169
self.s.exit_ln
11701170
} else {
@@ -1514,11 +1514,11 @@ fn check_fn(_v: &Liveness,
15141514
}
15151515

15161516
impl<'a, 'tcx> Liveness<'a, 'tcx> {
1517-
fn fn_ret(&self, id: NodeId) -> ty::FnOutput<'tcx> {
1517+
fn fn_ret(&self, id: NodeId) -> ty::PolyFnOutput<'tcx> {
15181518
let fn_ty = ty::node_id_to_type(self.ir.tcx, id);
15191519
match fn_ty.sty {
15201520
ty::ty_unboxed_closure(closure_def_id, _, substs) =>
1521-
self.ir.tcx.unboxed_closure_type(closure_def_id, substs).sig.0.output,
1521+
self.ir.tcx.unboxed_closure_type(closure_def_id, substs).sig.output(),
15221522
_ =>
15231523
ty::ty_fn_ret(fn_ty),
15241524
}
@@ -1529,8 +1529,16 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
15291529
sp: Span,
15301530
_fk: FnKind,
15311531
entry_ln: LiveNode,
1532-
body: &ast::Block) {
1533-
match self.fn_ret(id) {
1532+
body: &ast::Block)
1533+
{
1534+
// within the fn body, late-bound regions are liberated:
1535+
let fn_ret =
1536+
ty::liberate_late_bound_regions(
1537+
self.ir.tcx,
1538+
CodeExtent::from_node_id(body.id),
1539+
&self.fn_ret(id));
1540+
1541+
match fn_ret {
15341542
ty::FnConverging(t_ret)
15351543
if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() => {
15361544

src/librustc/middle/mem_categorization.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
857857

858858
let base_cmt = match method_ty {
859859
Some(method_ty) => {
860-
let ref_ty = ty::ty_fn_ret(method_ty).unwrap();
860+
let ref_ty =
861+
ty::assert_no_late_bound_regions(
862+
self.tcx(), &ty::ty_fn_ret(method_ty)).unwrap();
861863
self.cat_rvalue_node(node.id(), node.span(), ref_ty)
862864
}
863865
None => base_cmt
@@ -937,9 +939,12 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
937939

938940
let element_ty = match method_ty {
939941
Some(method_ty) => {
940-
let ref_ty = ty::ty_fn_ret(method_ty).unwrap();
942+
let ref_ty = self.overloaded_method_return_ty(method_ty);
941943
base_cmt = self.cat_rvalue_node(elt.id(), elt.span(), ref_ty);
942-
ty::ty_fn_args(method_ty)[0]
944+
945+
// FIXME(#20649) -- why are we using the `self_ty` as the element type...?
946+
let self_ty = ty::ty_fn_sig(method_ty).input(0);
947+
ty::assert_no_late_bound_regions(self.tcx(), &self_ty)
943948
}
944949
None => {
945950
match ty::array_element_ty(self.tcx(), base_cmt.ty) {
@@ -1261,6 +1266,19 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
12611266

12621267
Ok(())
12631268
}
1269+
1270+
fn overloaded_method_return_ty(&self,
1271+
method_ty: Ty<'tcx>)
1272+
-> Ty<'tcx>
1273+
{
1274+
// When we process an overloaded `*` or `[]` etc, we often
1275+
// need to extract the return type of the method. These method
1276+
// types are generated by method resolution and always have
1277+
// all late-bound regions fully instantiated, so we just want
1278+
// to skip past the binder.
1279+
ty::assert_no_late_bound_regions(self.tcx(), &ty::ty_fn_ret(method_ty))
1280+
.unwrap() // overloaded ops do not diverge, either
1281+
}
12641282
}
12651283

12661284
#[derive(Copy)]

src/librustc/middle/ty.rs

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,10 @@ pub enum FnOutput<'tcx> {
10541054
}
10551055

10561056
impl<'tcx> FnOutput<'tcx> {
1057+
pub fn diverges(&self) -> bool {
1058+
*self == FnDiverging
1059+
}
1060+
10571061
pub fn unwrap(self) -> Ty<'tcx> {
10581062
match self {
10591063
ty::FnConverging(t) => t,
@@ -1062,6 +1066,14 @@ impl<'tcx> FnOutput<'tcx> {
10621066
}
10631067
}
10641068

1069+
pub type PolyFnOutput<'tcx> = Binder<FnOutput<'tcx>>;
1070+
1071+
impl<'tcx> PolyFnOutput<'tcx> {
1072+
pub fn diverges(&self) -> bool {
1073+
self.0.diverges()
1074+
}
1075+
}
1076+
10651077
/// Signature of a function type, which I have arbitrarily
10661078
/// decided to use to refer to the input/output types.
10671079
///
@@ -1077,6 +1089,21 @@ pub struct FnSig<'tcx> {
10771089

10781090
pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>;
10791091

1092+
impl<'tcx> PolyFnSig<'tcx> {
1093+
pub fn inputs(&self) -> ty::Binder<Vec<Ty<'tcx>>> {
1094+
ty::Binder(self.0.inputs.clone())
1095+
}
1096+
pub fn input(&self, index: uint) -> ty::Binder<Ty<'tcx>> {
1097+
ty::Binder(self.0.inputs[index])
1098+
}
1099+
pub fn output(&self) -> ty::Binder<FnOutput<'tcx>> {
1100+
ty::Binder(self.0.output.clone())
1101+
}
1102+
pub fn variadic(&self) -> bool {
1103+
self.0.variadic
1104+
}
1105+
}
1106+
10801107
#[derive(Clone, Copy, PartialEq, Eq, Hash, Show)]
10811108
pub struct ParamTy {
10821109
pub space: subst::ParamSpace,
@@ -4146,8 +4173,8 @@ pub fn ty_fn_abi(fty: Ty) -> abi::Abi {
41464173
}
41474174

41484175
// Type accessors for substructures of types
4149-
pub fn ty_fn_args<'tcx>(fty: Ty<'tcx>) -> &'tcx [Ty<'tcx>] {
4150-
ty_fn_sig(fty).0.inputs.as_slice()
4176+
pub fn ty_fn_args<'tcx>(fty: Ty<'tcx>) -> ty::Binder<Vec<Ty<'tcx>>> {
4177+
ty_fn_sig(fty).inputs()
41514178
}
41524179

41534180
pub fn ty_closure_store(fty: Ty) -> TraitStore {
@@ -4163,9 +4190,9 @@ pub fn ty_closure_store(fty: Ty) -> TraitStore {
41634190
}
41644191
}
41654192

4166-
pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> FnOutput<'tcx> {
4193+
pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> Binder<FnOutput<'tcx>> {
41674194
match fty.sty {
4168-
ty_bare_fn(_, ref f) => f.sig.0.output,
4195+
ty_bare_fn(_, ref f) => f.sig.output(),
41694196
ref s => {
41704197
panic!("ty_fn_ret() called on non-fn type: {:?}", s)
41714198
}
@@ -4320,9 +4347,12 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
43204347
let method_call = MethodCall::autoderef(expr_id, i);
43214348
match method_type(method_call) {
43224349
Some(method_ty) => {
4323-
if let ty::FnConverging(result_type) = ty_fn_ret(method_ty) {
4324-
adjusted_ty = result_type;
4325-
}
4350+
// overloaded deref operators have all late-bound
4351+
// regions fully instantiated and coverge
4352+
let fn_ret =
4353+
ty::assert_no_late_bound_regions(cx,
4354+
&ty_fn_ret(method_ty));
4355+
adjusted_ty = fn_ret.unwrap();
43264356
}
43274357
None => {}
43284358
}
@@ -5144,7 +5174,9 @@ impl<'tcx> VariantInfo<'tcx> {
51445174
match ast_variant.node.kind {
51455175
ast::TupleVariantKind(ref args) => {
51465176
let arg_tys = if args.len() > 0 {
5147-
ty_fn_args(ctor_ty).iter().map(|a| *a).collect()
5177+
// the regions in the argument types come from the
5178+
// enum def'n, and hence will all be early bound
5179+
ty::assert_no_late_bound_regions(cx, &ty_fn_args(ctor_ty))
51485180
} else {
51495181
Vec::new()
51505182
};
@@ -5160,7 +5192,6 @@ impl<'tcx> VariantInfo<'tcx> {
51605192
};
51615193
},
51625194
ast::StructVariantKind(ref struct_def) => {
5163-
51645195
let fields: &[StructField] = struct_def.fields.index(&FullRange);
51655196

51665197
assert!(fields.len() > 0);
@@ -5792,40 +5823,6 @@ pub fn is_binopable<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, op: ast::BinOp) -> bool
57925823
return tbl[tycat(cx, ty) as uint ][opcat(op) as uint];
57935824
}
57945825

5795-
/// Returns an equivalent type with all the typedefs and self regions removed.
5796-
pub fn normalize_ty<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
5797-
let u = TypeNormalizer(cx).fold_ty(ty);
5798-
return u;
5799-
5800-
struct TypeNormalizer<'a, 'tcx: 'a>(&'a ctxt<'tcx>);
5801-
5802-
impl<'a, 'tcx> TypeFolder<'tcx> for TypeNormalizer<'a, 'tcx> {
5803-
fn tcx(&self) -> &ctxt<'tcx> { let TypeNormalizer(c) = *self; c }
5804-
5805-
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
5806-
match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
5807-
None => {}
5808-
Some(u) => return u
5809-
}
5810-
5811-
let t_norm = ty_fold::super_fold_ty(self, ty);
5812-
self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
5813-
return t_norm;
5814-
}
5815-
5816-
fn fold_region(&mut self, _: ty::Region) -> ty::Region {
5817-
ty::ReStatic
5818-
}
5819-
5820-
fn fold_substs(&mut self,
5821-
substs: &subst::Substs<'tcx>)
5822-
-> subst::Substs<'tcx> {
5823-
subst::Substs { regions: subst::ErasedRegions,
5824-
types: substs.types.fold_with(self) }
5825-
}
5826-
}
5827-
}
5828-
58295826
// Returns the repeat count for a repeating vector expression.
58305827
pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
58315828
match const_eval::eval_const_expr_partial(tcx, count_expr) {
@@ -6205,7 +6202,7 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
62056202
mt.mutbl.hash(state);
62066203
};
62076204
let fn_sig = |&: state: &mut sip::SipState, sig: &Binder<FnSig<'tcx>>| {
6208-
let sig = anonymize_late_bound_regions(tcx, sig);
6205+
let sig = anonymize_late_bound_regions(tcx, sig).0;
62096206
for a in sig.inputs.iter() { helper(tcx, *a, svh, state); }
62106207
if let ty::FnConverging(output) = sig.output {
62116208
helper(tcx, output, svh, state);
@@ -6266,7 +6263,7 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
62666263
did(state, data.principal_def_id());
62676264
hash!(data.bounds);
62686265

6269-
let principal = anonymize_late_bound_regions(tcx, &data.principal);
6266+
let principal = anonymize_late_bound_regions(tcx, &data.principal).0;
62706267
for subty in principal.substs.types.iter() {
62716268
helper(tcx, *subty, svh, state);
62726269
}
@@ -6697,6 +6694,16 @@ pub fn binds_late_bound_regions<'tcx, T>(
66976694
count_late_bound_regions(tcx, value) > 0
66986695
}
66996696

6697+
pub fn assert_no_late_bound_regions<'tcx, T>(
6698+
tcx: &ty::ctxt<'tcx>,
6699+
value: &Binder<T>)
6700+
-> T
6701+
where T : TypeFoldable<'tcx> + Repr<'tcx> + Clone
6702+
{
6703+
assert!(!binds_late_bound_regions(tcx, value));
6704+
value.0.clone()
6705+
}
6706+
67006707
/// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also
67016708
/// method lookup and a few other places where precise region relationships are not required.
67026709
pub fn erase_late_bound_regions<'tcx, T>(
@@ -6719,14 +6726,14 @@ pub fn erase_late_bound_regions<'tcx, T>(
67196726
pub fn anonymize_late_bound_regions<'tcx, T>(
67206727
tcx: &ctxt<'tcx>,
67216728
sig: &Binder<T>)
6722-
-> T
6729+
-> Binder<T>
67236730
where T : TypeFoldable<'tcx> + Repr<'tcx>,
67246731
{
67256732
let mut counter = 0;
6726-
replace_late_bound_regions(tcx, sig, |_, db| {
6733+
ty::Binder(replace_late_bound_regions(tcx, sig, |_, db| {
67276734
counter += 1;
67286735
ReLateBound(db, BrAnon(counter))
6729-
}).0
6736+
}).0)
67306737
}
67316738

67326739
/// Replaces the late-bound-regions in `value` that are bound by `value`.

src/librustc/middle/ty_fold.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,9 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
868868
fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
869869

870870
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
871+
// because whether or not a region is bound affects subtyping,
872+
// we can't erase the bound/free distinction, but we can
873+
// replace all free regions with 'static
871874
match r {
872875
ty::ReLateBound(..) | ty::ReEarlyBound(..) => r,
873876
_ => ty::ReStatic

0 commit comments

Comments
 (0)