Skip to content

Commit 7724455

Browse files
committed
switch projection errors to use the new type error messages
Unfortunately, projection errors do not come with a nice set of mismatched types. This is because the type equality check occurs within a higher-ranked context. Therefore, only the type error is reported. This is ugly but was always the situation. I will introduce better errors for the lower-ranked case in another commit. Fixes the last known occurence of rust-lang#31173
1 parent 620d4cb commit 7724455

File tree

6 files changed

+73
-32
lines changed

6 files changed

+73
-32
lines changed

src/librustc/infer/error_reporting.rs

+26-18
Original file line numberDiff line numberDiff line change
@@ -522,37 +522,45 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
522522
}
523523

524524
pub fn report_and_explain_type_error_with_code(&self,
525-
trace: TypeTrace<'tcx>,
525+
origin: TypeOrigin,
526+
values: Option<ValuePairs<'tcx>>,
526527
terr: &TypeError<'tcx>,
527528
message: &str,
528529
code: &str)
529530
-> DiagnosticBuilder<'tcx>
530531
{
531-
let (expected, found) = match self.values_str(&trace.values) {
532-
Some((expected, found)) => (expected, found),
533-
None => return self.tcx.sess.diagnostic().struct_dummy() /* derived error */
532+
let expected_found = match values {
533+
None => None,
534+
Some(values) => match self.values_str(&values) {
535+
Some((expected, found)) => Some((expected, found)),
536+
None => return self.tcx.sess.diagnostic().struct_dummy() /* derived error */
537+
}
534538
};
535539

536-
let span = trace.origin.span();
540+
let span = origin.span();
541+
let mut err = self.tcx.sess.struct_span_err_with_code(
542+
span, message, code);
537543

538-
let is_simple_error = if let &TypeError::Sorts(ref values) = terr {
539-
values.expected.is_primitive() && values.found.is_primitive()
540-
} else {
541-
false
542-
};
544+
let mut is_simple_error = false;
543545

544-
let mut err = self.tcx.sess.struct_span_err_with_code(
545-
trace.origin.span(),
546-
message,
547-
code);
546+
if let Some((expected, found)) = expected_found {
547+
is_simple_error = if let &TypeError::Sorts(ref values) = terr {
548+
values.expected.is_primitive() && values.found.is_primitive()
549+
} else {
550+
false
551+
};
548552

549-
if !is_simple_error || check_old_school() {
550-
err.note_expected_found(&"type", &expected, &found);
553+
if !is_simple_error || check_old_school() {
554+
err.note_expected_found(&"type", &expected, &found);
555+
}
551556
}
552557

558+
if !is_simple_error && check_old_school() {
559+
err.span_note(span, &format!("{}", terr));
560+
}
553561
err.span_label(span, &terr);
554562

555-
self.note_error_origin(&mut err, &trace.origin);
563+
self.note_error_origin(&mut err, &origin);
556564
self.check_and_note_conflicting_crates(&mut err, terr, span);
557565
self.tcx.note_and_explain_type_err(&mut err, terr, span);
558566

@@ -566,7 +574,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
566574
{
567575
// FIXME: do we want to use a different error code for each origin?
568576
let failure_str = trace.origin.as_failure_str();
569-
type_err!(self, trace, terr, E0308, "{}", failure_str)
577+
type_err!(self, trace.origin, Some(trace.values), terr, E0308, "{}", failure_str)
570578
}
571579

572580
/// Returns a string of the form "expected `{}`, found `{}`".

src/librustc/macros.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,12 @@ macro_rules! span_bug {
6262

6363
#[macro_export]
6464
macro_rules! type_err {
65-
($infcx:expr, $trace: expr, $terr: expr, $code:ident, $($message:tt)*) => ({
65+
($infcx:expr, $origin: expr, $values: expr, $terr: expr, $code:ident, $($message:tt)*) => ({
6666
__diagnostic_used!($code);
6767
$infcx.report_and_explain_type_error_with_code(
68-
$trace,
69-
$terr,
68+
$origin,
69+
$values,
70+
&$terr,
7071
&format!($($message)*),
7172
stringify!($code))
7273
})

src/librustc/traits/error_reporting.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use super::{
2626

2727
use fmt_macros::{Parser, Piece, Position};
2828
use hir::def_id::DefId;
29-
use infer::{InferCtxt};
29+
use infer::{InferCtxt, TypeOrigin};
3030
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
3131
use ty::fast_reject;
3232
use ty::fold::TypeFolder;
@@ -117,10 +117,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
117117
predicate,
118118
error.err));
119119
} else {
120-
let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271,
121-
"type mismatch resolving `{}`: {}",
122-
predicate,
123-
error.err);
120+
let mut err = type_err!(
121+
self,
122+
TypeOrigin::Misc(obligation.cause.span),
123+
None, // FIXME: be smarter
124+
error.err,
125+
E0271,
126+
"type mismatch resolving `{}`",
127+
predicate);
124128
self.note_obligation_cause(&mut err, obligation);
125129
err.emit();
126130
}

src/librustc_typeck/check/compare_method.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use middle::free_region::FreeRegionMap;
1212
use rustc::infer::{self, InferOk, TypeOrigin};
1313
use rustc::ty;
1414
use rustc::traits::{self, ProjectionMode};
15+
use rustc::ty::error::ExpectedFound;
1516
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
1617

1718
use syntax::ast;
@@ -324,8 +325,11 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
324325
debug!("sub_types failed: impl ty {:?}, trait ty {:?}",
325326
impl_fty,
326327
trait_fty);
327-
let trace = infer::TypeTrace::types(origin, false, impl_fty, trait_fty);
328-
type_err!(infcx, trace, &terr, E0053,
328+
let values = Some(infer::ValuePairs::Types(ExpectedFound {
329+
expected: trait_fty,
330+
found: impl_fty
331+
}));
332+
type_err!(infcx, origin, values, terr, E0053,
329333
"method `{}` has an incompatible type for trait",
330334
trait_m.name).emit();
331335
return

src/test/compile-fail/associated-types-eq-3.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,8 @@ pub fn main() {
4747
let a = 42;
4848
foo1(a);
4949
//~^ ERROR type mismatch resolving
50-
//~| expected usize
51-
//~| found struct `Bar`
50+
//~| expected usize, found struct `Bar`
5251
baz(&a);
5352
//~^ ERROR type mismatch resolving
54-
//~| expected usize
55-
//~| found struct `Bar`
53+
//~| expected usize, found struct `Bar`
5654
}

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

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2016 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+
use std::vec::IntoIter;
12+
13+
pub fn get_tok(it: &mut IntoIter<u8>) {
14+
let mut found_e = false;
15+
16+
let temp: Vec<u8> = it.take_while(|&x| {
17+
found_e = true;
18+
false
19+
})
20+
.cloned()
21+
//~^ ERROR type mismatch resolving
22+
//~| expected u8, found &-ptr
23+
.collect(); //~ ERROR no method named `collect`
24+
}
25+
26+
fn main() {}

0 commit comments

Comments
 (0)