Change:
Taking a look.
Probably the best fix for now is to disallow deref of outright. I'll work up a PR that fixes this and a few other ICEs surrounding .
This is fixed with a test, closing.

Discussion:
for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) { let resolved_t = structurally_resolved_type(fcx, sp, t); <ins> if ty::type_is_bot(resolved_t) { return (resolved_t, autoderefs, None); } </ins> match should_stop(resolved_t, autoderefs) { Some(x) => return (resolved_t, autoderefs, Some(x)), None => {}

check_expr_with_expectation_and_lvalue_pref( fcx, &**oprnd, expected_inner, lvalue_pref); let mut oprnd_t = fcx.expr_ty(&**oprnd); <del> if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) { </del> <ins> if !ty::type_is_error(oprnd_t) { </ins> match unop { ast::UnBox => { <del> oprnd_t = ty::mk_box(tcx, oprnd_t) </del> <ins> if !ty::type_is_bot(oprnd_t) { oprnd_t = ty::mk_box(tcx, oprnd_t) } </ins> } ast::UnUniq => { <del> oprnd_t = ty::mk_uniq(tcx, oprnd_t); </del> <ins> if !ty::type_is_bot(oprnd_t) { oprnd_t = ty::mk_uniq(tcx, oprnd_t); } </ins> } ast::UnDeref => { oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);

}; } ast::UnNot => { <del> oprnd_t = structurally_resolved_type(fcx, oprnd.span, oprnd_t); if !(ty::type_is_integral(oprnd_t) || ty::get(oprnd_t).sty == ty::ty_bool) { oprnd_t = check_user_unop(fcx, "!", "not", tcx.lang_items.not_trait(), expr, &**oprnd, oprnd_t); </del> <ins> if !ty::type_is_bot(oprnd_t) { oprnd_t = structurally_resolved_type(fcx, oprnd.span, oprnd_t); if !(ty::type_is_integral(oprnd_t) || ty::get(oprnd_t).sty == ty::ty_bool) { oprnd_t = check_user_unop(fcx, "!", "not", tcx.lang_items.not_trait(), expr, &**oprnd, oprnd_t); } </ins> } } ast::UnNeg => { <del> oprnd_t = structurally_resolved_type(fcx, oprnd.span, oprnd_t); if !(ty::type_is_integral(oprnd_t) || ty::type_is_fp(oprnd_t)) { oprnd_t = check_user_unop(fcx, "-", "neg", tcx.lang_items.neg_trait(), expr, &**oprnd, oprnd_t); </del> <ins> if !ty::type_is_bot(oprnd_t) { oprnd_t = structurally_resolved_type(fcx, oprnd.span, oprnd_t); if !(ty::type_is_integral(oprnd_t) || ty::type_is_fp(oprnd_t)) { oprnd_t = check_user_unop(fcx, "-", "neg", tcx.lang_items.neg_trait(), expr, &**oprnd, oprnd_t); } </ins> } } }

check_expr(fcx, &**idx); let raw_base_t = fcx.expr_ty(&**base); let idx_t = fcx.expr_ty(&**idx); <del> if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) { </del> <ins> if ty::type_is_error(raw_base_t) { </ins> fcx.write_ty(id, raw_base_t); <del> } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) { </del> <ins> } else if ty::type_is_error(idx_t) { </ins> fcx.write_ty(id, idx_t); } else { let (_, autoderefs, field_ty) = autoderef(fcx, expr.span, raw_base_t, Some(base.id), lvalue_pref, |base_t, _| ty::index(base_t)); match field_ty { <del> Some(ty) => { </del> <ins> Some(ty) if !ty::type_is_bot(ty) => { </ins> check_expr_has_type(fcx, &**idx, ty::mk_uint()); fcx.write_ty(id, ty); fcx.write_autoderef_adjustment(base.id, base.span, autoderefs); } <del> None => { </del> <ins> _ => { </ins> // This is an overloaded method. let base_t = structurally_resolved_type(fcx, expr.span,

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. fn main() { (return)[0u]; //~ ERROR cannot index a value of type `!` } </ins>

<ins> // Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. fn main() { *return; //~ ERROR type `!` cannot be dereferenced } </ins>