Add AutoBorrowMutability
; its like hir::Mutability
but w/ two-phase borrow info too.
Namely, the mutable borrows also carries a flag indicating whether they should support two-phase borrows. This allows us to thread down, from the point of the borrow's introduction, whether the particular adjustment that created it is one that yields two-phase mutable borrows.
This commit is contained in:
parent
1855ab7424
commit
c8041dd8ac
@ -163,6 +163,20 @@ impl_stable_hash_for!(struct ty::adjustment::Adjustment<'tcx> { kind, target });
|
|||||||
impl_stable_hash_for!(struct ty::adjustment::OverloadedDeref<'tcx> { region, mutbl });
|
impl_stable_hash_for!(struct ty::adjustment::OverloadedDeref<'tcx> { region, mutbl });
|
||||||
impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region });
|
impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region });
|
||||||
|
|
||||||
|
impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::adjustment::AutoBorrowMutability {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'gcx>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||||
|
match *self {
|
||||||
|
ty::adjustment::AutoBorrowMutability::Mutable { ref allow_two_phase_borrow } => {
|
||||||
|
allow_two_phase_borrow.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
|
ty::adjustment::AutoBorrowMutability::Immutable => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
|
impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
|
||||||
|
|
||||||
impl_stable_hash_for!(enum ty::BorrowKind {
|
impl_stable_hash_for!(enum ty::BorrowKind {
|
||||||
|
@ -760,7 +760,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
|||||||
expr.span,
|
expr.span,
|
||||||
cmt_base,
|
cmt_base,
|
||||||
r,
|
r,
|
||||||
ty::BorrowKind::from_mutbl(m),
|
ty::BorrowKind::from_mutbl(m.into()),
|
||||||
AutoRef);
|
AutoRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,10 +119,25 @@ impl<'a, 'gcx, 'tcx> OverloadedDeref<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
|
||||||
|
pub enum AutoBorrowMutability {
|
||||||
|
Mutable { allow_two_phase_borrow: bool },
|
||||||
|
Immutable,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AutoBorrowMutability> for hir::Mutability {
|
||||||
|
fn from(m: AutoBorrowMutability) -> Self {
|
||||||
|
match m {
|
||||||
|
AutoBorrowMutability::Mutable { .. } => hir::MutMutable,
|
||||||
|
AutoBorrowMutability::Immutable => hir::MutImmutable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
|
#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
|
||||||
pub enum AutoBorrow<'tcx> {
|
pub enum AutoBorrow<'tcx> {
|
||||||
/// Convert from T to &T.
|
/// Convert from T to &T.
|
||||||
Ref(ty::Region<'tcx>, hir::Mutability),
|
Ref(ty::Region<'tcx>, AutoBorrowMutability),
|
||||||
|
|
||||||
/// Convert from T to *T.
|
/// Convert from T to *T.
|
||||||
RawPtr(hir::Mutability),
|
RawPtr(hir::Mutability),
|
||||||
|
@ -437,8 +437,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation {
|
|||||||
for adj in cx.tables.expr_adjustments(e) {
|
for adj in cx.tables.expr_adjustments(e) {
|
||||||
if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
|
if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
|
||||||
let msg = match m {
|
let msg = match m {
|
||||||
hir::MutImmutable => "unnecessary allocation, use & instead",
|
adjustment::AutoBorrowMutability::Immutable =>
|
||||||
hir::MutMutable => "unnecessary allocation, use &mut instead"
|
"unnecessary allocation, use & instead",
|
||||||
|
adjustment::AutoBorrowMutability::Mutable { .. }=>
|
||||||
|
"unnecessary allocation, use &mut instead"
|
||||||
};
|
};
|
||||||
cx.span_lint(UNUSED_ALLOCATION, e.span, msg);
|
cx.span_lint(UNUSED_ALLOCATION, e.span, msg);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ use hair::cx::to_ref::ToRef;
|
|||||||
use rustc::hir::def::{Def, CtorKind};
|
use rustc::hir::def::{Def, CtorKind};
|
||||||
use rustc::middle::const_val::ConstVal;
|
use rustc::middle::const_val::ConstVal;
|
||||||
use rustc::ty::{self, AdtKind, VariantDef, Ty};
|
use rustc::ty::{self, AdtKind, VariantDef, Ty};
|
||||||
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
|
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
|
||||||
use rustc::ty::cast::CastKind as TyCastKind;
|
use rustc::ty::cast::CastKind as TyCastKind;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::def_id::LocalDefId;
|
use rustc::hir::def_id::LocalDefId;
|
||||||
@ -112,7 +112,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
span,
|
span,
|
||||||
kind: ExprKind::Borrow {
|
kind: ExprKind::Borrow {
|
||||||
region: deref.region,
|
region: deref.region,
|
||||||
borrow_kind: to_borrow_kind(deref.mutbl, true),
|
borrow_kind: deref.mutbl.to_borrow_kind(),
|
||||||
arg: expr.to_ref(),
|
arg: expr.to_ref(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -122,7 +122,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
Adjust::Borrow(AutoBorrow::Ref(r, m)) => {
|
Adjust::Borrow(AutoBorrow::Ref(r, m)) => {
|
||||||
ExprKind::Borrow {
|
ExprKind::Borrow {
|
||||||
region: r,
|
region: r,
|
||||||
borrow_kind: to_borrow_kind(m, true),
|
borrow_kind: m.to_borrow_kind(),
|
||||||
arg: expr.to_ref(),
|
arg: expr.to_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,7 +142,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
span,
|
span,
|
||||||
kind: ExprKind::Borrow {
|
kind: ExprKind::Borrow {
|
||||||
region,
|
region,
|
||||||
borrow_kind: to_borrow_kind(m, true),
|
borrow_kind: m.to_borrow_kind(),
|
||||||
arg: expr.to_ref(),
|
arg: expr.to_ref(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -288,7 +288,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
};
|
};
|
||||||
ExprKind::Borrow {
|
ExprKind::Borrow {
|
||||||
region,
|
region,
|
||||||
borrow_kind: to_borrow_kind(mutbl, false),
|
borrow_kind: mutbl.to_borrow_kind(),
|
||||||
arg: expr.to_ref(),
|
arg: expr.to_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -643,10 +643,25 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_borrow_kind(m: hir::Mutability, allow_two_phase_borrow: bool) -> BorrowKind {
|
trait ToBorrowKind { fn to_borrow_kind(&self) -> BorrowKind; }
|
||||||
match m {
|
|
||||||
hir::MutMutable => BorrowKind::Mut { allow_two_phase_borrow },
|
impl ToBorrowKind for AutoBorrowMutability {
|
||||||
hir::MutImmutable => BorrowKind::Shared,
|
fn to_borrow_kind(&self) -> BorrowKind {
|
||||||
|
match *self {
|
||||||
|
AutoBorrowMutability::Mutable { allow_two_phase_borrow } =>
|
||||||
|
BorrowKind::Mut { allow_two_phase_borrow },
|
||||||
|
AutoBorrowMutability::Immutable =>
|
||||||
|
BorrowKind::Shared,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToBorrowKind for hir::Mutability {
|
||||||
|
fn to_borrow_kind(&self) -> BorrowKind {
|
||||||
|
match *self {
|
||||||
|
hir::MutMutable => BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||||
|
hir::MutImmutable => BorrowKind::Shared,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ use hir::def::Def;
|
|||||||
use hir::def_id::{DefId, LOCAL_CRATE};
|
use hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc::{infer, traits};
|
use rustc::{infer, traits};
|
||||||
use rustc::ty::{self, TyCtxt, TypeFoldable, Ty};
|
use rustc::ty::{self, TyCtxt, TypeFoldable, Ty};
|
||||||
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
|
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
@ -176,8 +176,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
let mut autoref = None;
|
let mut autoref = None;
|
||||||
if borrow {
|
if borrow {
|
||||||
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
||||||
|
let mutbl = match mt.mutbl {
|
||||||
|
hir::MutImmutable => AutoBorrowMutability::Immutable,
|
||||||
|
hir::MutMutable => AutoBorrowMutability::Mutable {
|
||||||
|
// For initial two-phase borrow
|
||||||
|
// deployment, conservatively omit
|
||||||
|
// overloaded function call ops.
|
||||||
|
allow_two_phase_borrow: false,
|
||||||
|
}
|
||||||
|
};
|
||||||
autoref = Some(Adjustment {
|
autoref = Some(Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
|
||||||
target: method.sig.inputs()[0]
|
target: method.sig.inputs()[0]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ use rustc::infer::{Coercion, InferResult, InferOk};
|
|||||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||||
use rustc::lint;
|
use rustc::lint;
|
||||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
|
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
|
||||||
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
|
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
|
||||||
use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts};
|
use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts};
|
||||||
use rustc::ty::fold::TypeFoldable;
|
use rustc::ty::fold::TypeFoldable;
|
||||||
use rustc::ty::error::TypeError;
|
use rustc::ty::error::TypeError;
|
||||||
@ -421,8 +421,17 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
|
|||||||
ty::TyRef(r_borrow, _) => r_borrow,
|
ty::TyRef(r_borrow, _) => r_borrow,
|
||||||
_ => span_bug!(span, "expected a ref type, got {:?}", ty),
|
_ => span_bug!(span, "expected a ref type, got {:?}", ty),
|
||||||
};
|
};
|
||||||
|
let mutbl = match mt_b.mutbl {
|
||||||
|
hir::MutImmutable => AutoBorrowMutability::Immutable,
|
||||||
|
hir::MutMutable => AutoBorrowMutability::Mutable {
|
||||||
|
// Deref-coercion is a case where we deliberately
|
||||||
|
// disallow two-phase borrows in its initial
|
||||||
|
// deployment; see discussion on PR #47489.
|
||||||
|
allow_two_phase_borrow: false,
|
||||||
|
}
|
||||||
|
};
|
||||||
adjustments.push(Adjustment {
|
adjustments.push(Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mt_b.mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mutbl)),
|
||||||
target: ty
|
target: ty
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -461,11 +470,17 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
let coercion = Coercion(self.cause.span);
|
let coercion = Coercion(self.cause.span);
|
||||||
let r_borrow = self.next_region_var(coercion);
|
let r_borrow = self.next_region_var(coercion);
|
||||||
|
let mutbl = match mt_b.mutbl {
|
||||||
|
hir::MutImmutable => AutoBorrowMutability::Immutable,
|
||||||
|
hir::MutMutable => AutoBorrowMutability::Mutable {
|
||||||
|
allow_two_phase_borrow: false,
|
||||||
|
}
|
||||||
|
};
|
||||||
Some((Adjustment {
|
Some((Adjustment {
|
||||||
kind: Adjust::Deref(None),
|
kind: Adjust::Deref(None),
|
||||||
target: mt_a.ty
|
target: mt_a.ty
|
||||||
}, Adjustment {
|
}, Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mt_b.mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(r_borrow, mutbl)),
|
||||||
target: self.tcx.mk_ref(r_borrow, ty::TypeAndMut {
|
target: self.tcx.mk_ref(r_borrow, ty::TypeAndMut {
|
||||||
mutbl: mt_b.mutbl,
|
mutbl: mt_b.mutbl,
|
||||||
ty: mt_a.ty
|
ty: mt_a.ty
|
||||||
@ -871,6 +886,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
] => {
|
] => {
|
||||||
match self.node_ty(expr.hir_id).sty {
|
match self.node_ty(expr.hir_id).sty {
|
||||||
ty::TyRef(_, mt_orig) => {
|
ty::TyRef(_, mt_orig) => {
|
||||||
|
let mutbl_adj: hir::Mutability = mutbl_adj.into();
|
||||||
// Reborrow that we can safely ignore, because
|
// Reborrow that we can safely ignore, because
|
||||||
// the next adjustment can only be a Deref
|
// the next adjustment can only be a Deref
|
||||||
// which will be merged into it.
|
// which will be merged into it.
|
||||||
|
@ -17,7 +17,7 @@ use rustc::ty::subst::Substs;
|
|||||||
use rustc::traits;
|
use rustc::traits;
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::subst::Subst;
|
use rustc::ty::subst::Subst;
|
||||||
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, OverloadedDeref};
|
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability, OverloadedDeref};
|
||||||
use rustc::ty::fold::TypeFoldable;
|
use rustc::ty::fold::TypeFoldable;
|
||||||
use rustc::infer::{self, InferOk};
|
use rustc::infer::{self, InferOk};
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
@ -165,6 +165,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||||||
mutbl,
|
mutbl,
|
||||||
ty: target
|
ty: target
|
||||||
});
|
});
|
||||||
|
let mutbl = match mutbl {
|
||||||
|
hir::MutImmutable => AutoBorrowMutability::Immutable,
|
||||||
|
hir::MutMutable => AutoBorrowMutability::Mutable {
|
||||||
|
// Method call receivers are the primary use case
|
||||||
|
// for two-phase borrows.
|
||||||
|
allow_two_phase_borrow: true,
|
||||||
|
}
|
||||||
|
};
|
||||||
adjustments.push(Adjustment {
|
adjustments.push(Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
|
||||||
target
|
target
|
||||||
@ -172,7 +180,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
if let Some(unsize_target) = pick.unsize {
|
if let Some(unsize_target) = pick.unsize {
|
||||||
target = self.tcx.mk_ref(region, ty::TypeAndMut {
|
target = self.tcx.mk_ref(region, ty::TypeAndMut {
|
||||||
mutbl,
|
mutbl: mutbl.into(),
|
||||||
ty: unsize_target
|
ty: unsize_target
|
||||||
});
|
});
|
||||||
adjustments.push(Adjustment {
|
adjustments.push(Adjustment {
|
||||||
@ -530,10 +538,19 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||||||
for adjustment in &mut adjustments[..] {
|
for adjustment in &mut adjustments[..] {
|
||||||
if let Adjust::Borrow(AutoBorrow::Ref(..)) = adjustment.kind {
|
if let Adjust::Borrow(AutoBorrow::Ref(..)) = adjustment.kind {
|
||||||
debug!("convert_place_op_to_mutable: converting autoref {:?}", adjustment);
|
debug!("convert_place_op_to_mutable: converting autoref {:?}", adjustment);
|
||||||
|
let mutbl = match mutbl {
|
||||||
|
hir::MutImmutable => AutoBorrowMutability::Immutable,
|
||||||
|
hir::MutMutable => AutoBorrowMutability::Mutable {
|
||||||
|
// For initial two-phase borrow
|
||||||
|
// deployment, conservatively omit
|
||||||
|
// overloaded operators.
|
||||||
|
allow_two_phase_borrow: false,
|
||||||
|
}
|
||||||
|
};
|
||||||
adjustment.kind = Adjust::Borrow(AutoBorrow::Ref(region, mutbl));
|
adjustment.kind = Adjust::Borrow(AutoBorrow::Ref(region, mutbl));
|
||||||
adjustment.target = self.tcx.mk_ref(region, ty::TypeAndMut {
|
adjustment.target = self.tcx.mk_ref(region, ty::TypeAndMut {
|
||||||
ty: source,
|
ty: source,
|
||||||
mutbl
|
mutbl: mutbl.into(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
source = adjustment.target;
|
source = adjustment.target;
|
||||||
|
@ -96,7 +96,7 @@ use rustc::middle::region;
|
|||||||
use rustc::ty::subst::{Kind, Subst, Substs};
|
use rustc::ty::subst::{Kind, Subst, Substs};
|
||||||
use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode};
|
use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode};
|
||||||
use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate};
|
use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate};
|
||||||
use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
|
use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
||||||
use rustc::ty::fold::TypeFoldable;
|
use rustc::ty::fold::TypeFoldable;
|
||||||
use rustc::ty::maps::Providers;
|
use rustc::ty::maps::Providers;
|
||||||
use rustc::ty::util::{Representability, IntTypeExt};
|
use rustc::ty::util::{Representability, IntTypeExt};
|
||||||
@ -2357,8 +2357,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
|
|
||||||
let mut adjustments = autoderef.adjust_steps(needs);
|
let mut adjustments = autoderef.adjust_steps(needs);
|
||||||
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
||||||
|
let mutbl = match mt.mutbl {
|
||||||
|
hir::MutImmutable => AutoBorrowMutability::Immutable,
|
||||||
|
hir::MutMutable => AutoBorrowMutability::Mutable {
|
||||||
|
// FIXME (#46747): arguably indexing is
|
||||||
|
// "just another kind of call"; perhaps it
|
||||||
|
// would be more consistent to allow
|
||||||
|
// two-phase borrows for .index()
|
||||||
|
// receivers here.
|
||||||
|
allow_two_phase_borrow: false,
|
||||||
|
}
|
||||||
|
};
|
||||||
adjustments.push(Adjustment {
|
adjustments.push(Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
|
||||||
target: self.tcx.mk_ref(region, ty::TypeAndMut {
|
target: self.tcx.mk_ref(region, ty::TypeAndMut {
|
||||||
mutbl: mt.mutbl,
|
mutbl: mt.mutbl,
|
||||||
ty: adjusted_ty
|
ty: adjusted_ty
|
||||||
@ -3646,8 +3657,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
expr.span, oprnd_t, needs) {
|
expr.span, oprnd_t, needs) {
|
||||||
let method = self.register_infer_ok_obligations(ok);
|
let method = self.register_infer_ok_obligations(ok);
|
||||||
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
||||||
|
let mutbl = match mt.mutbl {
|
||||||
|
hir::MutImmutable => AutoBorrowMutability::Immutable,
|
||||||
|
hir::MutMutable => AutoBorrowMutability::Mutable {
|
||||||
|
// (It shouldn't actually matter for unary ops whether
|
||||||
|
// we enable two-phase borrows or not, since a unary
|
||||||
|
// op has no additional operands.)
|
||||||
|
allow_two_phase_borrow: false,
|
||||||
|
}
|
||||||
|
};
|
||||||
self.apply_adjustments(oprnd, vec![Adjustment {
|
self.apply_adjustments(oprnd, vec![Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
|
||||||
target: method.sig.inputs()[0]
|
target: method.sig.inputs()[0]
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use super::{FnCtxt, Needs};
|
|||||||
use super::method::MethodCallee;
|
use super::method::MethodCallee;
|
||||||
use rustc::ty::{self, Ty, TypeFoldable, TypeVariants};
|
use rustc::ty::{self, Ty, TypeFoldable, TypeVariants};
|
||||||
use rustc::ty::TypeVariants::{TyStr, TyRef};
|
use rustc::ty::TypeVariants::{TyStr, TyRef};
|
||||||
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
|
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
|
||||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||||
use errors;
|
use errors;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
@ -198,8 +198,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
let by_ref_binop = !op.node.is_by_value();
|
let by_ref_binop = !op.node.is_by_value();
|
||||||
if is_assign == IsAssign::Yes || by_ref_binop {
|
if is_assign == IsAssign::Yes || by_ref_binop {
|
||||||
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
if let ty::TyRef(region, mt) = method.sig.inputs()[0].sty {
|
||||||
|
let mutbl = match mt.mutbl {
|
||||||
|
hir::MutImmutable => AutoBorrowMutability::Immutable,
|
||||||
|
hir::MutMutable => AutoBorrowMutability::Mutable {
|
||||||
|
// For initial two-phase borrow
|
||||||
|
// deployment, conservatively omit
|
||||||
|
// overloaded binary ops.
|
||||||
|
allow_two_phase_borrow: false,
|
||||||
|
}
|
||||||
|
};
|
||||||
let autoref = Adjustment {
|
let autoref = Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
|
||||||
target: method.sig.inputs()[0]
|
target: method.sig.inputs()[0]
|
||||||
};
|
};
|
||||||
self.apply_adjustments(lhs_expr, vec![autoref]);
|
self.apply_adjustments(lhs_expr, vec![autoref]);
|
||||||
@ -207,8 +216,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
if by_ref_binop {
|
if by_ref_binop {
|
||||||
if let ty::TyRef(region, mt) = method.sig.inputs()[1].sty {
|
if let ty::TyRef(region, mt) = method.sig.inputs()[1].sty {
|
||||||
|
let mutbl = match mt.mutbl {
|
||||||
|
hir::MutImmutable => AutoBorrowMutability::Immutable,
|
||||||
|
hir::MutMutable => AutoBorrowMutability::Mutable {
|
||||||
|
// For initial two-phase borrow
|
||||||
|
// deployment, conservatively omit
|
||||||
|
// overloaded binary ops.
|
||||||
|
allow_two_phase_borrow: false,
|
||||||
|
}
|
||||||
|
};
|
||||||
let autoref = Adjustment {
|
let autoref = Adjustment {
|
||||||
kind: Adjust::Borrow(AutoBorrow::Ref(region, mt.mutbl)),
|
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
|
||||||
target: method.sig.inputs()[1]
|
target: method.sig.inputs()[1]
|
||||||
};
|
};
|
||||||
// HACK(eddyb) Bypass checks due to reborrows being in
|
// HACK(eddyb) Bypass checks due to reborrows being in
|
||||||
|
@ -1063,7 +1063,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
|||||||
match *autoref {
|
match *autoref {
|
||||||
adjustment::AutoBorrow::Ref(r, m) => {
|
adjustment::AutoBorrow::Ref(r, m) => {
|
||||||
self.link_region(expr.span, r,
|
self.link_region(expr.span, r,
|
||||||
ty::BorrowKind::from_mutbl(m), expr_cmt);
|
ty::BorrowKind::from_mutbl(m.into()), expr_cmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustment::AutoBorrow::RawPtr(m) => {
|
adjustment::AutoBorrow::RawPtr(m) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user