Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
eddyb's refactoring of coercions/adjustments
  • Loading branch information
eddyb authored and nrc committed Apr 14, 2015
1 parent a4eb5a6 commit 4e8e641
Show file tree
Hide file tree
Showing 25 changed files with 815 additions and 1,490 deletions.
274 changes: 59 additions & 215 deletions src/librustc/middle/astencode.rs

Large diffs are not rendered by default.

88 changes: 29 additions & 59 deletions src/librustc/middle/expr_use_visitor.rs
Expand Up @@ -787,23 +787,30 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
// process.
fn walk_adjustment(&mut self, expr: &ast::Expr) {
let typer = self.typer;
match typer.adjustments().borrow().get(&expr.id) {
None => { }
Some(adjustment) => {
match *adjustment {
ty::AdjustReifyFnPointer(..) |
ty::AdjustUnsafeFnPointer(..) => {
// Creating a closure/fn-pointer consumes the
// input and stores it into the resulting
// rvalue.
debug!("walk_adjustment(AutoAddEnv|AdjustReifyFnPointer)");
if let Some(adjustment) = typer.adjustments().borrow().get(&expr.id) {
match *adjustment {
ty::AdjustReifyFnPointer |
ty::AdjustUnsafeFnPointer => {
// Creating a closure/fn-pointer or unsizing consumes
// the input and stores it into the resulting rvalue.
debug!("walk_adjustment(AdjustReifyFnPointer|AdjustUnsafeFnPointer)");
let cmt_unadjusted =
return_if_err!(self.mc.cat_expr_unadjusted(expr));
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
}
ty::AdjustDerefRef(ref adj) => {
self.walk_autoderefs(expr, adj.autoderefs);
if let Some(ref r) = adj.autoref {
self.walk_autoref(expr, r, adj.autoderefs);
} else if adj.unsize.is_some() {
assert!(adj.autoderefs == 0,
format!("Expected no derefs with \
unsize AutoRefs, found: {}",
adj.repr(self.tcx())));
let cmt_unadjusted =
return_if_err!(self.mc.cat_expr_unadjusted(expr));
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
}
ty::AdjustDerefRef(ref adj) => {
self.walk_autoderefref(expr, adj);
}
}
}
}
Expand All @@ -818,7 +825,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
debug!("walk_autoderefs expr={} autoderefs={}", expr.repr(self.tcx()), autoderefs);

for i in 0..autoderefs {
let deref_id = ty::MethodCall::autoderef(expr.id, i);
let deref_id = ty::MethodCall::autoderef(expr.id, i as u32);
match self.typer.node_method_ty(deref_id) {
None => {}
Some(method_ty) => {
Expand Down Expand Up @@ -903,59 +910,22 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
}
};

match *autoref {
ty::AutoPtr(r, m, ref baseref) => {
let cmt_base = self.walk_autoref_recursively(expr, cmt_derefd, baseref);
let cmt_base = self.walk_autoref_recursively(expr, cmt_derefd, baseref);

debug!("walk_autoref: expr.id={} cmt_base={}",
expr.id,
cmt_base.repr(self.tcx()));
debug!("walk_autoref: expr.id={} cmt_base={}",
expr.id,
cmt_base.repr(self.tcx()));

match *autoref {
ty::AutoPtr(r, m) => {
self.delegate.borrow(expr.id,
expr.span,
cmt_base,
r,
cmt_derefd,
*r,
ty::BorrowKind::from_mutbl(m),
AutoRef);
}

ty::AutoUnsize(_) => {
// Converting a `[T; N]` to `[T]` or `T` to `Trait`
// isn't really a borrow, move, etc, in and of itself.
// Also, no recursive step here, this is a base case.

// It may seem a bit odd to return the cmt_derefd
// unmodified here, but in fact I think it's the right
// thing to do. Essentially the unsize transformation
// isn't really relevant to the borrowing rules --
// it's best thought of as a kind of side-modifier to
// the autoref, adding additional data that is
// attached to the pointer that is produced, but not
// affecting the data being borrowed in any other
// way. To see what I mean, consider this example:
//
// fn foo<'a>(&'a self) -> &'a Trait { self }
//
// This is valid because the underlying `self` value
// lives for the lifetime 'a. If we were to treat the
// "unsizing" as e.g. producing an rvalue, that would
// only be valid for the temporary scope, which isn't
// enough to justify the return value, which have the
// lifetime 'a.
//
// Another option would be to add a variant for
// categorization (like downcast) that wraps
// cmt_derefd and represents the unsizing operation.
// But I don't think there is any particular use for
// this (yet). -nmatsakis
return cmt_derefd.clone();
}

ty::AutoUnsizeUniq(_) => {
// these are handled via special case above
self.tcx().sess.span_bug(expr.span, "nexpected AutoUnsizeUniq");
}

ty::AutoUnsafe(m, ref baseref) => {
let cmt_base = self.walk_autoref_recursively(expr, cmt_derefd, baseref);

Expand Down
38 changes: 11 additions & 27 deletions src/librustc/middle/mem_categorization.rs
Expand Up @@ -451,33 +451,23 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {

Some(adjustment) => {
match *adjustment {
ty::AdjustReifyFnPointer(..) |
ty::AdjustUnsafeFnPointer(..) => {
debug!("cat_expr(AdjustReifyFnPointer): {}",
expr.repr(self.tcx()));
// Convert a bare fn to a closure by adding NULL env.
// Result is an rvalue.
let expr_ty = try!(self.expr_ty_adjusted(expr));
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
}

ty::AdjustDerefRef(
ty::AutoDerefRef {
autoref: Some(_), ..}) => {
debug!("cat_expr(AdjustDerefRef): {}",
autoref: None, unsize: None, autoderefs, ..}) => {
// Equivalent to *expr or something similar.
self.cat_expr_autoderefd(expr, autoderefs)
}

ty::AdjustReifyFnPointer |
ty::AdjustUnsafeFnPointer |
ty::AdjustDerefRef(_) => {
debug!("cat_expr({}): {}",
adjustment.repr(self.tcx()),
expr.repr(self.tcx()));
// Equivalent to &*expr or something similar.
// Result is an rvalue.
let expr_ty = try!(self.expr_ty_adjusted(expr));
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
}

ty::AdjustDerefRef(
ty::AutoDerefRef {
autoref: None, autoderefs}) => {
// Equivalent to *expr or something similar.
self.cat_expr_autoderefd(expr, autoderefs)
}
}
}
}
Expand Down Expand Up @@ -928,15 +918,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
deref_cnt: usize,
deref_context: DerefKindContext)
-> McResult<cmt<'tcx>> {
let adjustment = match self.typer.adjustments().borrow().get(&node.id()) {
Some(adj) if ty::adjust_is_object(adj) => ty::AutoObject,
_ if deref_cnt != 0 => ty::AutoDeref(deref_cnt),
_ => ty::NoAdjustment
};

let method_call = ty::MethodCall {
expr_id: node.id(),
adjustment: adjustment
autoderef: deref_cnt as u32
};
let method_ty = self.typer.node_method_ty(method_call);

Expand Down

0 comments on commit 4e8e641

Please sign in to comment.