Add comments to autoderef() helper and refactor it to take
an `Option<&Expr>` like everything else.
This commit is contained in:
parent
5364c4853f
commit
0a32010e43
@ -143,7 +143,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
// time writing the results into the various tables.
|
||||
let (autoderefd_ty, n, result) =
|
||||
check::autoderef(
|
||||
self.fcx, self.span, unadjusted_self_ty, Some(self.self_expr.id), NoPreference,
|
||||
self.fcx, self.span, unadjusted_self_ty, Some(self.self_expr), NoPreference,
|
||||
|_, n| if n == auto_deref_ref.autoderefs { Some(()) } else { None });
|
||||
assert_eq!(n, auto_deref_ref.autoderefs);
|
||||
assert_eq!(result, Some(()));
|
||||
@ -492,7 +492,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
exprs.repr(self.tcx()));
|
||||
|
||||
// Fix up autoderefs and derefs.
|
||||
for (i, expr) in exprs.iter().rev().enumerate() {
|
||||
for (i, &expr) in exprs.iter().rev().enumerate() {
|
||||
// Count autoderefs.
|
||||
let autoderef_count = match self.fcx
|
||||
.inh
|
||||
@ -512,8 +512,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
if autoderef_count > 0 {
|
||||
check::autoderef(self.fcx,
|
||||
expr.span,
|
||||
self.fcx.expr_ty(*expr),
|
||||
Some(expr.id),
|
||||
self.fcx.expr_ty(expr),
|
||||
Some(expr),
|
||||
PreferMutLvalue,
|
||||
|_, autoderefs| {
|
||||
if autoderefs == autoderef_count + 1 {
|
||||
@ -567,7 +567,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
let result = check::try_index_step(
|
||||
self.fcx,
|
||||
MethodCall::expr(expr.id),
|
||||
*expr,
|
||||
expr,
|
||||
&**base_expr,
|
||||
adjusted_base_ty,
|
||||
base_adjustment,
|
||||
@ -577,7 +577,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
||||
if let Some((input_ty, return_ty)) = result {
|
||||
demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty);
|
||||
|
||||
let expr_ty = self.fcx.expr_ty(&**expr);
|
||||
let expr_ty = self.fcx.expr_ty(&*expr);
|
||||
demand::suptype(self.fcx, expr.span, expr_ty, return_ty);
|
||||
}
|
||||
}
|
||||
|
@ -102,9 +102,9 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types))
|
||||
}
|
||||
|
||||
pub fn lookup_in_trait<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
span: Span,
|
||||
self_expr: Option<&'a ast::Expr>,
|
||||
self_expr: Option<&ast::Expr>,
|
||||
m_name: ast::Name,
|
||||
trait_def_id: DefId,
|
||||
self_ty: Ty<'tcx>,
|
||||
@ -125,9 +125,9 @@ pub fn lookup_in_trait<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
/// method-lookup code. In particular, autoderef on index is basically identical to autoderef with
|
||||
/// normal probes, except that the test also looks for built-in indexing. Also, the second half of
|
||||
/// this method is basically the same as confirmation.
|
||||
pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
span: Span,
|
||||
self_expr: Option<&'a ast::Expr>,
|
||||
self_expr: Option<&ast::Expr>,
|
||||
m_name: ast::Name,
|
||||
trait_def_id: DefId,
|
||||
autoderefref: ty::AutoDerefRef<'tcx>,
|
||||
|
@ -2263,17 +2263,36 @@ pub enum LvaluePreference {
|
||||
/// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
|
||||
/// whether to terminate the loop. Returns the final type and number of derefs that it performed.
|
||||
///
|
||||
<<<<<<< HEAD
|
||||
/// Note: this method does not modify the adjustments table. The caller is responsible for
|
||||
/// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
|
||||
pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
sp: Span,
|
||||
||||||| merged common ancestors
|
||||
/// Note: this method does not modify the adjustments table. The caller is responsible for
|
||||
/// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
|
||||
pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
|
||||
=======
|
||||
/// Note: this method does not modify the adjustments table. The
|
||||
/// caller is responsible for inserting an AutoAdjustment record into
|
||||
/// the `fcx` using one of the suitable methods. However, if
|
||||
/// `opt_expr` is not `None`, it *will* insert the appropriate method
|
||||
/// entries for the overloaded deref call.
|
||||
pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
sp: Span,
|
||||
>>>>>>> Add comments to autoderef() helper and refactor it to take
|
||||
base_ty: Ty<'tcx>,
|
||||
expr_id: Option<ast::NodeId>,
|
||||
opt_expr: Option<&ast::Expr>,
|
||||
mut lvalue_pref: LvaluePreference,
|
||||
mut should_stop: F)
|
||||
-> (Ty<'tcx>, uint, Option<T>) where
|
||||
F: FnMut(Ty<'tcx>, uint) -> Option<T>,
|
||||
-> (Ty<'tcx>, uint, Option<T>)
|
||||
where F: FnMut(Ty<'tcx>, uint) -> Option<T>,
|
||||
{
|
||||
debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={})",
|
||||
base_ty.repr(fcx.tcx()),
|
||||
opt_expr,
|
||||
lvalue_pref);
|
||||
|
||||
let mut t = base_ty;
|
||||
for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
|
||||
let resolved_t = structurally_resolved_type(fcx, sp, t);
|
||||
@ -2291,7 +2310,19 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
let mt = match ty::deref(resolved_t, false) {
|
||||
Some(mt) => Some(mt),
|
||||
None => {
|
||||
let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
|
||||
let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
|
||||
|
||||
// Super subtle: it might seem as though we should
|
||||
// pass `opt_expr` to `try_overloaded_deref`, so that
|
||||
// the (implicit) autoref of using an overloaded deref
|
||||
// would get added to the adjustment table. However we
|
||||
// do not do that, because it's kind of a
|
||||
// "meta-adjustment" -- instead, we just leave it
|
||||
// unrecorded and know that there "will be" an
|
||||
// autoref. regionck and other bits of the code base,
|
||||
// when they encounter an overloaded autoderef, have
|
||||
// to do some reconstructive surgery. This is a pretty
|
||||
// complex mess that is begging for a proper MIR.
|
||||
try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
|
||||
}
|
||||
};
|
||||
@ -2324,7 +2355,7 @@ fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
// Try DerefMut first, if preferred.
|
||||
let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
|
||||
(PreferMutLvalue, Some(trait_did)) => {
|
||||
method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
|
||||
method::lookup_in_trait(fcx, span, base_expr,
|
||||
token::intern("deref_mut"), trait_did,
|
||||
base_ty, None)
|
||||
}
|
||||
@ -2334,7 +2365,7 @@ fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
// Otherwise, fall back to Deref.
|
||||
let method = match (method, fcx.tcx().lang_items.deref_trait()) {
|
||||
(None, Some(trait_did)) => {
|
||||
method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
|
||||
method::lookup_in_trait(fcx, span, base_expr,
|
||||
token::intern("deref"), trait_did,
|
||||
base_ty, None)
|
||||
}
|
||||
@ -2390,7 +2421,7 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
// consolidated.
|
||||
|
||||
let (ty, autoderefs, final_mt) =
|
||||
autoderef(fcx, base_expr.span, base_ty, Some(base_expr.id), lvalue_pref, |adj_ty, idx| {
|
||||
autoderef(fcx, base_expr.span, base_ty, Some(base_expr), lvalue_pref, |adj_ty, idx| {
|
||||
let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
|
||||
step(adj_ty, autoderefref)
|
||||
});
|
||||
@ -3360,7 +3391,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
fcx.expr_ty(base));
|
||||
// FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
|
||||
let (_, autoderefs, field_ty) =
|
||||
autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
|
||||
autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
|
||||
match base_t.sty {
|
||||
ty::ty_struct(base_id, substs) => {
|
||||
debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
|
||||
@ -3421,7 +3452,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
let mut tuple_like = false;
|
||||
// FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
|
||||
let (_, autoderefs, field_ty) =
|
||||
autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
|
||||
autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
|
||||
match base_t.sty {
|
||||
ty::ty_struct(base_id, substs) => {
|
||||
tuple_like = ty::is_tuple_struct(tcx, base_id);
|
||||
|
@ -1049,13 +1049,16 @@ fn type_of_node_must_outlive<'a, 'tcx>(
|
||||
/// Computes the guarantor for an expression `&base` and then ensures that the lifetime of the
|
||||
/// resulting pointer is linked to the lifetime of its guarantor (if any).
|
||||
fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
|
||||
mutability: ast::Mutability, base: &ast::Expr) {
|
||||
debug!("link_addr_of(base=?)");
|
||||
mutability: ast::Mutability, base: &ast::Expr) {
|
||||
debug!("link_addr_of(expr={}, base={})", expr.repr(rcx.tcx()), base.repr(rcx.tcx()));
|
||||
|
||||
let cmt = {
|
||||
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
||||
ignore_err!(mc.cat_expr(base))
|
||||
};
|
||||
|
||||
debug!("link_addr_of: cmt={}", cmt.repr(rcx.tcx()));
|
||||
|
||||
link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
|
||||
}
|
||||
|
||||
@ -1182,6 +1185,9 @@ fn link_region_from_node_type<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
|
||||
id: ast::NodeId,
|
||||
mutbl: ast::Mutability,
|
||||
cmt_borrowed: mc::cmt<'tcx>) {
|
||||
debug!("link_region_from_node_type(id={}, mutbl={}, cmt_borrowed={})",
|
||||
id, mutbl, cmt_borrowed.repr(rcx.tcx()));
|
||||
|
||||
let rptr_ty = rcx.resolve_node_type(id);
|
||||
if !ty::type_is_error(rptr_ty) {
|
||||
let tcx = rcx.fcx.ccx.tcx;
|
||||
|
Loading…
x
Reference in New Issue
Block a user