Skip to content

Refactor coercions/adjustments #24261

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 14, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libcore/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ use option::Option::{self, Some, None};
use marker::Sized;
use usize;

fn _assert_is_object_safe(_: &Iterator) {}
fn _assert_is_object_safe(_: &Iterator<Item=()>) {}

/// An interface for dealing with "external iterators". These types of iterators
/// can be resumed at any time as all state is stored internally as opposed to
Expand Down
274 changes: 59 additions & 215 deletions src/librustc/middle/astencode.rs

Large diffs are not rendered by default.

146 changes: 40 additions & 106 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -787,23 +787,19 @@ 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)");
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);
}
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_autoderefref(expr, adj);
}
}
}
Expand All @@ -818,7 +814,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 @@ -852,30 +848,19 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {

self.walk_autoderefs(expr, adj.autoderefs);

// Weird hacky special case: AutoUnsizeUniq, which converts
// from a ~T to a ~Trait etc, always comes in a stylized
// fashion. In particular, we want to consume the ~ pointer
// being dereferenced, not the dereferenced content (as the
// content is, at least for upcasts, unsized).
match adj.autoref {
Some(ty::AutoUnsizeUniq(_)) => {
assert!(adj.autoderefs == 1,
format!("Expected exactly 1 deref with Uniq AutoRefs, found: {}",
adj.autoderefs));
let cmt_unadjusted =
return_if_err!(self.mc.cat_expr_unadjusted(expr));
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
return;
}
_ => { }
}
let cmt_derefd =
return_if_err!(self.mc.cat_expr_autoderefd(expr, adj.autoderefs));

let cmt_refd =
self.walk_autoref(expr, cmt_derefd, adj.autoref);

let autoref = adj.autoref.as_ref();
let cmt_derefd = return_if_err!(
self.mc.cat_expr_autoderefd(expr, adj.autoderefs));
self.walk_autoref(expr, &cmt_derefd, autoref);
if adj.unsize.is_some() {
// Unsizing consumes the thin pointer and produces a fat one.
self.delegate_consume(expr.id, expr.span, cmt_refd);
}
}


/// Walks the autoref `opt_autoref` applied to the autoderef'd
/// `expr`. `cmt_derefd` is the mem-categorized form of `expr`
/// after all relevant autoderefs have occurred. Because AutoRefs
Expand All @@ -886,79 +871,40 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
/// autoref.
fn walk_autoref(&mut self,
expr: &ast::Expr,
cmt_derefd: &mc::cmt<'tcx>,
opt_autoref: Option<&ty::AutoRef<'tcx>>)
cmt_base: mc::cmt<'tcx>,
opt_autoref: Option<ty::AutoRef<'tcx>>)
-> mc::cmt<'tcx>
{
debug!("walk_autoref(expr.id={} cmt_derefd={} opt_autoref={:?})",
expr.id,
cmt_derefd.repr(self.tcx()),
cmt_base.repr(self.tcx()),
opt_autoref);

let cmt_base_ty = cmt_base.ty;

let autoref = match opt_autoref {
Some(autoref) => autoref,
Some(ref autoref) => autoref,
None => {
// No recursive step here, this is a base case.
return cmt_derefd.clone();
// No AutoRef.
return cmt_base;
}
};

match *autoref {
ty::AutoPtr(r, m, ref 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,
*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);

ty::AutoUnsafe(m) => {
debug!("walk_autoref: expr.id={} cmt_base={}",
expr.id,
cmt_base.repr(self.tcx()));
Expand All @@ -983,24 +929,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {

let adj_ty =
ty::adjust_ty_for_autoref(self.tcx(),
expr.span,
cmt_derefd.ty,
cmt_base_ty,
opt_autoref);

self.mc.cat_rvalue_node(expr.id, expr.span, adj_ty)
}

fn walk_autoref_recursively(&mut self,
expr: &ast::Expr,
cmt_derefd: &mc::cmt<'tcx>,
autoref: &Option<Box<ty::AutoRef<'tcx>>>)
-> mc::cmt<'tcx>
{
// Shuffle from a ref to an optional box to an optional ref.
let autoref: Option<&ty::AutoRef<'tcx>> = autoref.as_ref().map(|b| &**b);
self.walk_autoref(expr, cmt_derefd, autoref)
}


// When this returns true, it means that the expression *is* a
// method-call (i.e. via the operator-overload). This true result
Expand Down
38 changes: 11 additions & 27 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
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
Loading