Skip to content

Commit 6383de1

Browse files
author
Cengiz Can
committed
fixes #40013
1 parent c398efc commit 6383de1

14 files changed

+258
-273
lines changed

src/librustc/diagnostics.rs

+52
Original file line numberDiff line numberDiff line change
@@ -1807,6 +1807,58 @@ makes a difference in practice.)
18071807
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
18081808
"##,
18091809

1810+
/*
1811+
1812+
E0101: r##"
1813+
#### Note: this error code is no longer emitted by the compiler.
1814+
1815+
You hit this error because the compiler lacks the information to
1816+
determine a type for this expression. Erroneous code example:
1817+
1818+
```ignore
1819+
let x = |_| {}; // error: cannot determine a type for this expression
1820+
```
1821+
1822+
You have two possibilities to solve this situation:
1823+
1824+
* Give an explicit definition of the expression
1825+
* Infer the expression
1826+
1827+
Examples:
1828+
1829+
```
1830+
let x = |_ : u32| {}; // ok!
1831+
// or:
1832+
let x = |_| {};
1833+
x(0u32);
1834+
```
1835+
"##,
1836+
1837+
E0102: r##"
1838+
#### Note: this error code is no longer emitted by the compiler.
1839+
1840+
You hit this error because the compiler lacks the information to
1841+
determine the type of this variable. Erroneous code example:
1842+
1843+
```ignore
1844+
// could be an array of anything
1845+
let x = []; // error: cannot determine a type for this local variable
1846+
```
1847+
1848+
To solve this situation, constrain the type of the variable.
1849+
Examples:
1850+
1851+
```
1852+
#![allow(unused_variables)]
1853+
1854+
fn main() {
1855+
let x: [u8; 0] = [];
1856+
}
1857+
```
1858+
"##,
1859+
1860+
*/
1861+
18101862
}
18111863

18121864

src/librustc/traits/error_reporting.rs

+84-41
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@ use super::{
2525

2626
use errors::DiagnosticBuilder;
2727
use fmt_macros::{Parser, Piece, Position};
28-
use hir::{intravisit, Local, Pat};
28+
use hir::{self, intravisit, Local, Pat, Body};
2929
use hir::intravisit::{Visitor, NestedVisitorMap};
3030
use hir::map::NodeExpr;
3131
use hir::def_id::DefId;
3232
use infer::{self, InferCtxt};
3333
use infer::type_variable::TypeVariableOrigin;
3434
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
3535
use std::fmt;
36-
use syntax::ast;
37-
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
36+
use syntax::ast::{self, NodeId};
37+
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TyInfer, TyVar};
3838
use ty::error::ExpectedFound;
3939
use ty::fast_reject;
4040
use ty::fold::TypeFolder;
@@ -66,37 +66,52 @@ impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
6666
struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
6767
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
6868
target_ty: &'a Ty<'tcx>,
69-
found_pattern: Option<&'a Pat>,
69+
hir_map: &'a hir::map::Map<'gcx>,
70+
found_local_pattern: Option<&'gcx Pat>,
71+
found_arg_pattern: Option<&'gcx Pat>,
7072
}
7173

7274
impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
73-
fn is_match(&self, ty: Ty<'tcx>) -> bool {
74-
ty == *self.target_ty || match (&ty.sty, &self.target_ty.sty) {
75-
(&ty::TyInfer(ty::TyVar(a_vid)), &ty::TyInfer(ty::TyVar(b_vid))) =>
76-
self.infcx.type_variables
77-
.borrow_mut()
78-
.sub_unified(a_vid, b_vid),
79-
75+
fn node_matches_type(&mut self, node_id: &'gcx NodeId) -> bool {
76+
match self.infcx.tables.borrow().node_types.get(node_id) {
77+
Some(&ty) => {
78+
let ty = self.infcx.resolve_type_vars_if_possible(&ty);
79+
ty.walk().any(|inner_ty| {
80+
inner_ty == *self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
81+
(&TyInfer(TyVar(a_vid)), &TyInfer(TyVar(b_vid))) => {
82+
self.infcx
83+
.type_variables
84+
.borrow_mut()
85+
.sub_unified(a_vid, b_vid)
86+
}
87+
_ => false,
88+
}
89+
})
90+
}
8091
_ => false,
8192
}
8293
}
8394
}
8495

85-
impl<'a, 'gcx, 'tcx> Visitor<'a> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
86-
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'a> {
87-
NestedVisitorMap::None
96+
impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
97+
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
98+
NestedVisitorMap::OnlyBodies(&self.hir_map)
8899
}
89100

90-
fn visit_local(&mut self, local: &'a Local) {
91-
if let Some(&ty) = self.infcx.tables.borrow().node_types.get(&local.id) {
92-
let ty = self.infcx.resolve_type_vars_if_possible(&ty);
93-
let is_match = ty.walk().any(|t| self.is_match(t));
101+
fn visit_local(&mut self, local: &'gcx Local) {
102+
if self.found_local_pattern.is_none() && self.node_matches_type(&local.id) {
103+
self.found_local_pattern = Some(&*local.pat);
104+
}
105+
intravisit::walk_local(self, local);
106+
}
94107

95-
if is_match && self.found_pattern.is_none() {
96-
self.found_pattern = Some(&*local.pat);
108+
fn visit_body(&mut self, body: &'gcx Body) {
109+
for argument in &body.arguments {
110+
if self.found_arg_pattern.is_none() && self.node_matches_type(&argument.id) {
111+
self.found_arg_pattern = Some(&*argument.pat);
97112
}
98113
}
99-
intravisit::walk_local(self, local);
114+
intravisit::walk_body(self, body);
100115
}
101116
}
102117

@@ -721,6 +736,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
721736
// coherence violation, so we don't report it here.
722737

723738
let predicate = self.resolve_type_vars_if_possible(&obligation.predicate);
739+
let body_id = hir::BodyId { node_id: obligation.cause.body_id };
740+
let span = obligation.cause.span;
724741

725742
debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
726743
predicate,
@@ -768,10 +785,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
768785
self.tcx.lang_items.sized_trait()
769786
.map_or(false, |sized_id| sized_id == trait_ref.def_id())
770787
{
771-
self.need_type_info(obligation, self_ty);
788+
self.need_type_info(body_id, span, self_ty);
772789
} else {
773790
let mut err = struct_span_err!(self.tcx.sess,
774-
obligation.cause.span, E0283,
791+
span, E0283,
775792
"type annotations required: \
776793
cannot resolve `{}`",
777794
predicate);
@@ -785,7 +802,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
785802
// Same hacky approach as above to avoid deluging user
786803
// with error messages.
787804
if !ty.references_error() && !self.tcx.sess.has_errors() {
788-
self.need_type_info(obligation, ty);
805+
self.need_type_info(body_id, span, ty);
789806
}
790807
}
791808

@@ -796,7 +813,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
796813
let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
797814
// both must be type variables, or the other would've been instantiated
798815
assert!(a.is_ty_var() && b.is_ty_var());
799-
self.need_type_info(obligation, a);
816+
self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id },
817+
obligation.cause.span,
818+
a);
800819
}
801820
}
802821

@@ -874,42 +893,66 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
874893
}
875894
}
876895

877-
fn need_type_info(&self, obligation: &PredicateObligation<'tcx>, ty: Ty<'tcx>) {
896+
pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) {
878897
let ty = self.resolve_type_vars_if_possible(&ty);
879898
let name = self.extract_type_name(&ty);
880-
let ref cause = obligation.cause;
881899

882-
let mut err = struct_span_err!(self.tcx.sess,
883-
cause.span,
884-
E0282,
885-
"type annotations needed");
886-
887-
err.span_label(cause.span, &format!("cannot infer type for `{}`", name));
900+
let mut err_span = span;
901+
let mut labels = vec![(span, format!("cannot infer type for `{}`", name))];
888902

889903
let mut local_visitor = FindLocalByTypeVisitor {
890904
infcx: &self,
891905
target_ty: &ty,
892-
found_pattern: None,
906+
hir_map: &self.tcx.hir,
907+
found_local_pattern: None,
908+
found_arg_pattern: None,
893909
};
894910

895911
// #40294: cause.body_id can also be a fn declaration.
896912
// Currently, if it's anything other than NodeExpr, we just ignore it
897-
match self.tcx.hir.find(cause.body_id) {
913+
match self.tcx.hir.find(body_id.node_id) {
898914
Some(NodeExpr(expr)) => local_visitor.visit_expr(expr),
899915
_ => ()
900916
}
901917

902-
if let Some(pattern) = local_visitor.found_pattern {
903-
let pattern_span = pattern.span;
918+
if let Some(pattern) = local_visitor.found_arg_pattern {
919+
err_span = pattern.span;
920+
// We don't want to show the default label for closures.
921+
//
922+
// So, before clearing, the output would look something like this:
923+
// ```
924+
// let x = |_| { };
925+
// - ^^^^ cannot infer type for `[_; 0]`
926+
// |
927+
// consider giving this closure parameter a type
928+
// ```
929+
//
930+
// After clearing, it looks something like this:
931+
// ```
932+
// let x = |_| { };
933+
// ^ consider giving this closure parameter a type
934+
// ```
935+
labels.clear();
936+
labels.push((pattern.span, format!("consider giving this closure parameter a type")));
937+
}
938+
939+
if let Some(pattern) = local_visitor.found_local_pattern {
904940
if let Some(simple_name) = pattern.simple_name() {
905-
err.span_label(pattern_span,
906-
&format!("consider giving `{}` a type",
907-
simple_name));
941+
labels.push((pattern.span, format!("consider giving `{}` a type", simple_name)));
908942
} else {
909-
err.span_label(pattern_span, &format!("consider giving a type to pattern"));
943+
labels.push((pattern.span, format!("consider giving a type to pattern")));
910944
}
911945
}
912946

947+
let mut err = struct_span_err!(self.tcx.sess,
948+
err_span,
949+
E0282,
950+
"type annotations needed");
951+
952+
for (target_span, label_message) in labels {
953+
err.span_label(target_span, &label_message);
954+
}
955+
913956
err.emit();
914957
}
915958

0 commit comments

Comments
 (0)