Skip to content

Commit

Permalink
typeck/expr.rs: extract out check_expr_addr_of.
Browse files Browse the repository at this point in the history
  • Loading branch information
Centril committed Jun 14, 2019
1 parent 840f3f6 commit d5cc080
Showing 1 changed file with 48 additions and 38 deletions.
86 changes: 48 additions & 38 deletions src/librustc_typeck/check/expr.rs
Expand Up @@ -65,44 +65,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_expr_unary(unop, oprnd, expected, needs, expr)
}
ExprKind::AddrOf(mutbl, ref oprnd) => {
let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
match ty.sty {
ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
if oprnd.is_place_expr() {
// Places may legitimately have unsized types.
// For example, dereferences of a fat pointer and
// the last field of a struct can be unsized.
ExpectHasType(ty)
} else {
Expectation::rvalue_hint(self, ty)
}
}
_ => NoExpectation
}
});
let needs = Needs::maybe_mut_place(mutbl);
let ty = self.check_expr_with_expectation_and_needs(&oprnd, hint, needs);

let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl };
if tm.ty.references_error() {
tcx.types.err
} else {
// Note: at this point, we cannot say what the best lifetime
// is to use for resulting pointer. We want to use the
// shortest lifetime possible so as to avoid spurious borrowck
// errors. Moreover, the longest lifetime will depend on the
// precise details of the value whose address is being taken
// (and how long it is valid), which we don't know yet until type
// inference is complete.
//
// Therefore, here we simply generate a region variable. The
// region inferencer will then select the ultimate value.
// Finally, borrowck is charged with guaranteeing that the
// value whose address was taken can actually be made to live
// as long as it needs to live.
let region = self.next_region_var(infer::AddrOfRegion(expr.span));
tcx.mk_ref(region, tm)
}
self.check_expr_addr_of(mutbl, oprnd, expected, expr)
}
ExprKind::Path(ref qpath) => {
let (res, opt_ty, segs) = self.resolve_ty_and_res_ufcs(qpath, expr.hir_id,
Expand Down Expand Up @@ -712,4 +675,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
oprnd_t
}

fn check_expr_addr_of(
&self,
mutbl: hir::Mutability,
oprnd: &'tcx hir::Expr,
expected: Expectation<'tcx>,
expr: &'tcx hir::Expr,
) -> Ty<'tcx> {
let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
match ty.sty {
ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
if oprnd.is_place_expr() {
// Places may legitimately have unsized types.
// For example, dereferences of a fat pointer and
// the last field of a struct can be unsized.
ExpectHasType(ty)
} else {
Expectation::rvalue_hint(self, ty)
}
}
_ => NoExpectation
}
});
let needs = Needs::maybe_mut_place(mutbl);
let ty = self.check_expr_with_expectation_and_needs(&oprnd, hint, needs);

let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl };
if tm.ty.references_error() {
self.tcx.types.err
} else {
// Note: at this point, we cannot say what the best lifetime
// is to use for resulting pointer. We want to use the
// shortest lifetime possible so as to avoid spurious borrowck
// errors. Moreover, the longest lifetime will depend on the
// precise details of the value whose address is being taken
// (and how long it is valid), which we don't know yet until type
// inference is complete.
//
// Therefore, here we simply generate a region variable. The
// region inferencer will then select the ultimate value.
// Finally, borrowck is charged with guaranteeing that the
// value whose address was taken can actually be made to live
// as long as it needs to live.
let region = self.next_region_var(infer::AddrOfRegion(expr.span));
self.tcx.mk_ref(region, tm)
}
}
}

0 comments on commit d5cc080

Please sign in to comment.