Auto merge of #24475 - arielb1:i24363-hacky-hack, r=pnkfelix
Fix #24363
This commit is contained in:
commit
9d2ac9b1e1
4 changed files with 77 additions and 59 deletions
|
@ -810,8 +810,12 @@ impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> {
|
||||||
// to enumerate the `for<...>` etc because the debruijn index
|
// to enumerate the `for<...>` etc because the debruijn index
|
||||||
// tells you everything you need to know.
|
// tells you everything you need to know.
|
||||||
let base = ty::item_path_str(tcx, self.def_id);
|
let base = ty::item_path_str(tcx, self.def_id);
|
||||||
parameterized(tcx, &base, self.substs, self.def_id, &[],
|
let result = parameterized(tcx, &base, self.substs, self.def_id, &[],
|
||||||
|| ty::lookup_trait_def(tcx, self.def_id).generics.clone())
|
|| ty::lookup_trait_def(tcx, self.def_id).generics.clone());
|
||||||
|
match self.substs.self_ty() {
|
||||||
|
None => result,
|
||||||
|
Some(sty) => format!("<{} as {}>", sty.repr(tcx), result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1504,8 +1508,7 @@ impl<'tcx> UserString<'tcx> for ty::ProjectionPredicate<'tcx> {
|
||||||
|
|
||||||
impl<'tcx> Repr<'tcx> for ty::ProjectionTy<'tcx> {
|
impl<'tcx> Repr<'tcx> for ty::ProjectionTy<'tcx> {
|
||||||
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
|
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
|
||||||
format!("<{} as {}>::{}",
|
format!("{}::{}",
|
||||||
self.trait_ref.substs.self_ty().repr(tcx),
|
|
||||||
self.trait_ref.repr(tcx),
|
self.trait_ref.repr(tcx),
|
||||||
self.item_name.repr(tcx))
|
self.item_name.repr(tcx))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3542,34 +3542,34 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
ast::ExprIndex(ref base, ref idx) => {
|
ast::ExprIndex(ref base, ref idx) => {
|
||||||
check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
|
check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
|
||||||
|
check_expr(fcx, &**idx);
|
||||||
|
|
||||||
let base_t = fcx.expr_ty(&**base);
|
let base_t = fcx.expr_ty(&**base);
|
||||||
|
let idx_t = fcx.expr_ty(&**idx);
|
||||||
|
|
||||||
if ty::type_is_error(base_t) {
|
if ty::type_is_error(base_t) {
|
||||||
fcx.write_ty(id, base_t);
|
fcx.write_ty(id, base_t);
|
||||||
|
} else if ty::type_is_error(idx_t) {
|
||||||
|
fcx.write_ty(id, idx_t);
|
||||||
} else {
|
} else {
|
||||||
check_expr(fcx, &**idx);
|
let base_t = structurally_resolved_type(fcx, expr.span, base_t);
|
||||||
let idx_t = fcx.expr_ty(&**idx);
|
match lookup_indexing(fcx, expr, base, base_t, idx_t, lvalue_pref) {
|
||||||
if ty::type_is_error(idx_t) {
|
Some((index_ty, element_ty)) => {
|
||||||
fcx.write_ty(id, idx_t);
|
let idx_expr_ty = fcx.expr_ty(idx);
|
||||||
} else {
|
demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty);
|
||||||
let base_t = structurally_resolved_type(fcx, expr.span, base_t);
|
fcx.write_ty(id, element_ty);
|
||||||
match lookup_indexing(fcx, expr, base, base_t, idx_t, lvalue_pref) {
|
}
|
||||||
Some((index_ty, element_ty)) => {
|
None => {
|
||||||
let idx_expr_ty = fcx.expr_ty(idx);
|
check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
|
||||||
demand::eqtype(fcx, expr.span, index_ty, idx_expr_ty);
|
fcx.type_error_message(
|
||||||
fcx.write_ty(id, element_ty);
|
expr.span,
|
||||||
}
|
|actual| {
|
||||||
None => {
|
format!("cannot index a value of type `{}`",
|
||||||
check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
|
actual)
|
||||||
fcx.type_error_message(
|
},
|
||||||
expr.span,
|
base_t,
|
||||||
|actual| {
|
None);
|
||||||
format!("cannot index a value of type `{}`",
|
fcx.write_ty(id, fcx.tcx().types.err);
|
||||||
actual)
|
|
||||||
},
|
|
||||||
base_t,
|
|
||||||
None);
|
|
||||||
fcx.write_ty(id, fcx.tcx().types.err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,32 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||||
fn tcx(&self) -> &'cx ty::ctxt<'tcx> {
|
fn tcx(&self) -> &'cx ty::ctxt<'tcx> {
|
||||||
self.fcx.tcx()
|
self.fcx.tcx()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hacky hack: During type-checking, we treat *all* operators
|
||||||
|
// as potentially overloaded. But then, during writeback, if
|
||||||
|
// we observe that something like `a+b` is (known to be)
|
||||||
|
// operating on scalars, we clear the overload.
|
||||||
|
fn fix_scalar_binary_expr(&mut self, e: &ast::Expr) {
|
||||||
|
if let ast::ExprBinary(ref op, ref lhs, ref rhs) = e.node {
|
||||||
|
let lhs_ty = self.fcx.node_ty(lhs.id);
|
||||||
|
let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
|
||||||
|
|
||||||
|
let rhs_ty = self.fcx.node_ty(rhs.id);
|
||||||
|
let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
|
||||||
|
|
||||||
|
if ty::type_is_scalar(lhs_ty) && ty::type_is_scalar(rhs_ty) {
|
||||||
|
self.fcx.inh.method_map.borrow_mut().remove(&MethodCall::expr(e.id));
|
||||||
|
|
||||||
|
// weird but true: the by-ref binops put an
|
||||||
|
// adjustment on the lhs but not the rhs; the
|
||||||
|
// adjustment for rhs is kind of baked into the
|
||||||
|
// system.
|
||||||
|
if !ast_util::is_by_value_binop(op.node) {
|
||||||
|
self.fcx.inh.adjustments.borrow_mut().remove(&lhs.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -114,43 +140,16 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hacky hack: During type-checking, we treat *all* operators
|
self.fix_scalar_binary_expr(e);
|
||||||
// as potentially overloaded. But then, during writeback, if
|
|
||||||
// we observe that something like `a+b` is (known to be)
|
|
||||||
// operating on scalars, we clear the overload.
|
|
||||||
match e.node {
|
|
||||||
ast::ExprBinary(ref op, ref lhs, ref rhs) => {
|
|
||||||
let lhs_ty = self.fcx.expr_ty(lhs);
|
|
||||||
let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
|
|
||||||
let rhs_ty = self.fcx.expr_ty(rhs);
|
|
||||||
let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
|
|
||||||
if ty::type_is_scalar(lhs_ty) && ty::type_is_scalar(rhs_ty) {
|
|
||||||
self.fcx.inh.method_map.borrow_mut().remove(&MethodCall::expr(e.id));
|
|
||||||
|
|
||||||
// weird but true: the by-ref binops put an
|
|
||||||
// adjustment on the lhs but not the rhs; the
|
|
||||||
// adjustment for rhs is kind of baked into the
|
|
||||||
// system.
|
|
||||||
if !ast_util::is_by_value_binop(op.node) {
|
|
||||||
self.fcx.inh.adjustments.borrow_mut().remove(&lhs.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => { }
|
|
||||||
}
|
|
||||||
|
|
||||||
self.visit_node_id(ResolvingExpr(e.span), e.id);
|
self.visit_node_id(ResolvingExpr(e.span), e.id);
|
||||||
self.visit_method_map_entry(ResolvingExpr(e.span),
|
self.visit_method_map_entry(ResolvingExpr(e.span),
|
||||||
MethodCall::expr(e.id));
|
MethodCall::expr(e.id));
|
||||||
|
|
||||||
match e.node {
|
if let ast::ExprClosure(_, ref decl, _) = e.node {
|
||||||
ast::ExprClosure(_, ref decl, _) => {
|
for input in &decl.inputs {
|
||||||
for input in &decl.inputs {
|
self.visit_node_id(ResolvingExpr(e.span), input.id);
|
||||||
let _ = self.visit_node_id(ResolvingExpr(e.span),
|
|
||||||
input.id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visit::walk_expr(self, e);
|
visit::walk_expr(self, e);
|
||||||
|
|
16
src/test/compile-fail/issue-24363.rs
Normal file
16
src/test/compile-fail/issue-24363.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
1.create_a_type_error[ //~ ERROR attempted access of field
|
||||||
|
()+() //~ ERROR binary operation `+` cannot be applied
|
||||||
|
// ^ ensure that we typeck the inner expression ^
|
||||||
|
];
|
||||||
|
}
|
Loading…
Reference in a new issue