1
Fork 0

A few cleanups and minor improvements to rustc_passes

This commit is contained in:
ljedrz 2018-09-07 15:10:16 +02:00
parent 2ae11a9c22
commit 8bbe1789fa
5 changed files with 96 additions and 128 deletions

View file

@ -98,14 +98,11 @@ impl<'a> AstValidator<'a> {
} }
fn check_trait_fn_not_const(&self, constness: Spanned<Constness>) { fn check_trait_fn_not_const(&self, constness: Spanned<Constness>) {
match constness.node { if constness.node == Constness::Const {
Constness::Const => { struct_span_err!(self.session, constness.span, E0379,
struct_span_err!(self.session, constness.span, E0379, "trait fns cannot be declared const")
"trait fns cannot be declared const") .span_label(constness.span, "trait fns cannot be const")
.span_label(constness.span, "trait fns cannot be const") .emit();
.emit();
}
_ => {}
} }
} }
@ -113,7 +110,7 @@ impl<'a> AstValidator<'a> {
for bound in bounds { for bound in bounds {
if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound { if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
let mut err = self.err_handler().struct_span_err(poly.span, let mut err = self.err_handler().struct_span_err(poly.span,
&format!("`?Trait` is not permitted in {}", where_)); &format!("`?Trait` is not permitted in {}", where_));
if is_trait { if is_trait {
err.note(&format!("traits are `?{}` by default", poly.trait_ref.path)); err.note(&format!("traits are `?{}` by default", poly.trait_ref.path));
} }
@ -152,16 +149,16 @@ impl<'a> AstValidator<'a> {
// Check only lifetime parameters are present and that the lifetime // Check only lifetime parameters are present and that the lifetime
// parameters that are present have no bounds. // parameters that are present have no bounds.
let non_lt_param_spans: Vec<_> = params.iter().filter_map(|param| match param.kind { let non_lt_param_spans: Vec<_> = params.iter().filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => { GenericParamKind::Lifetime { .. } => {
if !param.bounds.is_empty() { if !param.bounds.is_empty() {
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
self.err_handler() self.err_handler()
.span_err(spans, "lifetime bounds cannot be used in this context"); .span_err(spans, "lifetime bounds cannot be used in this context");
}
None
} }
_ => Some(param.ident.span), None
}).collect(); }
_ => Some(param.ident.span),
}).collect();
if !non_lt_param_spans.is_empty() { if !non_lt_param_spans.is_empty() {
self.err_handler().span_err(non_lt_param_spans, self.err_handler().span_err(non_lt_param_spans,
"only lifetime parameters can be used in this context"); "only lifetime parameters can be used in this context");
@ -387,7 +384,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.err_handler().span_err(item.span, self.err_handler().span_err(item.span,
"tuple and unit unions are not permitted"); "tuple and unit unions are not permitted");
} }
if vdata.fields().len() == 0 { if vdata.fields().is_empty() {
self.err_handler().span_err(item.span, self.err_handler().span_err(item.span,
"unions cannot have zero fields"); "unions cannot have zero fields");
} }
@ -414,14 +411,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
fn visit_vis(&mut self, vis: &'a Visibility) { fn visit_vis(&mut self, vis: &'a Visibility) {
match vis.node { if let VisibilityKind::Restricted { ref path, .. } = vis.node {
VisibilityKind::Restricted { ref path, .. } => { path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| { self.err_handler().span_err(segment.args.as_ref().unwrap().span(),
self.err_handler().span_err(segment.args.as_ref().unwrap().span(), "generic arguments in visibility path");
"generic arguments in visibility path"); });
});
}
_ => {}
} }
visit::walk_vis(self, vis) visit::walk_vis(self, vis)
@ -591,8 +585,7 @@ impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> {
TyKind::ImplTrait(..) => { TyKind::ImplTrait(..) => {
if self.is_banned { if self.is_banned {
struct_span_err!(self.session, t.span, E0667, struct_span_err!(self.session, t.span, E0667,
"`impl Trait` is not allowed in path parameters") "`impl Trait` is not allowed in path parameters").emit();
.emit();
} }
} }
TyKind::Path(ref qself, ref path) => { TyKind::Path(ref qself, ref path) => {
@ -616,7 +609,7 @@ impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> {
for (i, segment) in path.segments.iter().enumerate() { for (i, segment) in path.segments.iter().enumerate() {
// Allow `impl Trait` iff we're on the final path segment // Allow `impl Trait` iff we're on the final path segment
if i == (path.segments.len() - 1) { if i == path.segments.len() - 1 {
visit::walk_path_segment(self, path.span, segment); visit::walk_path_segment(self, path.span, segment);
} else { } else {
self.with_ban(|this| self.with_ban(|this|

View file

@ -61,10 +61,8 @@ pub fn print_ast_stats<'v>(krate: &'v ast::Crate, title: &str) {
impl<'k> StatCollector<'k> { impl<'k> StatCollector<'k> {
fn record<T>(&mut self, label: &'static str, id: Id, node: &T) { fn record<T>(&mut self, label: &'static str, id: Id, node: &T) {
if id != Id::None { if id != Id::None && !self.seen.insert(id) {
if !self.seen.insert(id) { return
return
}
} }
let entry = self.data.entry(label).or_insert(NodeData { let entry = self.data.entry(label).or_insert(NodeData {
@ -135,40 +133,46 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
hir_visit::walk_item(self, i) hir_visit::walk_item(self, i)
} }
///////////////////////////////////////////////////////////////////////////
fn visit_mod(&mut self, m: &'v hir::Mod, _s: Span, n: NodeId) { fn visit_mod(&mut self, m: &'v hir::Mod, _s: Span, n: NodeId) {
self.record("Mod", Id::None, m); self.record("Mod", Id::None, m);
hir_visit::walk_mod(self, m, n) hir_visit::walk_mod(self, m, n)
} }
fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem) { fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem) {
self.record("ForeignItem", Id::Node(i.id), i); self.record("ForeignItem", Id::Node(i.id), i);
hir_visit::walk_foreign_item(self, i) hir_visit::walk_foreign_item(self, i)
} }
fn visit_local(&mut self, l: &'v hir::Local) { fn visit_local(&mut self, l: &'v hir::Local) {
self.record("Local", Id::Node(l.id), l); self.record("Local", Id::Node(l.id), l);
hir_visit::walk_local(self, l) hir_visit::walk_local(self, l)
} }
fn visit_block(&mut self, b: &'v hir::Block) { fn visit_block(&mut self, b: &'v hir::Block) {
self.record("Block", Id::Node(b.id), b); self.record("Block", Id::Node(b.id), b);
hir_visit::walk_block(self, b) hir_visit::walk_block(self, b)
} }
fn visit_stmt(&mut self, s: &'v hir::Stmt) { fn visit_stmt(&mut self, s: &'v hir::Stmt) {
self.record("Stmt", Id::Node(s.node.id()), s); self.record("Stmt", Id::Node(s.node.id()), s);
hir_visit::walk_stmt(self, s) hir_visit::walk_stmt(self, s)
} }
fn visit_arm(&mut self, a: &'v hir::Arm) { fn visit_arm(&mut self, a: &'v hir::Arm) {
self.record("Arm", Id::None, a); self.record("Arm", Id::None, a);
hir_visit::walk_arm(self, a) hir_visit::walk_arm(self, a)
} }
fn visit_pat(&mut self, p: &'v hir::Pat) { fn visit_pat(&mut self, p: &'v hir::Pat) {
self.record("Pat", Id::Node(p.id), p); self.record("Pat", Id::Node(p.id), p);
hir_visit::walk_pat(self, p) hir_visit::walk_pat(self, p)
} }
fn visit_decl(&mut self, d: &'v hir::Decl) { fn visit_decl(&mut self, d: &'v hir::Decl) {
self.record("Decl", Id::None, d); self.record("Decl", Id::None, d);
hir_visit::walk_decl(self, d) hir_visit::walk_decl(self, d)
} }
fn visit_expr(&mut self, ex: &'v hir::Expr) { fn visit_expr(&mut self, ex: &'v hir::Expr) {
self.record("Expr", Id::Node(ex.id), ex); self.record("Expr", Id::Node(ex.id), ex);
hir_visit::walk_expr(self, ex) hir_visit::walk_expr(self, ex)
@ -198,6 +202,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
self.record("TraitItem", Id::Node(ti.id), ti); self.record("TraitItem", Id::Node(ti.id), ti);
hir_visit::walk_trait_item(self, ti) hir_visit::walk_trait_item(self, ti)
} }
fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) { fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
self.record("ImplItem", Id::Node(ii.id), ii); self.record("ImplItem", Id::Node(ii.id), ii);
hir_visit::walk_impl_item(self, ii) hir_visit::walk_impl_item(self, ii)
@ -220,31 +225,38 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
self.record("Variant", Id::None, v); self.record("Variant", Id::None, v);
hir_visit::walk_variant(self, v, g, item_id) hir_visit::walk_variant(self, v, g, item_id)
} }
fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
self.record("Lifetime", Id::Node(lifetime.id), lifetime); self.record("Lifetime", Id::Node(lifetime.id), lifetime);
hir_visit::walk_lifetime(self, lifetime) hir_visit::walk_lifetime(self, lifetime)
} }
fn visit_qpath(&mut self, qpath: &'v hir::QPath, id: hir::HirId, span: Span) { fn visit_qpath(&mut self, qpath: &'v hir::QPath, id: hir::HirId, span: Span) {
self.record("QPath", Id::None, qpath); self.record("QPath", Id::None, qpath);
hir_visit::walk_qpath(self, qpath, id, span) hir_visit::walk_qpath(self, qpath, id, span)
} }
fn visit_path(&mut self, path: &'v hir::Path, _id: hir::HirId) { fn visit_path(&mut self, path: &'v hir::Path, _id: hir::HirId) {
self.record("Path", Id::None, path); self.record("Path", Id::None, path);
hir_visit::walk_path(self, path) hir_visit::walk_path(self, path)
} }
fn visit_path_segment(&mut self, fn visit_path_segment(&mut self,
path_span: Span, path_span: Span,
path_segment: &'v hir::PathSegment) { path_segment: &'v hir::PathSegment) {
self.record("PathSegment", Id::None, path_segment); self.record("PathSegment", Id::None, path_segment);
hir_visit::walk_path_segment(self, path_span, path_segment) hir_visit::walk_path_segment(self, path_span, path_segment)
} }
fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding) { fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding) {
self.record("TypeBinding", Id::Node(type_binding.id), type_binding); self.record("TypeBinding", Id::Node(type_binding.id), type_binding);
hir_visit::walk_assoc_type_binding(self, type_binding) hir_visit::walk_assoc_type_binding(self, type_binding)
} }
fn visit_attribute(&mut self, attr: &'v ast::Attribute) { fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
self.record("Attribute", Id::Attr(attr.id), attr); self.record("Attribute", Id::Attr(attr.id), attr);
} }
fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef) { fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef) {
self.record("MacroDef", Id::Node(macro_def.id), macro_def); self.record("MacroDef", Id::Node(macro_def.id), macro_def);
hir_visit::walk_macro_def(self, macro_def) hir_visit::walk_macro_def(self, macro_def)

View file

@ -114,9 +114,8 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
}; };
if loop_id != ast::DUMMY_NODE_ID { if loop_id != ast::DUMMY_NODE_ID {
match self.hir_map.find(loop_id).unwrap() { if let Node::Block(_) = self.hir_map.find(loop_id).unwrap() {
Node::Block(_) => return, return
_=> (),
} }
} }
@ -153,10 +152,10 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
self.require_break_cx("break", e.span); self.require_break_cx("break", e.span);
} }
hir::ExprKind::Continue(label) => { hir::ExprKind::Continue(destination) => {
self.require_label_in_labeled_block(e.span, &label, "continue"); self.require_label_in_labeled_block(e.span, &destination, "continue");
match label.target_id { match destination.target_id {
Ok(loop_id) => { Ok(loop_id) => {
if let Node::Block(block) = self.hir_map.find(loop_id).unwrap() { if let Node::Block(block) = self.hir_map.find(loop_id).unwrap() {
struct_span_err!(self.sess, e.span, E0696, struct_span_err!(self.sess, e.span, E0696,
@ -171,7 +170,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => { Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
self.emit_unlabled_cf_in_while_condition(e.span, "continue"); self.emit_unlabled_cf_in_while_condition(e.span, "continue");
} }
_ => {} Err(_) => {}
} }
self.require_break_cx("continue", e.span) self.require_break_cx("continue", e.span)
}, },
@ -192,8 +191,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
fn require_break_cx(&self, name: &str, span: Span) { fn require_break_cx(&self, name: &str, span: Span) {
match self.cx { match self.cx {
LabeledBlock | LabeledBlock | Loop(_) => {}
Loop(_) => {}
Closure => { Closure => {
struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name) struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name)
.span_label(span, "cannot break inside of a closure") .span_label(span, "cannot break inside of a closure")

View file

@ -65,15 +65,12 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
self.super_mir(mir); self.super_mir(mir);
} }
fn visit_basic_block_data(&mut self, fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
block: BasicBlock,
data: &BasicBlockData<'tcx>) {
self.record("BasicBlockData", data); self.record("BasicBlockData", data);
self.super_basic_block_data(block, data); self.super_basic_block_data(block, data);
} }
fn visit_source_scope_data(&mut self, fn visit_source_scope_data(&mut self, scope_data: &SourceScopeData) {
scope_data: &SourceScopeData) {
self.record("SourceScopeData", scope_data); self.record("SourceScopeData", scope_data);
self.super_source_scope_data(scope_data); self.super_source_scope_data(scope_data);
} }
@ -130,9 +127,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
self.super_terminator_kind(block, kind, location); self.super_terminator_kind(block, kind, location);
} }
fn visit_assert_message(&mut self, fn visit_assert_message(&mut self, msg: &AssertMessage<'tcx>, location: Location) {
msg: &AssertMessage<'tcx>,
location: Location) {
self.record("AssertMessage", msg); self.record("AssertMessage", msg);
self.record(match *msg { self.record(match *msg {
EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck", EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck",
@ -151,9 +146,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
self.super_assert_message(msg, location); self.super_assert_message(msg, location);
} }
fn visit_rvalue(&mut self, fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
rvalue: &Rvalue<'tcx>,
location: Location) {
self.record("Rvalue", rvalue); self.record("Rvalue", rvalue);
let rvalue_kind = match *rvalue { let rvalue_kind = match *rvalue {
Rvalue::Use(..) => "Rvalue::Use", Rvalue::Use(..) => "Rvalue::Use",
@ -184,9 +177,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
self.super_rvalue(rvalue, location); self.super_rvalue(rvalue, location);
} }
fn visit_operand(&mut self, fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
operand: &Operand<'tcx>,
location: Location) {
self.record("Operand", operand); self.record("Operand", operand);
self.record(match *operand { self.record(match *operand {
Operand::Copy(..) => "Operand::Copy", Operand::Copy(..) => "Operand::Copy",
@ -234,42 +225,32 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
self.super_projection_elem(place, context, location); self.super_projection_elem(place, context, location);
} }
fn visit_constant(&mut self, fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
constant: &Constant<'tcx>,
location: Location) {
self.record("Constant", constant); self.record("Constant", constant);
self.super_constant(constant, location); self.super_constant(constant, location);
} }
fn visit_source_info(&mut self, fn visit_source_info(&mut self, source_info: &SourceInfo) {
source_info: &SourceInfo) {
self.record("SourceInfo", source_info); self.record("SourceInfo", source_info);
self.super_source_info(source_info); self.super_source_info(source_info);
} }
fn visit_closure_substs(&mut self, fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, _: Location) {
substs: &ClosureSubsts<'tcx>,
_: Location) {
self.record("ClosureSubsts", substs); self.record("ClosureSubsts", substs);
self.super_closure_substs(substs); self.super_closure_substs(substs);
} }
fn visit_const(&mut self, fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
constant: &&'tcx ty::Const<'tcx>,
_: Location) {
self.record("Const", constant); self.record("Const", constant);
self.super_const(constant); self.super_const(constant);
} }
fn visit_local_decl(&mut self, fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
local: Local,
local_decl: &LocalDecl<'tcx>) {
self.record("LocalDecl", local_decl); self.record("LocalDecl", local_decl);
self.super_local_decl(local, local_decl); self.super_local_decl(local, local_decl);
} }
fn visit_source_scope(&mut self, fn visit_source_scope(&mut self, scope: &SourceScope) {
scope: &SourceScope) {
self.record("VisiblityScope", scope); self.record("VisiblityScope", scope);
self.super_source_scope(scope); self.super_source_scope(scope);
} }

View file

@ -41,8 +41,7 @@ use syntax::ast;
use syntax::attr; use syntax::attr;
use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::{Span, DUMMY_SP};
use self::Promotability::*; use self::Promotability::*;
use std::ops::{BitAnd, BitOr}; use std::ops::{BitAnd, BitAndAssign, BitOr};
pub fn provide(providers: &mut Providers) { pub fn provide(providers: &mut Providers) {
*providers = Providers { *providers = Providers {
@ -114,7 +113,7 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> {
} }
#[must_use] #[must_use]
#[derive(Debug, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
enum Promotability { enum Promotability {
Promotable, Promotable,
NotPromotable NotPromotable
@ -125,23 +124,25 @@ impl BitAnd for Promotability {
fn bitand(self, rhs: Self) -> Self { fn bitand(self, rhs: Self) -> Self {
match (self, rhs) { match (self, rhs) {
(Promotable, NotPromotable) => NotPromotable,
(NotPromotable, Promotable) => NotPromotable,
(NotPromotable, NotPromotable) => NotPromotable,
(Promotable, Promotable) => Promotable, (Promotable, Promotable) => Promotable,
_ => NotPromotable,
} }
} }
} }
impl BitAndAssign for Promotability {
fn bitand_assign(&mut self, rhs: Self) {
*self = *self & rhs
}
}
impl BitOr for Promotability { impl BitOr for Promotability {
type Output = Self; type Output = Self;
fn bitor(self, rhs: Self) -> Self { fn bitor(self, rhs: Self) -> Self {
match (self, rhs) { match (self, rhs) {
(Promotable, NotPromotable) => Promotable,
(NotPromotable, Promotable) => Promotable,
(NotPromotable, NotPromotable) => NotPromotable, (NotPromotable, NotPromotable) => NotPromotable,
(Promotable, Promotable) => Promotable, _ => Promotable,
} }
} }
} }
@ -161,7 +162,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
fn handle_const_fn_call(&mut self, def_id: DefId, fn handle_const_fn_call(&mut self, def_id: DefId,
ret_ty: Ty<'gcx>, span: Span) -> Promotability { ret_ty: Ty<'gcx>, span: Span) -> Promotability {
if let NotPromotable = self.type_promotability(ret_ty) { if self.type_promotability(ret_ty) == NotPromotable {
return NotPromotable; return NotPromotable;
} }
@ -266,9 +267,8 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
} }
} }
match local.init { if let Some(ref expr) = local.init {
Some(ref expr) => { let _ = self.check_expr(&expr); }, let _ = self.check_expr(&expr);
None => {},
} }
NotPromotable NotPromotable
} }
@ -287,7 +287,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
fn check_expr(&mut self, ex: &'tcx hir::Expr) -> Promotability { fn check_expr(&mut self, ex: &'tcx hir::Expr) -> Promotability {
let node_ty = self.tables.node_id_to_type(ex.hir_id); let node_ty = self.tables.node_id_to_type(ex.hir_id);
let mut outer = check_expr_kind(self, ex, node_ty); let mut outer = check_expr_kind(self, ex, node_ty);
outer = outer & check_adjustments(self, ex); outer &= check_adjustments(self, ex);
// Handle borrows on (or inside the autorefs of) this expression. // Handle borrows on (or inside the autorefs of) this expression.
if self.mut_rvalue_borrows.remove(&ex.id) { if self.mut_rvalue_borrows.remove(&ex.id) {
@ -303,7 +303,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
fn check_block(&mut self, block: &'tcx hir::Block) -> Promotability { fn check_block(&mut self, block: &'tcx hir::Block) -> Promotability {
let mut iter_result = Promotable; let mut iter_result = Promotable;
for index in block.stmts.iter() { for index in block.stmts.iter() {
iter_result = iter_result & self.check_stmt(index); iter_result &= self.check_stmt(index);
} }
match block.expr { match block.expr {
Some(ref box_expr) => iter_result & self.check_expr(&*box_expr), Some(ref box_expr) => iter_result & self.check_expr(&*box_expr),
@ -336,10 +336,7 @@ fn check_expr_kind<'a, 'tcx>(
} }
hir::ExprKind::Unary(op, ref expr) => { hir::ExprKind::Unary(op, ref expr) => {
let expr_promotability = v.check_expr(expr); let expr_promotability = v.check_expr(expr);
if v.tables.is_method_call(e) { if v.tables.is_method_call(e) || op == hir::UnDeref {
return NotPromotable;
}
if op == hir::UnDeref {
return NotPromotable; return NotPromotable;
} }
expr_promotability expr_promotability
@ -353,8 +350,8 @@ fn check_expr_kind<'a, 'tcx>(
match v.tables.node_id_to_type(lhs.hir_id).sty { match v.tables.node_id_to_type(lhs.hir_id).sty {
ty::RawPtr(_) => { ty::RawPtr(_) => {
assert!(op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne || assert!(op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne ||
op.node == hir::BinOpKind::Le || op.node == hir::BinOpKind::Lt || op.node == hir::BinOpKind::Le || op.node == hir::BinOpKind::Lt ||
op.node == hir::BinOpKind::Ge || op.node == hir::BinOpKind::Gt); op.node == hir::BinOpKind::Ge || op.node == hir::BinOpKind::Gt);
NotPromotable NotPromotable
} }
@ -400,7 +397,6 @@ fn check_expr_kind<'a, 'tcx>(
debug!("Reference to Static(id={:?}) is unpromotable as it is not \ debug!("Reference to Static(id={:?}) is unpromotable as it is not \
referenced from a static", did); referenced from a static", did);
NotPromotable NotPromotable
} }
} }
@ -425,7 +421,7 @@ fn check_expr_kind<'a, 'tcx>(
hir::ExprKind::Call(ref callee, ref hirvec) => { hir::ExprKind::Call(ref callee, ref hirvec) => {
let mut call_result = v.check_expr(callee); let mut call_result = v.check_expr(callee);
for index in hirvec.iter() { for index in hirvec.iter() {
call_result = call_result & v.check_expr(index); call_result &= v.check_expr(index);
} }
let mut callee = &**callee; let mut callee = &**callee;
loop { loop {
@ -464,7 +460,7 @@ fn check_expr_kind<'a, 'tcx>(
hir::ExprKind::MethodCall(ref _pathsegment, ref _span, ref hirvec) => { hir::ExprKind::MethodCall(ref _pathsegment, ref _span, ref hirvec) => {
let mut method_call_result = Promotable; let mut method_call_result = Promotable;
for index in hirvec.iter() { for index in hirvec.iter() {
method_call_result = method_call_result & v.check_expr(index); method_call_result &= v.check_expr(index);
} }
if let Some(def) = v.tables.type_dependent_defs().get(e.hir_id) { if let Some(def) = v.tables.type_dependent_defs().get(e.hir_id) {
let def_id = def.def_id(); let def_id = def.def_id();
@ -483,11 +479,10 @@ fn check_expr_kind<'a, 'tcx>(
hir::ExprKind::Struct(ref _qpath, ref hirvec, ref option_expr) => { hir::ExprKind::Struct(ref _qpath, ref hirvec, ref option_expr) => {
let mut struct_result = Promotable; let mut struct_result = Promotable;
for index in hirvec.iter() { for index in hirvec.iter() {
struct_result = struct_result & v.check_expr(&index.expr); struct_result &= v.check_expr(&index.expr);
} }
match *option_expr { if let Some(ref expr) = *option_expr {
Some(ref expr) => { struct_result = struct_result & v.check_expr(&expr); }, struct_result &= v.check_expr(&expr);
None => {},
} }
if let ty::Adt(adt, ..) = v.tables.expr_ty(e).sty { if let ty::Adt(adt, ..) = v.tables.expr_ty(e).sty {
// unsafe_cell_type doesn't necessarily exist with no_core // unsafe_cell_type doesn't necessarily exist with no_core
@ -506,7 +501,7 @@ fn check_expr_kind<'a, 'tcx>(
} }
hir::ExprKind::Closure(_capture_clause, ref _box_fn_decl, hir::ExprKind::Closure(_capture_clause, ref _box_fn_decl,
body_id, _span, _option_generator_movability) => { body_id, _span, _option_generator_movability) => {
let nested_body_promotable = v.check_nested_body(body_id); let nested_body_promotable = v.check_nested_body(body_id);
// Paths in constant contexts cannot refer to local variables, // Paths in constant contexts cannot refer to local variables,
// as there are none, and thus closures can't have upvars there. // as there are none, and thus closures can't have upvars there.
@ -543,7 +538,7 @@ fn check_expr_kind<'a, 'tcx>(
hir::ExprKind::Array(ref hirvec) => { hir::ExprKind::Array(ref hirvec) => {
let mut array_result = Promotable; let mut array_result = Promotable;
for index in hirvec.iter() { for index in hirvec.iter() {
array_result = array_result & v.check_expr(index); array_result &= v.check_expr(index);
} }
array_result array_result
} }
@ -555,7 +550,7 @@ fn check_expr_kind<'a, 'tcx>(
hir::ExprKind::Tup(ref hirvec) => { hir::ExprKind::Tup(ref hirvec) => {
let mut tup_result = Promotable; let mut tup_result = Promotable;
for index in hirvec.iter() { for index in hirvec.iter() {
tup_result = tup_result & v.check_expr(index); tup_result &= v.check_expr(index);
} }
tup_result tup_result
} }
@ -576,12 +571,9 @@ fn check_expr_kind<'a, 'tcx>(
let _ = v.check_expr(expr); let _ = v.check_expr(expr);
for index in hirvec_arm.iter() { for index in hirvec_arm.iter() {
let _ = v.check_expr(&*index.body); let _ = v.check_expr(&*index.body);
match index.guard { if let Some(hir::Guard::If(ref expr)) = index.guard {
Some(hir::Guard::If(ref expr)) => { let _ = v.check_expr(&expr);
let _ = v.check_expr(&expr); }
},
None => {},
};
} }
NotPromotable NotPromotable
} }
@ -589,10 +581,9 @@ fn check_expr_kind<'a, 'tcx>(
hir::ExprKind::If(ref lhs, ref rhs, ref option_expr) => { hir::ExprKind::If(ref lhs, ref rhs, ref option_expr) => {
let _ = v.check_expr(lhs); let _ = v.check_expr(lhs);
let _ = v.check_expr(rhs); let _ = v.check_expr(rhs);
match option_expr { if let Some(ref expr) = option_expr {
Some(ref expr) => { let _ = v.check_expr(&expr); }, let _ = v.check_expr(&expr);
None => {}, }
};
NotPromotable NotPromotable
} }
@ -610,9 +601,8 @@ fn check_expr_kind<'a, 'tcx>(
// More control flow (also not very meaningful). // More control flow (also not very meaningful).
hir::ExprKind::Break(_, ref option_expr) | hir::ExprKind::Ret(ref option_expr) => { hir::ExprKind::Break(_, ref option_expr) | hir::ExprKind::Ret(ref option_expr) => {
match *option_expr { if let Some(ref expr) = *option_expr {
Some(ref expr) => { let _ = v.check_expr(&expr); }, let _ = v.check_expr(&expr);
None => {},
} }
NotPromotable NotPromotable
} }
@ -635,10 +625,7 @@ fn check_expr_kind<'a, 'tcx>(
} }
hir::ExprKind::InlineAsm(ref _inline_asm, ref hirvec_lhs, ref hirvec_rhs) => { hir::ExprKind::InlineAsm(ref _inline_asm, ref hirvec_lhs, ref hirvec_rhs) => {
for index in hirvec_lhs.iter() { for index in hirvec_lhs.iter().chain(hirvec_rhs.iter()) {
let _ = v.check_expr(index);
}
for index in hirvec_rhs.iter() {
let _ = v.check_expr(index); let _ = v.check_expr(index);
} }
NotPromotable NotPromotable
@ -703,11 +690,8 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
// These occur when we convert a &T or *T to a *U, as well as // These occur when we convert a &T or *T to a *U, as well as
// when making a thin pointer (e.g., `*T`) into a fat pointer // when making a thin pointer (e.g., `*T`) into a fat pointer
// (e.g., `*Trait`). // (e.g., `*Trait`).
match loan_cause { if let euv::LoanCause::AutoUnsafe = loan_cause {
euv::LoanCause::AutoUnsafe => { return;
return;
}
_ => {}
} }
let mut cur = cmt; let mut cur = cmt;