Skip to content

Commit 840f3f6

Browse files
committed
typeck/expr.rs: extract out check_expr_unary.
1 parent 7227a38 commit 840f3f6

File tree

1 file changed

+88
-82
lines changed

1 file changed

+88
-82
lines changed

src/librustc_typeck/check/expr.rs

Lines changed: 88 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -62,88 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6262
self.check_binop_assign(expr, op, lhs, rhs)
6363
}
6464
ExprKind::Unary(unop, ref oprnd) => {
65-
let expected_inner = match unop {
66-
hir::UnNot | hir::UnNeg => {
67-
expected
68-
}
69-
hir::UnDeref => {
70-
NoExpectation
71-
}
72-
};
73-
let needs = match unop {
74-
hir::UnDeref => needs,
75-
_ => Needs::None
76-
};
77-
let mut oprnd_t = self.check_expr_with_expectation_and_needs(&oprnd,
78-
expected_inner,
79-
needs);
80-
81-
if !oprnd_t.references_error() {
82-
oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);
83-
match unop {
84-
hir::UnDeref => {
85-
if let Some(mt) = oprnd_t.builtin_deref(true) {
86-
oprnd_t = mt.ty;
87-
} else if let Some(ok) = self.try_overloaded_deref(
88-
expr.span, oprnd_t, needs) {
89-
let method = self.register_infer_ok_obligations(ok);
90-
if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty {
91-
let mutbl = match mutbl {
92-
hir::MutImmutable => AutoBorrowMutability::Immutable,
93-
hir::MutMutable => AutoBorrowMutability::Mutable {
94-
// (It shouldn't actually matter for unary ops whether
95-
// we enable two-phase borrows or not, since a unary
96-
// op has no additional operands.)
97-
allow_two_phase_borrow: AllowTwoPhase::No,
98-
}
99-
};
100-
self.apply_adjustments(oprnd, vec![Adjustment {
101-
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
102-
target: method.sig.inputs()[0]
103-
}]);
104-
}
105-
oprnd_t = self.make_overloaded_place_return_type(method).ty;
106-
self.write_method_call(expr.hir_id, method);
107-
} else {
108-
let mut err = type_error_struct!(
109-
tcx.sess,
110-
expr.span,
111-
oprnd_t,
112-
E0614,
113-
"type `{}` cannot be dereferenced",
114-
oprnd_t,
115-
);
116-
let sp = tcx.sess.source_map().start_point(expr.span);
117-
if let Some(sp) = tcx.sess.parse_sess.ambiguous_block_expr_parse
118-
.borrow().get(&sp)
119-
{
120-
tcx.sess.parse_sess.expr_parentheses_needed(
121-
&mut err,
122-
*sp,
123-
None,
124-
);
125-
}
126-
err.emit();
127-
oprnd_t = tcx.types.err;
128-
}
129-
}
130-
hir::UnNot => {
131-
let result = self.check_user_unop(expr, oprnd_t, unop);
132-
// If it's builtin, we can reuse the type, this helps inference.
133-
if !(oprnd_t.is_integral() || oprnd_t.sty == ty::Bool) {
134-
oprnd_t = result;
135-
}
136-
}
137-
hir::UnNeg => {
138-
let result = self.check_user_unop(expr, oprnd_t, unop);
139-
// If it's builtin, we can reuse the type, this helps inference.
140-
if !oprnd_t.is_numeric() {
141-
oprnd_t = result;
142-
}
143-
}
144-
}
145-
}
146-
oprnd_t
65+
self.check_expr_unary(unop, oprnd, expected, needs, expr)
14766
}
14867
ExprKind::AddrOf(mutbl, ref oprnd) => {
14968
let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
@@ -706,4 +625,91 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
706625
let referent_ty = self.check_expr_with_expectation(expr, expected_inner);
707626
self.tcx.mk_box(referent_ty)
708627
}
628+
629+
fn check_expr_unary(
630+
&self,
631+
unop: hir::UnOp,
632+
oprnd: &'tcx hir::Expr,
633+
expected: Expectation<'tcx>,
634+
needs: Needs,
635+
expr: &'tcx hir::Expr,
636+
) -> Ty<'tcx> {
637+
let tcx = self.tcx;
638+
let expected_inner = match unop {
639+
hir::UnNot | hir::UnNeg => expected,
640+
hir::UnDeref => NoExpectation,
641+
};
642+
let needs = match unop {
643+
hir::UnDeref => needs,
644+
_ => Needs::None
645+
};
646+
let mut oprnd_t = self.check_expr_with_expectation_and_needs(&oprnd, expected_inner, needs);
647+
648+
if !oprnd_t.references_error() {
649+
oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);
650+
match unop {
651+
hir::UnDeref => {
652+
if let Some(mt) = oprnd_t.builtin_deref(true) {
653+
oprnd_t = mt.ty;
654+
} else if let Some(ok) = self.try_overloaded_deref(
655+
expr.span, oprnd_t, needs) {
656+
let method = self.register_infer_ok_obligations(ok);
657+
if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty {
658+
let mutbl = match mutbl {
659+
hir::MutImmutable => AutoBorrowMutability::Immutable,
660+
hir::MutMutable => AutoBorrowMutability::Mutable {
661+
// (It shouldn't actually matter for unary ops whether
662+
// we enable two-phase borrows or not, since a unary
663+
// op has no additional operands.)
664+
allow_two_phase_borrow: AllowTwoPhase::No,
665+
}
666+
};
667+
self.apply_adjustments(oprnd, vec![Adjustment {
668+
kind: Adjust::Borrow(AutoBorrow::Ref(region, mutbl)),
669+
target: method.sig.inputs()[0]
670+
}]);
671+
}
672+
oprnd_t = self.make_overloaded_place_return_type(method).ty;
673+
self.write_method_call(expr.hir_id, method);
674+
} else {
675+
let mut err = type_error_struct!(
676+
tcx.sess,
677+
expr.span,
678+
oprnd_t,
679+
E0614,
680+
"type `{}` cannot be dereferenced",
681+
oprnd_t,
682+
);
683+
let sp = tcx.sess.source_map().start_point(expr.span);
684+
if let Some(sp) = tcx.sess.parse_sess.ambiguous_block_expr_parse
685+
.borrow().get(&sp)
686+
{
687+
tcx.sess.parse_sess.expr_parentheses_needed(
688+
&mut err,
689+
*sp,
690+
None,
691+
);
692+
}
693+
err.emit();
694+
oprnd_t = tcx.types.err;
695+
}
696+
}
697+
hir::UnNot => {
698+
let result = self.check_user_unop(expr, oprnd_t, unop);
699+
// If it's builtin, we can reuse the type, this helps inference.
700+
if !(oprnd_t.is_integral() || oprnd_t.sty == ty::Bool) {
701+
oprnd_t = result;
702+
}
703+
}
704+
hir::UnNeg => {
705+
let result = self.check_user_unop(expr, oprnd_t, unop);
706+
// If it's builtin, we can reuse the type, this helps inference.
707+
if !oprnd_t.is_numeric() {
708+
oprnd_t = result;
709+
}
710+
}
711+
}
712+
}
713+
oprnd_t
714+
}
709715
}

0 commit comments

Comments
 (0)