mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 09:44:08 +00:00
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 #31173
This commit is contained in:
parent
b7b2db4da7
commit
fa4eda8935
@ -522,37 +522,46 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn report_and_explain_type_error_with_code(&self,
|
pub fn report_and_explain_type_error_with_code(&self,
|
||||||
trace: TypeTrace<'tcx>,
|
origin: TypeOrigin,
|
||||||
|
values: Option<ValuePairs<'tcx>>,
|
||||||
terr: &TypeError<'tcx>,
|
terr: &TypeError<'tcx>,
|
||||||
message: &str,
|
message: &str,
|
||||||
code: &str)
|
code: &str)
|
||||||
-> DiagnosticBuilder<'tcx>
|
-> DiagnosticBuilder<'tcx>
|
||||||
{
|
{
|
||||||
let (expected, found) = match self.values_str(&trace.values) {
|
let expected_found = match values {
|
||||||
Some((expected, found)) => (expected, found),
|
None => None,
|
||||||
None => return self.tcx.sess.diagnostic().struct_dummy() /* derived error */
|
Some(values) => match self.values_str(&values) {
|
||||||
};
|
Some((expected, found)) => Some((expected, found)),
|
||||||
|
None => return self.tcx.sess.diagnostic().struct_dummy() /* derived error */
|
||||||
let span = trace.origin.span();
|
}
|
||||||
|
|
||||||
let is_simple_error = if let &TypeError::Sorts(ref values) = terr {
|
|
||||||
values.expected.is_primitive() && values.found.is_primitive()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let span = origin.span();
|
||||||
let mut err = self.tcx.sess.struct_span_err_with_code(
|
let mut err = self.tcx.sess.struct_span_err_with_code(
|
||||||
trace.origin.span(),
|
span, message, code);
|
||||||
message,
|
|
||||||
code);
|
|
||||||
|
|
||||||
if !is_simple_error || check_old_school() {
|
let mut is_simple_error = false;
|
||||||
err.note_expected_found(&"type", &expected, &found);
|
|
||||||
|
if let Some((expected, found)) = expected_found {
|
||||||
|
is_simple_error = if let &TypeError::Sorts(ref values) = terr {
|
||||||
|
values.expected.is_primitive() && values.found.is_primitive()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
if !is_simple_error || check_old_school() {
|
||||||
|
err.note_expected_found(&"type", &expected, &found);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err.span_label(span, &terr);
|
if !is_simple_error && check_old_school() {
|
||||||
|
err.span_note(span, &format!("{}", terr));
|
||||||
|
} else {
|
||||||
|
err.span_label(span, &terr);
|
||||||
|
}
|
||||||
|
|
||||||
self.note_error_origin(&mut err, &trace.origin);
|
self.note_error_origin(&mut err, &origin);
|
||||||
self.check_and_note_conflicting_crates(&mut err, terr, span);
|
self.check_and_note_conflicting_crates(&mut err, terr, span);
|
||||||
self.tcx.note_and_explain_type_err(&mut err, terr, span);
|
self.tcx.note_and_explain_type_err(&mut err, terr, span);
|
||||||
|
|
||||||
@ -566,7 +575,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
{
|
{
|
||||||
// FIXME: do we want to use a different error code for each origin?
|
// FIXME: do we want to use a different error code for each origin?
|
||||||
let failure_str = trace.origin.as_failure_str();
|
let failure_str = trace.origin.as_failure_str();
|
||||||
type_err!(self, trace, terr, E0308, "{}", failure_str)
|
type_err!(self, trace.origin, Some(trace.values), terr, E0308, "{}", failure_str)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a string of the form "expected `{}`, found `{}`".
|
/// Returns a string of the form "expected `{}`, found `{}`".
|
||||||
|
@ -62,11 +62,12 @@ macro_rules! span_bug {
|
|||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! type_err {
|
macro_rules! type_err {
|
||||||
($infcx:expr, $trace: expr, $terr: expr, $code:ident, $($message:tt)*) => ({
|
($infcx:expr, $origin: expr, $values: expr, $terr: expr, $code:ident, $($message:tt)*) => ({
|
||||||
__diagnostic_used!($code);
|
__diagnostic_used!($code);
|
||||||
$infcx.report_and_explain_type_error_with_code(
|
$infcx.report_and_explain_type_error_with_code(
|
||||||
$trace,
|
$origin,
|
||||||
$terr,
|
$values,
|
||||||
|
&$terr,
|
||||||
&format!($($message)*),
|
&format!($($message)*),
|
||||||
stringify!($code))
|
stringify!($code))
|
||||||
})
|
})
|
||||||
|
@ -26,7 +26,7 @@ use super::{
|
|||||||
|
|
||||||
use fmt_macros::{Parser, Piece, Position};
|
use fmt_macros::{Parser, Piece, Position};
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use infer::{InferCtxt};
|
use infer::{InferCtxt, TypeOrigin};
|
||||||
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||||
use ty::fast_reject;
|
use ty::fast_reject;
|
||||||
use ty::fold::TypeFolder;
|
use ty::fold::TypeFolder;
|
||||||
@ -117,10 +117,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||||||
predicate,
|
predicate,
|
||||||
error.err));
|
error.err));
|
||||||
} else {
|
} else {
|
||||||
let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271,
|
let mut err = type_err!(
|
||||||
"type mismatch resolving `{}`: {}",
|
self,
|
||||||
predicate,
|
TypeOrigin::Misc(obligation.cause.span),
|
||||||
error.err);
|
None, // FIXME: be smarter
|
||||||
|
error.err,
|
||||||
|
E0271,
|
||||||
|
"type mismatch resolving `{}`",
|
||||||
|
predicate);
|
||||||
self.note_obligation_cause(&mut err, obligation);
|
self.note_obligation_cause(&mut err, obligation);
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ use middle::free_region::FreeRegionMap;
|
|||||||
use rustc::infer::{self, InferOk, TypeOrigin};
|
use rustc::infer::{self, InferOk, TypeOrigin};
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::traits::{self, ProjectionMode};
|
use rustc::traits::{self, ProjectionMode};
|
||||||
|
use rustc::ty::error::ExpectedFound;
|
||||||
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
|
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
|
||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
@ -324,8 +325,11 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||||||
debug!("sub_types failed: impl ty {:?}, trait ty {:?}",
|
debug!("sub_types failed: impl ty {:?}, trait ty {:?}",
|
||||||
impl_fty,
|
impl_fty,
|
||||||
trait_fty);
|
trait_fty);
|
||||||
let trace = infer::TypeTrace::types(origin, false, impl_fty, trait_fty);
|
let values = Some(infer::ValuePairs::Types(ExpectedFound {
|
||||||
type_err!(infcx, trace, &terr, E0053,
|
expected: trait_fty,
|
||||||
|
found: impl_fty
|
||||||
|
}));
|
||||||
|
type_err!(infcx, origin, values, terr, E0053,
|
||||||
"method `{}` has an incompatible type for trait",
|
"method `{}` has an incompatible type for trait",
|
||||||
trait_m.name).emit();
|
trait_m.name).emit();
|
||||||
return
|
return
|
||||||
|
@ -47,10 +47,8 @@ pub fn main() {
|
|||||||
let a = 42;
|
let a = 42;
|
||||||
foo1(a);
|
foo1(a);
|
||||||
//~^ ERROR type mismatch resolving
|
//~^ ERROR type mismatch resolving
|
||||||
//~| expected usize
|
//~| expected usize, found struct `Bar`
|
||||||
//~| found struct `Bar`
|
|
||||||
baz(&a);
|
baz(&a);
|
||||||
//~^ ERROR type mismatch resolving
|
//~^ ERROR type mismatch resolving
|
||||||
//~| expected usize
|
//~| expected usize, found struct `Bar`
|
||||||
//~| found struct `Bar`
|
|
||||||
}
|
}
|
||||||
|
26
src/test/compile-fail/issue-31173.rs
Normal file
26
src/test/compile-fail/issue-31173.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
use std::vec::IntoIter;
|
||||||
|
|
||||||
|
pub fn get_tok(it: &mut IntoIter<u8>) {
|
||||||
|
let mut found_e = false;
|
||||||
|
|
||||||
|
let temp: Vec<u8> = it.take_while(|&x| {
|
||||||
|
found_e = true;
|
||||||
|
false
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
//~^ ERROR type mismatch resolving
|
||||||
|
//~| expected u8, found &-ptr
|
||||||
|
.collect(); //~ ERROR no method named `collect`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user