Skip to content

Commit 9d2ac9b

Browse files
committed
Auto merge of #24475 - arielb1:i24363-hacky-hack, r=pnkfelix
Fix #24363
2 parents b7fb575 + fd8c592 commit 9d2ac9b

File tree

4 files changed

+77
-59
lines changed

4 files changed

+77
-59
lines changed

src/librustc/util/ppaux.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -810,8 +810,12 @@ impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> {
810810
// to enumerate the `for<...>` etc because the debruijn index
811811
// tells you everything you need to know.
812812
let base = ty::item_path_str(tcx, self.def_id);
813-
parameterized(tcx, &base, self.substs, self.def_id, &[],
814-
|| ty::lookup_trait_def(tcx, self.def_id).generics.clone())
813+
let result = parameterized(tcx, &base, self.substs, self.def_id, &[],
814+
|| ty::lookup_trait_def(tcx, self.def_id).generics.clone());
815+
match self.substs.self_ty() {
816+
None => result,
817+
Some(sty) => format!("<{} as {}>", sty.repr(tcx), result)
818+
}
815819
}
816820
}
817821

@@ -1504,8 +1508,7 @@ impl<'tcx> UserString<'tcx> for ty::ProjectionPredicate<'tcx> {
15041508

15051509
impl<'tcx> Repr<'tcx> for ty::ProjectionTy<'tcx> {
15061510
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1507-
format!("<{} as {}>::{}",
1508-
self.trait_ref.substs.self_ty().repr(tcx),
1511+
format!("{}::{}",
15091512
self.trait_ref.repr(tcx),
15101513
self.item_name.repr(tcx))
15111514
}

src/librustc_typeck/check/mod.rs

+24-24
Original file line numberDiff line numberDiff line change
@@ -3542,34 +3542,34 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
35423542
}
35433543
ast::ExprIndex(ref base, ref idx) => {
35443544
check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
3545+
check_expr(fcx, &**idx);
3546+
35453547
let base_t = fcx.expr_ty(&**base);
3548+
let idx_t = fcx.expr_ty(&**idx);
3549+
35463550
if ty::type_is_error(base_t) {
35473551
fcx.write_ty(id, base_t);
3552+
} else if ty::type_is_error(idx_t) {
3553+
fcx.write_ty(id, idx_t);
35483554
} else {
3549-
check_expr(fcx, &**idx);
3550-
let idx_t = fcx.expr_ty(&**idx);
3551-
if ty::type_is_error(idx_t) {
3552-
fcx.write_ty(id, idx_t);
3553-
} else {
3554-
let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3555-
match lookup_indexing(fcx, expr, base, base_t, idx_t, lvalue_pref) {
3556-
Some((index_ty, element_ty)) => {
3557-
let idx_expr_ty = fcx.expr_ty(idx);
3558-
demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty);
3559-
fcx.write_ty(id, element_ty);
3560-
}
3561-
None => {
3562-
check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3563-
fcx.type_error_message(
3564-
expr.span,
3565-
|actual| {
3566-
format!("cannot index a value of type `{}`",
3567-
actual)
3568-
},
3569-
base_t,
3570-
None);
3571-
fcx.write_ty(id, fcx.tcx().types.err);
3572-
}
3555+
let base_t = structurally_resolved_type(fcx, expr.span, base_t);
3556+
match lookup_indexing(fcx, expr, base, base_t, idx_t, lvalue_pref) {
3557+
Some((index_ty, element_ty)) => {
3558+
let idx_expr_ty = fcx.expr_ty(idx);
3559+
demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty);
3560+
fcx.write_ty(id, element_ty);
3561+
}
3562+
None => {
3563+
check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
3564+
fcx.type_error_message(
3565+
expr.span,
3566+
|actual| {
3567+
format!("cannot index a value of type `{}`",
3568+
actual)
3569+
},
3570+
base_t,
3571+
None);
3572+
fcx.write_ty(id, fcx.tcx().types.err);
35733573
}
35743574
}
35753575
}

src/librustc_typeck/check/writeback.rs

+30-31
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,32 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
8585
fn tcx(&self) -> &'cx ty::ctxt<'tcx> {
8686
self.fcx.tcx()
8787
}
88+
89+
// Hacky hack: During type-checking, we treat *all* operators
90+
// as potentially overloaded. But then, during writeback, if
91+
// we observe that something like `a+b` is (known to be)
92+
// operating on scalars, we clear the overload.
93+
fn fix_scalar_binary_expr(&mut self, e: &ast::Expr) {
94+
if let ast::ExprBinary(ref op, ref lhs, ref rhs) = e.node {
95+
let lhs_ty = self.fcx.node_ty(lhs.id);
96+
let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
97+
98+
let rhs_ty = self.fcx.node_ty(rhs.id);
99+
let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
100+
101+
if ty::type_is_scalar(lhs_ty) && ty::type_is_scalar(rhs_ty) {
102+
self.fcx.inh.method_map.borrow_mut().remove(&MethodCall::expr(e.id));
103+
104+
// weird but true: the by-ref binops put an
105+
// adjustment on the lhs but not the rhs; the
106+
// adjustment for rhs is kind of baked into the
107+
// system.
108+
if !ast_util::is_by_value_binop(op.node) {
109+
self.fcx.inh.adjustments.borrow_mut().remove(&lhs.id);
110+
}
111+
}
112+
}
113+
}
88114
}
89115

90116
///////////////////////////////////////////////////////////////////////////
@@ -114,43 +140,16 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
114140
return;
115141
}
116142

117-
// Hacky hack: During type-checking, we treat *all* operators
118-
// as potentially overloaded. But then, during writeback, if
119-
// we observe that something like `a+b` is (known to be)
120-
// operating on scalars, we clear the overload.
121-
match e.node {
122-
ast::ExprBinary(ref op, ref lhs, ref rhs) => {
123-
let lhs_ty = self.fcx.expr_ty(lhs);
124-
let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
125-
let rhs_ty = self.fcx.expr_ty(rhs);
126-
let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
127-
if ty::type_is_scalar(lhs_ty) && ty::type_is_scalar(rhs_ty) {
128-
self.fcx.inh.method_map.borrow_mut().remove(&MethodCall::expr(e.id));
129-
130-
// weird but true: the by-ref binops put an
131-
// adjustment on the lhs but not the rhs; the
132-
// adjustment for rhs is kind of baked into the
133-
// system.
134-
if !ast_util::is_by_value_binop(op.node) {
135-
self.fcx.inh.adjustments.borrow_mut().remove(&lhs.id);
136-
}
137-
}
138-
}
139-
_ => { }
140-
}
143+
self.fix_scalar_binary_expr(e);
141144

142145
self.visit_node_id(ResolvingExpr(e.span), e.id);
143146
self.visit_method_map_entry(ResolvingExpr(e.span),
144147
MethodCall::expr(e.id));
145148

146-
match e.node {
147-
ast::ExprClosure(_, ref decl, _) => {
148-
for input in &decl.inputs {
149-
let _ = self.visit_node_id(ResolvingExpr(e.span),
150-
input.id);
151-
}
149+
if let ast::ExprClosure(_, ref decl, _) = e.node {
150+
for input in &decl.inputs {
151+
self.visit_node_id(ResolvingExpr(e.span), input.id);
152152
}
153-
_ => {}
154153
}
155154

156155
visit::walk_expr(self, e);

src/test/compile-fail/issue-24363.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
1.create_a_type_error[ //~ ERROR attempted access of field
13+
()+() //~ ERROR binary operation `+` cannot be applied
14+
// ^ ensure that we typeck the inner expression ^
15+
];
16+
}

0 commit comments

Comments
 (0)