Don't promote to 'static the result of dereferences.

This commit is contained in:
Eduard-Mihai Burtescu 2018-01-12 23:46:23 +02:00
parent 6cf081c8c5
commit 121499a119
2 changed files with 46 additions and 15 deletions

View file

@ -491,9 +491,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
this.add(Qualif::STATIC);
}
this.add(Qualif::NOT_CONST);
let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
if let ty::TyRawPtr(_) = base_ty.sty {
this.add(Qualif::NOT_CONST);
if this.mode != Mode::Fn {
struct_span_err!(this.tcx.sess,
this.span, E0396,
@ -570,7 +571,38 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
// Recurse through operands and places.
self.super_rvalue(rvalue, location);
if let Rvalue::Ref(region, kind, ref place) = *rvalue {
let mut is_reborrow = false;
if let Place::Projection(ref proj) = *place {
if let ProjectionElem::Deref = proj.elem {
let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
if let ty::TyRef(..) = base_ty.sty {
is_reborrow = true;
}
}
}
if is_reborrow {
self.nest(|this| {
this.super_place(place, PlaceContext::Borrow {
region,
kind
}, location);
if !this.try_consume() {
return;
}
if this.qualif.intersects(Qualif::STATIC_REF) {
this.qualif = this.qualif - Qualif::STATIC_REF;
this.add(Qualif::STATIC);
}
});
} else {
self.super_rvalue(rvalue, location);
}
} else {
self.super_rvalue(rvalue, location);
}
match *rvalue {
Rvalue::Use(_) |

View file

@ -352,14 +352,9 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
hir::ExprBox(_) => {
v.promotable = false;
}
hir::ExprUnary(op, ref inner) => {
match v.tables.node_id_to_type(inner.hir_id).sty {
ty::TyRawPtr(_) => {
assert!(op == hir::UnDeref);
v.promotable = false;
}
_ => {}
hir::ExprUnary(op, _) => {
if op == hir::UnDeref {
v.promotable = false;
}
}
hir::ExprBinary(op, ref lhs, _) => {
@ -548,7 +543,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
use rustc::ty::adjustment::*;
for adjustment in v.tables.expr_adjustments(e) {
let mut adjustments = v.tables.expr_adjustments(e).iter().peekable();
while let Some(adjustment) = adjustments.next() {
match adjustment.kind {
Adjust::NeverToAny |
Adjust::ReifyFnPointer |
@ -558,11 +554,14 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
Adjust::Borrow(_) |
Adjust::Unsize => {}
Adjust::Deref(ref overloaded) => {
if overloaded.is_some() {
v.promotable = false;
break;
Adjust::Deref(_) => {
if let Some(next_adjustment) = adjustments.peek() {
if let Adjust::Borrow(_) = next_adjustment.kind {
continue;
}
}
v.promotable = false;
break;
}
}
}