typeck/expr.rs: extract out check_expr_unary.
This commit is contained in:
parent
7227a386a5
commit
840f3f64dc
@ -62,88 +62,7 @@ pub(super) fn check_expr_kind(
|
||||
self.check_binop_assign(expr, op, lhs, rhs)
|
||||
}
|
||||
ExprKind::Unary(unop, ref oprnd) => {
|
||||
let expected_inner = match unop {
|
||||
hir::UnNot | hir::UnNeg => {
|
||||
expected
|
||||
}
|
||||
hir::UnDeref => {
|
||||
NoExpectation
|
||||
}
|
||||
};
|
||||
let needs = match unop {
|
||||
hir::UnDeref => needs,
|
||||
_ => Needs::None
|
||||
};
|
||||
let mut oprnd_t = self.check_expr_with_expectation_and_needs(&oprnd,
|
||||
expected_inner,
|
||||
needs);
|
||||
|
||||
if !oprnd_t.references_error() {
|
||||
oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);
|
||||
match unop {
|
||||
hir::UnDeref => {
|
||||
if let Some(mt) = oprnd_t.builtin_deref(true) {
|
||||
oprnd_t = mt.ty;
|
||||
} else if let Some(ok) = self.try_overloaded_deref(
|
||||
expr.span, oprnd_t, needs) {
|
||||
let method = self.register_infer_ok_obligations(ok);
|
||||
if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty {
|
||||
let mutbl = match mutbl {
|
||||
hir::MutImmutable => AutoBorrowMutability::Immutable,
|
||||
hir::MutMutable => AutoBorrowMutability::Mutable {
|
||||
// (It shouldn't actually matter for unary ops whether
|
||||
// we enable two-phase borrows or not, since a unary
|
||||
// op has no additional operands.)
|
||||
allow_two_phase_borrow: AllowTwoPhase::No,
|
||||
}
|
||||
};
|
||||
self.apply_adjustments(oprnd, vec![Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
|
||||
target: method.sig.inputs()[0]
|
||||
}]);
|
||||
}
|
||||
oprnd_t = self.make_overloaded_place_return_type(method).ty;
|
||||
self.write_method_call(expr.hir_id, method);
|
||||
} else {
|
||||
let mut err = type_error_struct!(
|
||||
tcx.sess,
|
||||
expr.span,
|
||||
oprnd_t,
|
||||
E0614,
|
||||
"type `{}` cannot be dereferenced",
|
||||
oprnd_t,
|
||||
);
|
||||
let sp = tcx.sess.source_map().start_point(expr.span);
|
||||
if let Some(sp) = tcx.sess.parse_sess.ambiguous_block_expr_parse
|
||||
.borrow().get(&sp)
|
||||
{
|
||||
tcx.sess.parse_sess.expr_parentheses_needed(
|
||||
&mut err,
|
||||
*sp,
|
||||
None,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
oprnd_t = tcx.types.err;
|
||||
}
|
||||
}
|
||||
hir::UnNot => {
|
||||
let result = self.check_user_unop(expr, oprnd_t, unop);
|
||||
// If it's builtin, we can reuse the type, this helps inference.
|
||||
if !(oprnd_t.is_integral() || oprnd_t.sty == ty::Bool) {
|
||||
oprnd_t = result;
|
||||
}
|
||||
}
|
||||
hir::UnNeg => {
|
||||
let result = self.check_user_unop(expr, oprnd_t, unop);
|
||||
// If it's builtin, we can reuse the type, this helps inference.
|
||||
if !oprnd_t.is_numeric() {
|
||||
oprnd_t = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
oprnd_t
|
||||
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| {
|
||||
@ -706,4 +625,91 @@ fn check_expr_box(&self, expr: &'tcx hir::Expr, expected: Expectation<'tcx>) ->
|
||||
let referent_ty = self.check_expr_with_expectation(expr, expected_inner);
|
||||
self.tcx.mk_box(referent_ty)
|
||||
}
|
||||
|
||||
fn check_expr_unary(
|
||||
&self,
|
||||
unop: hir::UnOp,
|
||||
oprnd: &'tcx hir::Expr,
|
||||
expected: Expectation<'tcx>,
|
||||
needs: Needs,
|
||||
expr: &'tcx hir::Expr,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let expected_inner = match unop {
|
||||
hir::UnNot | hir::UnNeg => expected,
|
||||
hir::UnDeref => NoExpectation,
|
||||
};
|
||||
let needs = match unop {
|
||||
hir::UnDeref => needs,
|
||||
_ => Needs::None
|
||||
};
|
||||
let mut oprnd_t = self.check_expr_with_expectation_and_needs(&oprnd, expected_inner, needs);
|
||||
|
||||
if !oprnd_t.references_error() {
|
||||
oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);
|
||||
match unop {
|
||||
hir::UnDeref => {
|
||||
if let Some(mt) = oprnd_t.builtin_deref(true) {
|
||||
oprnd_t = mt.ty;
|
||||
} else if let Some(ok) = self.try_overloaded_deref(
|
||||
expr.span, oprnd_t, needs) {
|
||||
let method = self.register_infer_ok_obligations(ok);
|
||||
if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty {
|
||||
let mutbl = match mutbl {
|
||||
hir::MutImmutable => AutoBorrowMutability::Immutable,
|
||||
hir::MutMutable => AutoBorrowMutability::Mutable {
|
||||
// (It shouldn't actually matter for unary ops whether
|
||||
// we enable two-phase borrows or not, since a unary
|
||||
// op has no additional operands.)
|
||||
allow_two_phase_borrow: AllowTwoPhase::No,
|
||||
}
|
||||
};
|
||||
self.apply_adjustments(oprnd, vec![Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
|
||||
target: method.sig.inputs()[0]
|
||||
}]);
|
||||
}
|
||||
oprnd_t = self.make_overloaded_place_return_type(method).ty;
|
||||
self.write_method_call(expr.hir_id, method);
|
||||
} else {
|
||||
let mut err = type_error_struct!(
|
||||
tcx.sess,
|
||||
expr.span,
|
||||
oprnd_t,
|
||||
E0614,
|
||||
"type `{}` cannot be dereferenced",
|
||||
oprnd_t,
|
||||
);
|
||||
let sp = tcx.sess.source_map().start_point(expr.span);
|
||||
if let Some(sp) = tcx.sess.parse_sess.ambiguous_block_expr_parse
|
||||
.borrow().get(&sp)
|
||||
{
|
||||
tcx.sess.parse_sess.expr_parentheses_needed(
|
||||
&mut err,
|
||||
*sp,
|
||||
None,
|
||||
);
|
||||
}
|
||||
err.emit();
|
||||
oprnd_t = tcx.types.err;
|
||||
}
|
||||
}
|
||||
hir::UnNot => {
|
||||
let result = self.check_user_unop(expr, oprnd_t, unop);
|
||||
// If it's builtin, we can reuse the type, this helps inference.
|
||||
if !(oprnd_t.is_integral() || oprnd_t.sty == ty::Bool) {
|
||||
oprnd_t = result;
|
||||
}
|
||||
}
|
||||
hir::UnNeg => {
|
||||
let result = self.check_user_unop(expr, oprnd_t, unop);
|
||||
// If it's builtin, we can reuse the type, this helps inference.
|
||||
if !oprnd_t.is_numeric() {
|
||||
oprnd_t = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
oprnd_t
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user