Modify primary span label for E0308
The previous output was unintuitive to users.
This commit is contained in:
parent
006ca9b14d
commit
62ba3e70a1
383 changed files with 889 additions and 926 deletions
|
@ -8,9 +8,7 @@ use rustc_span::symbol::Symbol;
|
|||
use rustc_target::spec::abi;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable, Lift)]
|
||||
|
@ -87,20 +85,16 @@ impl TypeError<'_> {
|
|||
/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
|
||||
/// afterwards to present additional details, particularly when it comes to lifetime-related
|
||||
/// errors.
|
||||
impl<'tcx> fmt::Display for TypeError<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl<'tcx> TypeError<'tcx> {
|
||||
pub fn to_string(self, tcx: TyCtxt<'tcx>) -> String {
|
||||
use self::TypeError::*;
|
||||
fn report_maybe_different(
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
expected: &str,
|
||||
found: &str,
|
||||
) -> fmt::Result {
|
||||
fn report_maybe_different(expected: &str, found: &str) -> String {
|
||||
// A naive approach to making sure that we're not reporting silly errors such as:
|
||||
// (expected closure, found closure).
|
||||
if expected == found {
|
||||
write!(f, "expected {}, found a different {}", expected, found)
|
||||
format!("expected {}, found a different {}", expected, found)
|
||||
} else {
|
||||
write!(f, "expected {}, found {}", expected, found)
|
||||
format!("expected {}, found {}", expected, found)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,64 +103,59 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
|||
_ => String::new(),
|
||||
};
|
||||
|
||||
match *self {
|
||||
CyclicTy(_) => write!(f, "cyclic type of infinite size"),
|
||||
CyclicConst(_) => write!(f, "encountered a self-referencing constant"),
|
||||
Mismatch => write!(f, "types differ"),
|
||||
match self {
|
||||
CyclicTy(_) => format!("cyclic type of infinite size"),
|
||||
CyclicConst(_) => format!("encountered a self-referencing constant"),
|
||||
Mismatch => format!("types differ"),
|
||||
ConstnessMismatch(values) => {
|
||||
write!(f, "expected {} bound, found {} bound", values.expected, values.found)
|
||||
format!("expected {} bound, found {} bound", values.expected, values.found)
|
||||
}
|
||||
PolarityMismatch(values) => {
|
||||
write!(f, "expected {} polarity, found {} polarity", values.expected, values.found)
|
||||
format!("expected {} polarity, found {} polarity", values.expected, values.found)
|
||||
}
|
||||
UnsafetyMismatch(values) => {
|
||||
write!(f, "expected {} fn, found {} fn", values.expected, values.found)
|
||||
format!("expected {} fn, found {} fn", values.expected, values.found)
|
||||
}
|
||||
AbiMismatch(values) => {
|
||||
write!(f, "expected {} fn, found {} fn", values.expected, values.found)
|
||||
format!("expected {} fn, found {} fn", values.expected, values.found)
|
||||
}
|
||||
ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"),
|
||||
TupleSize(values) => write!(
|
||||
f,
|
||||
ArgumentMutability(_) | Mutability => format!("types differ in mutability"),
|
||||
TupleSize(values) => format!(
|
||||
"expected a tuple with {} element{}, found one with {} element{}",
|
||||
values.expected,
|
||||
pluralize!(values.expected),
|
||||
values.found,
|
||||
pluralize!(values.found)
|
||||
),
|
||||
FixedArraySize(values) => write!(
|
||||
f,
|
||||
FixedArraySize(values) => format!(
|
||||
"expected an array with a fixed size of {} element{}, found one with {} element{}",
|
||||
values.expected,
|
||||
pluralize!(values.expected),
|
||||
values.found,
|
||||
pluralize!(values.found)
|
||||
),
|
||||
ArgCount => write!(f, "incorrect number of function parameters"),
|
||||
FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field),
|
||||
RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
|
||||
ArgCount => format!("incorrect number of function parameters"),
|
||||
FieldMisMatch(adt, field) => format!("field type mismatch: {}.{}", adt, field),
|
||||
RegionsDoesNotOutlive(..) => format!("lifetime mismatch"),
|
||||
// Actually naming the region here is a bit confusing because context is lacking
|
||||
RegionsInsufficientlyPolymorphic(..) => {
|
||||
write!(f, "one type is more general than the other")
|
||||
format!("one type is more general than the other")
|
||||
}
|
||||
RegionsOverlyPolymorphic(br, _) => write!(
|
||||
f,
|
||||
RegionsOverlyPolymorphic(br, _) => format!(
|
||||
"expected concrete lifetime, found bound lifetime parameter{}",
|
||||
br_string(br)
|
||||
),
|
||||
RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
|
||||
ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| {
|
||||
let (mut expected, mut found) = with_forced_trimmed_paths!((
|
||||
values.expected.sort_string(tcx),
|
||||
values.found.sort_string(tcx),
|
||||
));
|
||||
RegionsPlaceholderMismatch => format!("one type is more general than the other"),
|
||||
ArgumentSorts(values, _) | Sorts(values) => {
|
||||
let mut expected = values.expected.sort_string(tcx);
|
||||
let mut found = values.found.sort_string(tcx);
|
||||
if expected == found {
|
||||
expected = values.expected.sort_string(tcx);
|
||||
found = values.found.sort_string(tcx);
|
||||
}
|
||||
report_maybe_different(f, &expected, &found)
|
||||
}),
|
||||
Traits(values) => ty::tls::with(|tcx| {
|
||||
report_maybe_different(&expected, &found)
|
||||
}
|
||||
Traits(values) => {
|
||||
let (mut expected, mut found) = with_forced_trimmed_paths!((
|
||||
tcx.def_path_str(values.expected),
|
||||
tcx.def_path_str(values.found),
|
||||
|
@ -175,12 +164,8 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
|||
expected = tcx.def_path_str(values.expected);
|
||||
found = tcx.def_path_str(values.found);
|
||||
}
|
||||
report_maybe_different(
|
||||
f,
|
||||
&format!("trait `{expected}`"),
|
||||
&format!("trait `{found}`"),
|
||||
)
|
||||
}),
|
||||
report_maybe_different(&format!("trait `{expected}`"), &format!("trait `{found}`"))
|
||||
}
|
||||
IntMismatch(ref values) => {
|
||||
let expected = match values.expected {
|
||||
ty::IntVarValue::IntType(ty) => ty.name_str(),
|
||||
|
@ -190,41 +175,34 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
|||
ty::IntVarValue::IntType(ty) => ty.name_str(),
|
||||
ty::IntVarValue::UintType(ty) => ty.name_str(),
|
||||
};
|
||||
write!(f, "expected `{}`, found `{}`", expected, found)
|
||||
format!("expected `{}`, found `{}`", expected, found)
|
||||
}
|
||||
FloatMismatch(ref values) => {
|
||||
write!(
|
||||
f,
|
||||
format!(
|
||||
"expected `{}`, found `{}`",
|
||||
values.expected.name_str(),
|
||||
values.found.name_str()
|
||||
)
|
||||
}
|
||||
VariadicMismatch(ref values) => write!(
|
||||
f,
|
||||
VariadicMismatch(ref values) => format!(
|
||||
"expected {} fn, found {} function",
|
||||
if values.expected { "variadic" } else { "non-variadic" },
|
||||
if values.found { "variadic" } else { "non-variadic" }
|
||||
),
|
||||
ProjectionMismatched(ref values) => ty::tls::with(|tcx| {
|
||||
write!(
|
||||
f,
|
||||
"expected {}, found {}",
|
||||
tcx.def_path_str(values.expected),
|
||||
tcx.def_path_str(values.found)
|
||||
)
|
||||
}),
|
||||
ProjectionMismatched(ref values) => format!(
|
||||
"expected {}, found {}",
|
||||
tcx.def_path_str(values.expected),
|
||||
tcx.def_path_str(values.found)
|
||||
),
|
||||
ExistentialMismatch(ref values) => report_maybe_different(
|
||||
f,
|
||||
&format!("trait `{}`", values.expected),
|
||||
&format!("trait `{}`", values.found),
|
||||
),
|
||||
ConstMismatch(ref values) => {
|
||||
write!(f, "expected `{}`, found `{}`", values.expected, values.found)
|
||||
format!("expected `{}`, found `{}`", values.expected, values.found)
|
||||
}
|
||||
IntrinsicCast => write!(f, "cannot coerce intrinsics to function pointers"),
|
||||
TargetFeatureCast(_) => write!(
|
||||
f,
|
||||
IntrinsicCast => format!("cannot coerce intrinsics to function pointers"),
|
||||
TargetFeatureCast(_) => format!(
|
||||
"cannot coerce functions with `#[target_feature]` to safe function pointers"
|
||||
),
|
||||
}
|
||||
|
@ -259,60 +237,9 @@ impl<'tcx> TypeError<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> Ty<'tcx> {
|
||||
pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
|
||||
pub fn sort_string(self, tcx: TyCtxt<'tcx>) -> String {
|
||||
match *self.kind() {
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
|
||||
format!("`{}`", self).into()
|
||||
}
|
||||
ty::Tuple(ref tys) if tys.is_empty() => format!("`{}`", self).into(),
|
||||
|
||||
ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did())).into(),
|
||||
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
|
||||
ty::Array(t, n) => {
|
||||
if t.is_simple_ty() {
|
||||
return format!("array `{}`", self).into();
|
||||
}
|
||||
|
||||
let n = tcx.lift(n).unwrap();
|
||||
if let ty::ConstKind::Value(v) = n.kind() {
|
||||
if let Some(n) = v.try_to_machine_usize(tcx) {
|
||||
return format!("array of {} element{}", n, pluralize!(n)).into();
|
||||
}
|
||||
}
|
||||
"array".into()
|
||||
}
|
||||
ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(),
|
||||
ty::Slice(_) => "slice".into(),
|
||||
ty::RawPtr(tymut) => {
|
||||
let tymut_string = match tymut.mutbl {
|
||||
hir::Mutability::Mut => tymut.to_string(),
|
||||
hir::Mutability::Not => format!("const {}", tymut.ty),
|
||||
};
|
||||
|
||||
if tymut_string != "_" && (tymut.ty.is_simple_text() || tymut_string.len() < "const raw pointer".len()) {
|
||||
format!("`*{}`", tymut_string).into()
|
||||
} else {
|
||||
// Unknown type name, it's long or has type arguments
|
||||
"raw pointer".into()
|
||||
}
|
||||
},
|
||||
ty::Ref(_, ty, mutbl) => {
|
||||
let tymut = ty::TypeAndMut { ty, mutbl };
|
||||
let tymut_string = tymut.to_string();
|
||||
|
||||
if tymut_string != "_"
|
||||
&& (ty.is_simple_text() || tymut_string.len() < "mutable reference".len())
|
||||
{
|
||||
format!("`&{}`", tymut_string).into()
|
||||
} else {
|
||||
// Unknown type name, it's long or has type arguments
|
||||
match mutbl {
|
||||
hir::Mutability::Mut => "mutable reference",
|
||||
_ => "reference",
|
||||
}
|
||||
.into()
|
||||
}
|
||||
}
|
||||
ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
|
||||
DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
|
||||
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
|
||||
|
@ -320,14 +247,13 @@ impl<'tcx> Ty<'tcx> {
|
|||
},
|
||||
ty::FnPtr(_) => "fn pointer".into(),
|
||||
ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
|
||||
format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
|
||||
format!("`dyn {}`", tcx.def_path_str(principal.def_id()))
|
||||
}
|
||||
ty::Dynamic(..) => "trait object".into(),
|
||||
ty::Closure(..) => "closure".into(),
|
||||
ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
|
||||
ty::GeneratorWitness(..) |
|
||||
ty::GeneratorWitnessMIR(..) => "generator witness".into(),
|
||||
ty::Tuple(..) => "tuple".into(),
|
||||
ty::Infer(ty::TyVar(_)) => "inferred type".into(),
|
||||
ty::Infer(ty::IntVar(_)) => "integer".into(),
|
||||
ty::Infer(ty::FloatVar(_)) => "floating-point number".into(),
|
||||
|
@ -337,9 +263,14 @@ impl<'tcx> Ty<'tcx> {
|
|||
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
|
||||
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
|
||||
ty::Alias(ty::Projection, _) => "associated type".into(),
|
||||
ty::Param(p) => format!("type parameter `{}`", p).into(),
|
||||
ty::Param(p) => format!("type parameter `{p}`").into(),
|
||||
ty::Alias(ty::Opaque, ..) => "opaque type".into(),
|
||||
ty::Error(_) => "type error".into(),
|
||||
_ => {
|
||||
let width = tcx.sess.diagnostic_width();
|
||||
let length_limit = std::cmp::max(width / 4, 15);
|
||||
format!("`{}`", tcx.ty_string_with_limit(self, length_limit))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,16 +317,14 @@ impl<'tcx> Ty<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
|
||||
let width = self.sess.diagnostic_width();
|
||||
let length_limit = width.saturating_sub(30);
|
||||
pub fn ty_string_with_limit(self, ty: Ty<'tcx>, length_limit: usize) -> String {
|
||||
let mut type_limit = 50;
|
||||
let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
|
||||
.pretty_print_type(ty)
|
||||
.expect("could not write to `String`")
|
||||
.into_buffer();
|
||||
if regular.len() <= width {
|
||||
return (regular, None);
|
||||
if regular.len() <= length_limit {
|
||||
return regular;
|
||||
}
|
||||
let mut short;
|
||||
loop {
|
||||
|
@ -415,6 +344,20 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
type_limit -= 1;
|
||||
}
|
||||
short
|
||||
}
|
||||
|
||||
pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
|
||||
let width = self.sess.diagnostic_width();
|
||||
let length_limit = width.saturating_sub(30);
|
||||
let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
|
||||
.pretty_print_type(ty)
|
||||
.expect("could not write to `String`")
|
||||
.into_buffer();
|
||||
if regular.len() <= width {
|
||||
return (regular, None);
|
||||
}
|
||||
let short = self.ty_string_with_limit(ty, length_limit);
|
||||
if regular == short {
|
||||
return (regular, None);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue