mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-12 20:16:49 +00:00
try to recover the non-matching types in projection errors
The type equation in projection takes place under a binder and a snapshot, which we can't easily take types out of. Instead, when encountering a projection error, try to re-do the projection and find the type error then. This fails to produce a sane type error when the failure was a "leak_check" failure. I can't think of a sane way to show *these*, so I just left them use the old crappy representation, and added a test to make sure we don't break them.
This commit is contained in:
parent
712c5cadbb
commit
f3ee99bd4d
@ -26,8 +26,9 @@ use super::{
|
||||
|
||||
use fmt_macros::{Parser, Piece, Position};
|
||||
use hir::def_id::DefId;
|
||||
use infer::{InferCtxt, TypeOrigin};
|
||||
use infer::{self, InferCtxt, TypeOrigin};
|
||||
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||
use ty::error::ExpectedFound;
|
||||
use ty::fast_reject;
|
||||
use ty::fold::TypeFolder;
|
||||
use ty::subst::{self, Subst, TypeSpace};
|
||||
@ -107,28 +108,66 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
let predicate =
|
||||
self.resolve_type_vars_if_possible(&obligation.predicate);
|
||||
|
||||
if !predicate.references_error() {
|
||||
if let Some(warning_node_id) = warning_node_id {
|
||||
self.tcx.sess.add_lint(
|
||||
::lint::builtin::UNSIZED_IN_TUPLE,
|
||||
warning_node_id,
|
||||
obligation.cause.span,
|
||||
format!("type mismatch resolving `{}`: {}",
|
||||
predicate,
|
||||
error.err));
|
||||
} else {
|
||||
let mut err = type_err!(
|
||||
self,
|
||||
TypeOrigin::Misc(obligation.cause.span),
|
||||
None, // FIXME: be smarter
|
||||
error.err,
|
||||
E0271,
|
||||
"type mismatch resolving `{}`",
|
||||
predicate);
|
||||
self.note_obligation_cause(&mut err, obligation);
|
||||
err.emit();
|
||||
}
|
||||
if predicate.references_error() {
|
||||
return
|
||||
}
|
||||
if let Some(warning_node_id) = warning_node_id {
|
||||
self.tcx.sess.add_lint(
|
||||
::lint::builtin::UNSIZED_IN_TUPLE,
|
||||
warning_node_id,
|
||||
obligation.cause.span,
|
||||
format!("type mismatch resolving `{}`: {}",
|
||||
predicate,
|
||||
error.err));
|
||||
return
|
||||
}
|
||||
self.probe(|_| {
|
||||
let origin = TypeOrigin::Misc(obligation.cause.span);
|
||||
let err_buf;
|
||||
let mut err = &error.err;
|
||||
let mut values = None;
|
||||
|
||||
// try to find the mismatched types to report the error with.
|
||||
//
|
||||
// this can fail if the problem was higher-ranked, in which
|
||||
// cause I have no idea for a good error message.
|
||||
if let ty::Predicate::Projection(ref data) = predicate {
|
||||
let mut selcx = SelectionContext::new(self);
|
||||
let (data, _) = self.replace_late_bound_regions_with_fresh_var(
|
||||
obligation.cause.span,
|
||||
infer::LateBoundRegionConversionTime::HigherRankedType,
|
||||
data);
|
||||
let normalized = super::normalize_projection_type(
|
||||
&mut selcx,
|
||||
data.projection_ty,
|
||||
obligation.cause.clone(),
|
||||
0
|
||||
);
|
||||
let origin = TypeOrigin::Misc(obligation.cause.span);
|
||||
if let Err(error) = self.eq_types(
|
||||
false, origin,
|
||||
data.ty, normalized.value
|
||||
) {
|
||||
values = Some(infer::ValuePairs::Types(ExpectedFound {
|
||||
expected: normalized.value,
|
||||
found: data.ty,
|
||||
}));
|
||||
err_buf = error;
|
||||
err = &err_buf;
|
||||
}
|
||||
}
|
||||
|
||||
let mut diag = type_err!(
|
||||
self,
|
||||
origin,
|
||||
values,
|
||||
err,
|
||||
E0271,
|
||||
"type mismatch resolving `{}`",
|
||||
predicate);
|
||||
self.note_obligation_cause(&mut diag, obligation);
|
||||
diag.emit();
|
||||
});
|
||||
}
|
||||
|
||||
fn impl_substs(&self,
|
||||
|
@ -0,0 +1,38 @@
|
||||
// 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.
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
// revisions: good bad
|
||||
|
||||
trait Mirror {
|
||||
type Image;
|
||||
}
|
||||
|
||||
impl<T> Mirror for T {
|
||||
type Image = T;
|
||||
}
|
||||
|
||||
#[cfg(bad)]
|
||||
fn foo<U, T>(_t: T)
|
||||
where for<'a> &'a T: Mirror<Image=U>
|
||||
{}
|
||||
|
||||
#[cfg(good)]
|
||||
fn foo<U, T>(_t: T)
|
||||
where for<'a> &'a T: Mirror<Image=&'a U>
|
||||
{}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { //[good]~ ERROR compilation successful
|
||||
foo(());
|
||||
//[bad]~^ ERROR type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _`
|
||||
//[bad]~| expected bound lifetime parameter 'a, found concrete lifetime
|
||||
}
|
@ -19,7 +19,8 @@ pub fn get_tok(it: &mut IntoIter<u8>) {
|
||||
})
|
||||
.cloned()
|
||||
//~^ ERROR type mismatch resolving
|
||||
//~| expected u8, found &-ptr
|
||||
//~| expected type `u8`
|
||||
//~| found type `&_`
|
||||
.collect(); //~ ERROR no method named `collect`
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user