rustc: avoid using MethodCallee's signature where possible.
This commit is contained in:
parent
22510f3266
commit
a65ced5d16
12 changed files with 147 additions and 163 deletions
|
@ -412,15 +412,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||||
pred: CFGIndex,
|
pred: CFGIndex,
|
||||||
func_or_rcvr: &hir::Expr,
|
func_or_rcvr: &hir::Expr,
|
||||||
args: I) -> CFGIndex {
|
args: I) -> CFGIndex {
|
||||||
let fn_ty = match self.tables.method_map.get(&call_expr.id) {
|
|
||||||
Some(method) => method.ty,
|
|
||||||
None => self.tables.expr_ty_adjusted(func_or_rcvr),
|
|
||||||
};
|
|
||||||
|
|
||||||
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
|
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
|
||||||
let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
|
let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
|
||||||
// FIXME(canndrew): This is_never should probably be an is_uninhabited.
|
// FIXME(canndrew): This is_never should probably be an is_uninhabited.
|
||||||
if fn_ty.fn_ret().0.is_never() {
|
if self.tables.expr_ty(call_expr).is_never() {
|
||||||
self.add_unreachable_node()
|
self.add_unreachable_node()
|
||||||
} else {
|
} else {
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -173,10 +173,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
hir::ExprMethodCall(..) => {
|
hir::ExprMethodCall(..) => {
|
||||||
let method_sig = self.tables.method_map[&expr.id].sig;
|
let method = self.tables.method_map[&expr.id];
|
||||||
|
let base_type = self.tcx.type_of(method.def_id);
|
||||||
debug!("effect: method call case, base type is {:?}",
|
debug!("effect: method call case, base type is {:?}",
|
||||||
method_sig);
|
base_type);
|
||||||
if method_sig.unsafety == hir::Unsafety::Unsafe {
|
if type_is_unsafe_function(base_type) {
|
||||||
self.require_unsafe(expr.span,
|
self.require_unsafe(expr.span,
|
||||||
"invocation of unsafe method")
|
"invocation of unsafe method")
|
||||||
}
|
}
|
||||||
|
|
|
@ -761,8 +761,10 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
let bk = ty::BorrowKind::from_mutbl(m);
|
let bk = ty::BorrowKind::from_mutbl(m);
|
||||||
self.delegate.borrow(expr.id, expr.span, cmt.clone(),
|
self.delegate.borrow(expr.id, expr.span, cmt.clone(),
|
||||||
r, bk, AutoRef);
|
r, bk, AutoRef);
|
||||||
|
cmt = self.mc.cat_overloaded_autoderef(expr, method)?;
|
||||||
|
} else {
|
||||||
|
cmt = self.mc.cat_deref(expr, cmt, false)?;
|
||||||
}
|
}
|
||||||
cmt = self.mc.cat_deref(expr, cmt, overloaded)?;
|
|
||||||
}
|
}
|
||||||
Ok(cmt)
|
Ok(cmt)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1072,9 +1072,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||||
|
|
||||||
hir::ExprCall(ref f, ref args) => {
|
hir::ExprCall(ref f, ref args) => {
|
||||||
// FIXME(canndrew): This is_never should really be an is_uninhabited
|
// FIXME(canndrew): This is_never should really be an is_uninhabited
|
||||||
let diverges = !self.tables.is_method_call(expr.id) &&
|
let succ = if self.tables.expr_ty(expr).is_never() {
|
||||||
self.tables.expr_ty_adjusted(&f).fn_sig().output().0.is_never();
|
|
||||||
let succ = if diverges {
|
|
||||||
self.s.exit_ln
|
self.s.exit_ln
|
||||||
} else {
|
} else {
|
||||||
succ
|
succ
|
||||||
|
@ -1084,9 +1082,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprMethodCall(.., ref args) => {
|
hir::ExprMethodCall(.., ref args) => {
|
||||||
let ret_ty = self.tables.method_map[&expr.id].sig.output();
|
|
||||||
// FIXME(canndrew): This is_never should really be an is_uninhabited
|
// FIXME(canndrew): This is_never should really be an is_uninhabited
|
||||||
let succ = if ret_ty.is_never() {
|
let succ = if self.tables.expr_ty(expr).is_never() {
|
||||||
self.s.exit_ln
|
self.s.exit_ln
|
||||||
} else {
|
} else {
|
||||||
succ
|
succ
|
||||||
|
|
|
@ -63,7 +63,6 @@
|
||||||
pub use self::PointerKind::*;
|
pub use self::PointerKind::*;
|
||||||
pub use self::InteriorKind::*;
|
pub use self::InteriorKind::*;
|
||||||
pub use self::FieldName::*;
|
pub use self::FieldName::*;
|
||||||
pub use self::ElementKind::*;
|
|
||||||
pub use self::MutabilityCategory::*;
|
pub use self::MutabilityCategory::*;
|
||||||
pub use self::AliasableReason::*;
|
pub use self::AliasableReason::*;
|
||||||
pub use self::Note::*;
|
pub use self::Note::*;
|
||||||
|
@ -129,7 +128,7 @@ pub enum PointerKind<'tcx> {
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum InteriorKind {
|
pub enum InteriorKind {
|
||||||
InteriorField(FieldName),
|
InteriorField(FieldName),
|
||||||
InteriorElement(InteriorOffsetKind, ElementKind),
|
InteriorElement(InteriorOffsetKind),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
|
@ -144,12 +143,6 @@ pub enum InteriorOffsetKind {
|
||||||
Pattern, // e.g. `fn foo([_, a, _, _]: [A; 4]) { ... }`
|
Pattern, // e.g. `fn foo([_, a, _, _]: [A; 4]) { ... }`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
|
||||||
pub enum ElementKind {
|
|
||||||
VecElement,
|
|
||||||
OtherElement,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
pub enum MutabilityCategory {
|
pub enum MutabilityCategory {
|
||||||
McImmutable, // Immutable.
|
McImmutable, // Immutable.
|
||||||
|
@ -492,7 +485,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
debug!("cat_expr: autoderefs={:?}, cmt={:?}",
|
debug!("cat_expr: autoderefs={:?}, cmt={:?}",
|
||||||
autoderefs, cmt);
|
autoderefs, cmt);
|
||||||
for &overloaded in autoderefs {
|
for &overloaded in autoderefs {
|
||||||
cmt = self.cat_deref(expr, cmt, overloaded)?;
|
if let Some(method) = overloaded {
|
||||||
|
cmt = self.cat_overloaded_autoderef(expr, method)?;
|
||||||
|
} else {
|
||||||
|
cmt = self.cat_deref(expr, cmt, false)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Ok(cmt);
|
return Ok(cmt);
|
||||||
}
|
}
|
||||||
|
@ -518,10 +515,12 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
let expr_ty = self.expr_ty(expr)?;
|
let expr_ty = self.expr_ty(expr)?;
|
||||||
match expr.node {
|
match expr.node {
|
||||||
hir::ExprUnary(hir::UnDeref, ref e_base) => {
|
hir::ExprUnary(hir::UnDeref, ref e_base) => {
|
||||||
let base_cmt = self.cat_expr(&e_base)?;
|
if self.infcx.tables.borrow().is_method_call(expr.id) {
|
||||||
let method = self.infcx.tables.borrow().method_map
|
self.cat_overloaded_lvalue(expr, e_base, false)
|
||||||
.get(&expr.id).cloned();
|
} else {
|
||||||
self.cat_deref(expr, base_cmt, method)
|
let base_cmt = self.cat_expr(&e_base)?;
|
||||||
|
self.cat_deref(expr, base_cmt, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprField(ref base, f_name) => {
|
hir::ExprField(ref base, f_name) => {
|
||||||
|
@ -539,33 +538,16 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprIndex(ref base, _) => {
|
hir::ExprIndex(ref base, _) => {
|
||||||
let method = self.infcx.tables.borrow().method_map.get(&expr.id()).cloned();
|
if self.infcx.tables.borrow().is_method_call(expr.id()) {
|
||||||
match method {
|
// If this is an index implemented by a method call, then it
|
||||||
Some(method) => {
|
// will include an implicit deref of the result.
|
||||||
// If this is an index implemented by a method call, then it
|
// The call to index() returns a `&T` value, which
|
||||||
// will include an implicit deref of the result.
|
// is an rvalue. That is what we will be
|
||||||
let ret_ty = self.overloaded_method_return_ty(method);
|
// dereferencing.
|
||||||
|
self.cat_overloaded_lvalue(expr, base, true)
|
||||||
// The index method always returns an `&T`, so
|
} else {
|
||||||
// dereference it to find the result type.
|
let base_cmt = self.cat_expr(&base)?;
|
||||||
let elem_ty = match ret_ty.sty {
|
self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index)
|
||||||
ty::TyRef(_, mt) => mt.ty,
|
|
||||||
_ => {
|
|
||||||
debug!("cat_expr_unadjusted: return type of overloaded index is {:?}?",
|
|
||||||
ret_ty);
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// The call to index() returns a `&T` value, which
|
|
||||||
// is an rvalue. That is what we will be
|
|
||||||
// dereferencing.
|
|
||||||
let base_cmt = self.cat_rvalue_node(expr.id(), expr.span(), ret_ty);
|
|
||||||
Ok(self.cat_deref_common(expr, base_cmt, elem_ty, true))
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.cat_index(expr, self.cat_expr(&base)?, InteriorOffsetKind::Index)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -924,42 +906,63 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cat_overloaded_lvalue(&self,
|
||||||
|
expr: &hir::Expr,
|
||||||
|
base: &hir::Expr,
|
||||||
|
implicit: bool)
|
||||||
|
-> McResult<cmt<'tcx>> {
|
||||||
|
debug!("cat_overloaded_lvalue: implicit={}", implicit);
|
||||||
|
|
||||||
|
// Reconstruct the output assuming it's a reference with the
|
||||||
|
// same region and mutability as the receiver. This holds for
|
||||||
|
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
|
||||||
|
let lvalue_ty = self.expr_ty(expr)?;
|
||||||
|
let base_ty = self.expr_ty_adjusted(base)?;
|
||||||
|
|
||||||
|
let (region, mutbl) = match base_ty.sty {
|
||||||
|
ty::TyRef(region, mt) => (region, mt.mutbl),
|
||||||
|
_ => {
|
||||||
|
span_bug!(expr.span, "cat_overloaded_lvalue: base is not a reference")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let ref_ty = self.tcx().mk_ref(region, ty::TypeAndMut {
|
||||||
|
ty: lvalue_ty,
|
||||||
|
mutbl,
|
||||||
|
});
|
||||||
|
|
||||||
|
let base_cmt = self.cat_rvalue_node(expr.id, expr.span, ref_ty);
|
||||||
|
self.cat_deref(expr, base_cmt, implicit)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cat_overloaded_autoderef(&self,
|
||||||
|
expr: &hir::Expr,
|
||||||
|
method: ty::MethodCallee<'tcx>)
|
||||||
|
-> McResult<cmt<'tcx>> {
|
||||||
|
debug!("cat_overloaded_autoderef: method={:?}", method);
|
||||||
|
|
||||||
|
let ref_ty = method.sig.output();
|
||||||
|
let ref_ty = self.infcx.resolve_type_vars_if_possible(&ref_ty);
|
||||||
|
let base_cmt = self.cat_rvalue_node(expr.id, expr.span, ref_ty);
|
||||||
|
self.cat_deref(expr, base_cmt, false)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cat_deref<N:ast_node>(&self,
|
pub fn cat_deref<N:ast_node>(&self,
|
||||||
node: &N,
|
node: &N,
|
||||||
base_cmt: cmt<'tcx>,
|
base_cmt: cmt<'tcx>,
|
||||||
overloaded: Option<ty::MethodCallee<'tcx>>)
|
implicit: bool)
|
||||||
-> McResult<cmt<'tcx>> {
|
-> McResult<cmt<'tcx>> {
|
||||||
debug!("cat_deref: overloaded={:?}", overloaded);
|
debug!("cat_deref: base_cmt={:?}", base_cmt);
|
||||||
|
|
||||||
let base_cmt = match overloaded {
|
|
||||||
Some(method) => {
|
|
||||||
let ref_ty = self.overloaded_method_return_ty(method);
|
|
||||||
self.cat_rvalue_node(node.id(), node.span(), ref_ty)
|
|
||||||
}
|
|
||||||
None => base_cmt
|
|
||||||
};
|
|
||||||
let base_cmt_ty = base_cmt.ty;
|
let base_cmt_ty = base_cmt.ty;
|
||||||
match base_cmt_ty.builtin_deref(true, ty::NoPreference) {
|
let deref_ty = match base_cmt_ty.builtin_deref(true, ty::NoPreference) {
|
||||||
Some(mt) => {
|
Some(mt) => mt.ty,
|
||||||
let ret = self.cat_deref_common(node, base_cmt, mt.ty, false);
|
|
||||||
debug!("cat_deref ret {:?}", ret);
|
|
||||||
Ok(ret)
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
debug!("Explicit deref of non-derefable type: {:?}",
|
debug!("Explicit deref of non-derefable type: {:?}",
|
||||||
base_cmt_ty);
|
base_cmt_ty);
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
fn cat_deref_common<N:ast_node>(&self,
|
|
||||||
node: &N,
|
|
||||||
base_cmt: cmt<'tcx>,
|
|
||||||
deref_ty: Ty<'tcx>,
|
|
||||||
implicit: bool)
|
|
||||||
-> cmt<'tcx>
|
|
||||||
{
|
|
||||||
let ptr = match base_cmt.ty.sty {
|
let ptr = match base_cmt.ty.sty {
|
||||||
ty::TyAdt(def, ..) if def.is_box() => Unique,
|
ty::TyAdt(def, ..) if def.is_box() => Unique,
|
||||||
ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl),
|
ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl),
|
||||||
|
@ -967,7 +970,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
let bk = ty::BorrowKind::from_mutbl(mt.mutbl);
|
let bk = ty::BorrowKind::from_mutbl(mt.mutbl);
|
||||||
if implicit { Implicit(bk, r) } else { BorrowedPtr(bk, r) }
|
if implicit { Implicit(bk, r) } else { BorrowedPtr(bk, r) }
|
||||||
}
|
}
|
||||||
ref ty => bug!("unexpected type in cat_deref_common: {:?}", ty)
|
ref ty => bug!("unexpected type in cat_deref: {:?}", ty)
|
||||||
};
|
};
|
||||||
let ret = Rc::new(cmt_ {
|
let ret = Rc::new(cmt_ {
|
||||||
id: node.id(),
|
id: node.id(),
|
||||||
|
@ -978,15 +981,16 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
ty: deref_ty,
|
ty: deref_ty,
|
||||||
note: NoteNone
|
note: NoteNone
|
||||||
});
|
});
|
||||||
debug!("cat_deref_common ret {:?}", ret);
|
debug!("cat_deref ret {:?}", ret);
|
||||||
ret
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cat_index<N:ast_node>(&self,
|
fn cat_index<N:ast_node>(&self,
|
||||||
elt: &N,
|
elt: &N,
|
||||||
mut base_cmt: cmt<'tcx>,
|
base_cmt: cmt<'tcx>,
|
||||||
context: InteriorOffsetKind)
|
element_ty: Ty<'tcx>,
|
||||||
-> McResult<cmt<'tcx>> {
|
context: InteriorOffsetKind)
|
||||||
|
-> McResult<cmt<'tcx>> {
|
||||||
//! Creates a cmt for an indexing operation (`[]`).
|
//! Creates a cmt for an indexing operation (`[]`).
|
||||||
//!
|
//!
|
||||||
//! One subtle aspect of indexing that may not be
|
//! One subtle aspect of indexing that may not be
|
||||||
|
@ -1004,29 +1008,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
//! - `elt`: the AST node being indexed
|
//! - `elt`: the AST node being indexed
|
||||||
//! - `base_cmt`: the cmt of `elt`
|
//! - `base_cmt`: the cmt of `elt`
|
||||||
|
|
||||||
let method = self.infcx.tables.borrow().method_map.get(&elt.id()).cloned();
|
let interior_elem = InteriorElement(context);
|
||||||
let (element_ty, element_kind) = match method {
|
|
||||||
Some(method) => {
|
|
||||||
let ref_ty = self.overloaded_method_return_ty(method);
|
|
||||||
base_cmt = self.cat_rvalue_node(elt.id(), elt.span(), ref_ty);
|
|
||||||
|
|
||||||
(ref_ty.builtin_deref(false, ty::NoPreference).unwrap().ty,
|
|
||||||
ElementKind::OtherElement)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
match base_cmt.ty.builtin_index() {
|
|
||||||
Some(ty) => (ty, ElementKind::VecElement),
|
|
||||||
None => {
|
|
||||||
debug!("Explicit index of non-indexable type {:?}", base_cmt);
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let interior_elem = InteriorElement(context, element_kind);
|
|
||||||
let ret =
|
let ret =
|
||||||
self.cat_imm_interior(elt, base_cmt.clone(), element_ty, interior_elem);
|
self.cat_imm_interior(elt, base_cmt, element_ty, interior_elem);
|
||||||
debug!("cat_index ret {:?}", ret);
|
debug!("cat_index ret {:?}", ret);
|
||||||
return Ok(ret);
|
return Ok(ret);
|
||||||
}
|
}
|
||||||
|
@ -1216,15 +1200,20 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
// box p1, &p1, &mut p1. we can ignore the mutability of
|
// box p1, &p1, &mut p1. we can ignore the mutability of
|
||||||
// PatKind::Ref since that information is already contained
|
// PatKind::Ref since that information is already contained
|
||||||
// in the type.
|
// in the type.
|
||||||
let method = self.infcx.tables.borrow().method_map
|
let subcmt = self.cat_deref(pat, cmt, false)?;
|
||||||
.get(&pat.id).cloned();
|
|
||||||
let subcmt = self.cat_deref(pat, cmt, method)?;
|
|
||||||
self.cat_pattern_(subcmt, &subpat, op)?;
|
self.cat_pattern_(subcmt, &subpat, op)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
PatKind::Slice(ref before, ref slice, ref after) => {
|
PatKind::Slice(ref before, ref slice, ref after) => {
|
||||||
|
let element_ty = match cmt.ty.builtin_index() {
|
||||||
|
Some(ty) => ty,
|
||||||
|
None => {
|
||||||
|
debug!("Explicit index of non-indexable type {:?}", cmt);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
};
|
||||||
let context = InteriorOffsetKind::Pattern;
|
let context = InteriorOffsetKind::Pattern;
|
||||||
let elt_cmt = self.cat_index(pat, cmt, context)?;
|
let elt_cmt = self.cat_index(pat, cmt, element_ty, context)?;
|
||||||
for before_pat in before {
|
for before_pat in before {
|
||||||
self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
|
self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
|
||||||
}
|
}
|
||||||
|
@ -1244,16 +1233,6 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn overloaded_method_return_ty(&self,
|
|
||||||
method: ty::MethodCallee<'tcx>)
|
|
||||||
-> Ty<'tcx>
|
|
||||||
{
|
|
||||||
// When we process an overloaded `*` or `[]` etc, we often
|
|
||||||
// need to extract the return type of the method.
|
|
||||||
let ret_ty = method.sig.output();
|
|
||||||
self.infcx.resolve_type_vars_if_possible(&ret_ty)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -1401,16 +1380,10 @@ impl<'tcx> cmt_<'tcx> {
|
||||||
Categorization::Interior(_, InteriorField(PositionalField(_))) => {
|
Categorization::Interior(_, InteriorField(PositionalField(_))) => {
|
||||||
"anonymous field".to_string()
|
"anonymous field".to_string()
|
||||||
}
|
}
|
||||||
Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Index,
|
Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Index)) => {
|
||||||
VecElement)) |
|
|
||||||
Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Index,
|
|
||||||
OtherElement)) => {
|
|
||||||
"indexed content".to_string()
|
"indexed content".to_string()
|
||||||
}
|
}
|
||||||
Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Pattern,
|
Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Pattern)) => {
|
||||||
VecElement)) |
|
|
||||||
Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Pattern,
|
|
||||||
OtherElement)) => {
|
|
||||||
"pattern-bound indexed content".to_string()
|
"pattern-bound indexed content".to_string()
|
||||||
}
|
}
|
||||||
Categorization::Upvar(ref var) => {
|
Categorization::Upvar(ref var) => {
|
||||||
|
|
|
@ -805,7 +805,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||||
self.check_if_assigned_path_is_moved(id, span,
|
self.check_if_assigned_path_is_moved(id, span,
|
||||||
use_kind, lp_base);
|
use_kind, lp_base);
|
||||||
}
|
}
|
||||||
LpExtend(ref lp_base, _, LpInterior(_, InteriorElement(..))) |
|
LpExtend(ref lp_base, _, LpInterior(_, InteriorElement)) |
|
||||||
LpExtend(ref lp_base, _, LpDeref(_)) => {
|
LpExtend(ref lp_base, _, LpDeref(_)) => {
|
||||||
// assigning to `P[i]` requires `P` is initialized
|
// assigning to `P[i]` requires `P` is initialized
|
||||||
// assigning to `(*P)` requires `P` is initialized
|
// assigning to `(*P)` requires `P` is initialized
|
||||||
|
|
|
@ -237,7 +237,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
|
|
||||||
Categorization::Downcast(ref b, _) |
|
Categorization::Downcast(ref b, _) |
|
||||||
Categorization::Interior(ref b, mc::InteriorField(_)) |
|
Categorization::Interior(ref b, mc::InteriorField(_)) |
|
||||||
Categorization::Interior(ref b, mc::InteriorElement(Kind::Pattern, _)) => {
|
Categorization::Interior(ref b, mc::InteriorElement(Kind::Pattern)) => {
|
||||||
match b.ty.sty {
|
match b.ty.sty {
|
||||||
ty::TyAdt(def, _) => {
|
ty::TyAdt(def, _) => {
|
||||||
if def.has_dtor(bccx.tcx) {
|
if def.has_dtor(bccx.tcx) {
|
||||||
|
@ -253,7 +253,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Categorization::Interior(_, mc::InteriorElement(Kind::Index, _)) => {
|
Categorization::Interior(_, mc::InteriorElement(Kind::Index)) => {
|
||||||
// Forbid move of arr[i] for arr: [T; 3]; see RFC 533.
|
// Forbid move of arr[i] for arr: [T; 3]; see RFC 533.
|
||||||
Some(cmt.clone())
|
Some(cmt.clone())
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,7 +152,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
|
|
||||||
Categorization::Interior(ref b, mc::InteriorElement(ik, _)) => {
|
Categorization::Interior(ref b, mc::InteriorElement(ik)) => {
|
||||||
match (&b.ty.sty, ik) {
|
match (&b.ty.sty, ik) {
|
||||||
(&ty::TySlice(..), _) |
|
(&ty::TySlice(..), _) |
|
||||||
(_, Kind::Index) => {
|
(_, Kind::Index) => {
|
||||||
|
|
|
@ -284,7 +284,7 @@ const DOWNCAST_PRINTED_OPERATOR: &'static str = " as ";
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum InteriorKind {
|
pub enum InteriorKind {
|
||||||
InteriorField(mc::FieldName),
|
InteriorField(mc::FieldName),
|
||||||
InteriorElement(mc::ElementKind),
|
InteriorElement,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ToInteriorKind { fn cleaned(self) -> InteriorKind; }
|
trait ToInteriorKind { fn cleaned(self) -> InteriorKind; }
|
||||||
|
@ -292,7 +292,7 @@ impl ToInteriorKind for mc::InteriorKind {
|
||||||
fn cleaned(self) -> InteriorKind {
|
fn cleaned(self) -> InteriorKind {
|
||||||
match self {
|
match self {
|
||||||
mc::InteriorField(name) => InteriorField(name),
|
mc::InteriorField(name) => InteriorField(name),
|
||||||
mc::InteriorElement(_, elem_kind) => InteriorElement(elem_kind),
|
mc::InteriorElement(_) => InteriorElement,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1232,7 +1232,7 @@ before rustc 1.16, this temporary lived longer - see issue #39283 \
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LpExtend(ref lp_base, _, LpInterior(_, InteriorElement(..))) => {
|
LpExtend(ref lp_base, _, LpInterior(_, InteriorElement)) => {
|
||||||
self.append_autoderefd_loan_path_to_string(&lp_base, out);
|
self.append_autoderefd_loan_path_to_string(&lp_base, out);
|
||||||
out.push_str("[..]");
|
out.push_str("[..]");
|
||||||
}
|
}
|
||||||
|
@ -1318,7 +1318,7 @@ impl<'tcx> fmt::Debug for InteriorKind {
|
||||||
match *self {
|
match *self {
|
||||||
InteriorField(mc::NamedField(fld)) => write!(f, "{}", fld),
|
InteriorField(mc::NamedField(fld)) => write!(f, "{}", fld),
|
||||||
InteriorField(mc::PositionalField(i)) => write!(f, "#{}", i),
|
InteriorField(mc::PositionalField(i)) => write!(f, "#{}", i),
|
||||||
InteriorElement(..) => write!(f, "[]"),
|
InteriorElement => write!(f, "[]"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,7 +191,7 @@ fn loan_path_is_precise(loan_path: &LoanPath) -> bool {
|
||||||
LpVar(_) | LpUpvar(_) => {
|
LpVar(_) | LpUpvar(_) => {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
LpExtend(.., LpInterior(_, InteriorKind::InteriorElement(..))) => {
|
LpExtend(.., LpInterior(_, InteriorKind::InteriorElement)) => {
|
||||||
// Paths involving element accesses a[i] do not refer to a unique
|
// Paths involving element accesses a[i] do not refer to a unique
|
||||||
// location, as there is no accurate tracking of the indices.
|
// location, as there is no accurate tracking of the indices.
|
||||||
//
|
//
|
||||||
|
|
|
@ -94,8 +94,8 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||||
debug!("make_mirror: overloaded autoderef (method={:?})", method);
|
debug!("make_mirror: overloaded autoderef (method={:?})", method);
|
||||||
|
|
||||||
ref_ty = method.sig.output();
|
ref_ty = method.sig.output();
|
||||||
let (region, mutbl) = match ref_ty.sty {
|
let (region, mt) = match ref_ty.sty {
|
||||||
ty::TyRef(region, mt) => (region, mt.mutbl),
|
ty::TyRef(region, mt) => (region, mt),
|
||||||
_ => span_bug!(expr.span, "autoderef returned bad type"),
|
_ => span_bug!(expr.span, "autoderef returned bad type"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,18 +105,19 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||||
ty: cx.tcx.mk_ref(region,
|
ty: cx.tcx.mk_ref(region,
|
||||||
ty::TypeAndMut {
|
ty::TypeAndMut {
|
||||||
ty: expr.ty,
|
ty: expr.ty,
|
||||||
mutbl: mutbl,
|
mutbl: mt.mutbl,
|
||||||
}),
|
}),
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
kind: ExprKind::Borrow {
|
kind: ExprKind::Borrow {
|
||||||
region: region,
|
region: region,
|
||||||
borrow_kind: to_borrow_kind(mutbl),
|
borrow_kind: to_borrow_kind(mt.mutbl),
|
||||||
arg: expr.to_ref(),
|
arg: expr.to_ref(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
overloaded_lvalue(cx,
|
overloaded_lvalue(cx,
|
||||||
self,
|
self,
|
||||||
|
mt.ty,
|
||||||
method,
|
method,
|
||||||
PassArgs::ByRef,
|
PassArgs::ByRef,
|
||||||
expr.to_ref(),
|
expr.to_ref(),
|
||||||
|
@ -264,13 +265,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
|
|
||||||
// rewrite f(u, v) into FnOnce::call_once(f, (u, v))
|
// rewrite f(u, v) into FnOnce::call_once(f, (u, v))
|
||||||
|
|
||||||
let sig = method.sig;
|
|
||||||
let method = method_callee(cx, expr, method);
|
let method = method_callee(cx, expr, method);
|
||||||
|
|
||||||
assert_eq!(sig.inputs().len(), 2);
|
let arg_tys = args.iter().map(|e| cx.tables().expr_ty_adjusted(e));
|
||||||
|
|
||||||
let tupled_args = Expr {
|
let tupled_args = Expr {
|
||||||
ty: sig.inputs()[1],
|
ty: cx.tcx.mk_tup(arg_tys, false),
|
||||||
temp_lifetime: temp_lifetime,
|
temp_lifetime: temp_lifetime,
|
||||||
temp_lifetime_was_shrunk: was_shrunk,
|
temp_lifetime_was_shrunk: was_shrunk,
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
|
@ -435,6 +434,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
if let Some(&method) = cx.tables().method_map.get(&expr.id) {
|
if let Some(&method) = cx.tables().method_map.get(&expr.id) {
|
||||||
overloaded_lvalue(cx,
|
overloaded_lvalue(cx,
|
||||||
expr,
|
expr,
|
||||||
|
expr_ty,
|
||||||
method,
|
method,
|
||||||
PassArgs::ByValue,
|
PassArgs::ByValue,
|
||||||
lhs.to_ref(),
|
lhs.to_ref(),
|
||||||
|
@ -451,6 +451,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
if let Some(&method) = cx.tables().method_map.get(&expr.id) {
|
if let Some(&method) = cx.tables().method_map.get(&expr.id) {
|
||||||
overloaded_lvalue(cx,
|
overloaded_lvalue(cx,
|
||||||
expr,
|
expr,
|
||||||
|
expr_ty,
|
||||||
method,
|
method,
|
||||||
PassArgs::ByValue,
|
PassArgs::ByValue,
|
||||||
arg.to_ref(),
|
arg.to_ref(),
|
||||||
|
@ -996,6 +997,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
|
|
||||||
fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
expr: &'tcx hir::Expr,
|
expr: &'tcx hir::Expr,
|
||||||
|
lvalue_ty: Ty<'tcx>,
|
||||||
method: ty::MethodCallee<'tcx>,
|
method: ty::MethodCallee<'tcx>,
|
||||||
pass_args: PassArgs,
|
pass_args: PassArgs,
|
||||||
receiver: ExprRef<'tcx>,
|
receiver: ExprRef<'tcx>,
|
||||||
|
@ -1005,8 +1007,22 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
// call returns an &T and we must add the deref so that the types
|
// call returns an &T and we must add the deref so that the types
|
||||||
// line up (this is because `*x` and `x[y]` represent lvalues):
|
// line up (this is because `*x` and `x[y]` represent lvalues):
|
||||||
|
|
||||||
// to find the type &T of the content returned by the method;
|
let recv_ty = match receiver {
|
||||||
let ref_ty = method.sig.output();
|
ExprRef::Hair(e) => cx.tables().expr_ty_adjusted(e),
|
||||||
|
ExprRef::Mirror(ref e) => e.ty
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reconstruct the output assuming it's a reference with the
|
||||||
|
// same region and mutability as the receiver. This holds for
|
||||||
|
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
|
||||||
|
let (region, mutbl) = match recv_ty.sty {
|
||||||
|
ty::TyRef(region, mt) => (region, mt.mutbl),
|
||||||
|
_ => span_bug!(expr.span, "overloaded_lvalue: receiver is not a reference"),
|
||||||
|
};
|
||||||
|
let ref_ty = cx.tcx.mk_ref(region, ty::TypeAndMut {
|
||||||
|
ty: lvalue_ty,
|
||||||
|
mutbl,
|
||||||
|
});
|
||||||
|
|
||||||
// construct the complete expression `foo()` for the overloaded call,
|
// construct the complete expression `foo()` for the overloaded call,
|
||||||
// which will yield the &T type
|
// which will yield the &T type
|
||||||
|
|
|
@ -538,10 +538,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.substs_wf_in_scope(origin, &callee.substs, expr.span, expr_region);
|
self.substs_wf_in_scope(origin, &callee.substs, expr.span, expr_region);
|
||||||
for &ty in callee.sig.inputs() {
|
// Arguments (sub-expressions) are checked via `constrain_call`, below.
|
||||||
self.type_must_outlive(infer::ExprTypeIsNotInScope(ty, expr.span),
|
|
||||||
ty, expr_region);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check any autoderefs or autorefs that appear.
|
// Check any autoderefs or autorefs that appear.
|
||||||
|
@ -690,14 +687,13 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
hir::ExprUnary(hir::UnDeref, ref base) => {
|
hir::ExprUnary(hir::UnDeref, ref base) => {
|
||||||
// For *a, the lifetime of a must enclose the deref
|
// For *a, the lifetime of a must enclose the deref
|
||||||
let base_ty = match self.tables.borrow().method_map.get(&expr.id) {
|
if self.tables.borrow().is_method_call(expr.id) {
|
||||||
Some(method) => {
|
self.constrain_call(expr, Some(base),
|
||||||
self.constrain_call(expr, Some(&base),
|
None::<hir::Expr>.iter(), true);
|
||||||
None::<hir::Expr>.iter(), true);
|
}
|
||||||
method.sig.output()
|
// For overloaded derefs, base_ty is the input to `Deref::deref`,
|
||||||
}
|
// but it's a reference type uing the same region as the output.
|
||||||
None => self.resolve_node_type(base.id)
|
let base_ty = self.resolve_expr_type_adjusted(base);
|
||||||
};
|
|
||||||
if let ty::TyRef(r_ptr, _) = base_ty.sty {
|
if let ty::TyRef(r_ptr, _) = base_ty.sty {
|
||||||
self.mk_subregion_due_to_dereference(expr.span, expr_region, r_ptr);
|
self.mk_subregion_due_to_dereference(expr.span, expr_region, r_ptr);
|
||||||
}
|
}
|
||||||
|
@ -960,7 +956,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
{
|
{
|
||||||
let mc = mc::MemCategorizationContext::new(self, &self.region_maps);
|
let mc = mc::MemCategorizationContext::new(self, &self.region_maps);
|
||||||
cmt = mc.cat_deref(deref_expr, cmt, overloaded)?;
|
if let Some(method) = overloaded {
|
||||||
|
cmt = mc.cat_overloaded_autoderef(deref_expr, method)?;
|
||||||
|
} else {
|
||||||
|
cmt = mc.cat_deref(deref_expr, cmt, false)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Categorization::Deref(_, mc::BorrowedPtr(_, r_ptr)) = cmt.cat {
|
if let Categorization::Deref(_, mc::BorrowedPtr(_, r_ptr)) = cmt.cat {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue