Uplift TypeError
This commit is contained in:
parent
c74efbca71
commit
82ef3ad980
16 changed files with 217 additions and 194 deletions
|
@ -7,7 +7,6 @@
|
|||
|
||||
use crate::error::DropCheckOverflow;
|
||||
use crate::infer::canonical::{Canonical, QueryResponse};
|
||||
use crate::ty::error::TypeError;
|
||||
use crate::ty::GenericArg;
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
|
||||
|
@ -91,12 +90,6 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
|
|||
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
|
||||
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
|
||||
|
||||
impl<'tcx> From<TypeError<'tcx>> for NoSolution {
|
||||
fn from(_: TypeError<'tcx>) -> NoSolution {
|
||||
NoSolution
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct DropckOutlivesResult<'tcx> {
|
||||
pub kinds: Vec<GenericArg<'tcx>>,
|
||||
|
|
|
@ -1,89 +1,26 @@
|
|||
use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, PrettyPrinter};
|
||||
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
|
||||
use rustc_errors::pluralize;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorOf, DefKind};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_macros::extension;
|
||||
pub use rustc_type_ir::error::ExpectedFound;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::hash::{DefaultHasher, Hash, Hasher};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
|
||||
pub struct ExpectedFound<T> {
|
||||
pub expected: T,
|
||||
pub found: T,
|
||||
}
|
||||
pub type TypeError<'tcx> = rustc_type_ir::error::TypeError<TyCtxt<'tcx>>;
|
||||
|
||||
impl<T> ExpectedFound<T> {
|
||||
pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
|
||||
if a_is_expected {
|
||||
ExpectedFound { expected: a, found: b }
|
||||
} else {
|
||||
ExpectedFound { expected: b, found: a }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Data structures used in type unification
|
||||
#[derive(Copy, Clone, Debug, TypeVisitable, PartialEq, Eq)]
|
||||
#[rustc_pass_by_value]
|
||||
pub enum TypeError<'tcx> {
|
||||
Mismatch,
|
||||
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
|
||||
PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
|
||||
SafetyMismatch(ExpectedFound<hir::Safety>),
|
||||
AbiMismatch(ExpectedFound<abi::Abi>),
|
||||
Mutability,
|
||||
ArgumentMutability(usize),
|
||||
TupleSize(ExpectedFound<usize>),
|
||||
FixedArraySize(ExpectedFound<u64>),
|
||||
ArgCount,
|
||||
FieldMisMatch(Symbol, Symbol),
|
||||
|
||||
RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
|
||||
RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>),
|
||||
RegionsPlaceholderMismatch,
|
||||
|
||||
Sorts(ExpectedFound<Ty<'tcx>>),
|
||||
ArgumentSorts(ExpectedFound<Ty<'tcx>>, usize),
|
||||
Traits(ExpectedFound<DefId>),
|
||||
VariadicMismatch(ExpectedFound<bool>),
|
||||
|
||||
/// Instantiating a type variable with the given type would have
|
||||
/// created a cycle (because it appears somewhere within that
|
||||
/// type).
|
||||
CyclicTy(Ty<'tcx>),
|
||||
CyclicConst(ty::Const<'tcx>),
|
||||
ProjectionMismatched(ExpectedFound<DefId>),
|
||||
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>>),
|
||||
ConstMismatch(ExpectedFound<ty::Const<'tcx>>),
|
||||
|
||||
IntrinsicCast,
|
||||
/// Safe `#[target_feature]` functions are not assignable to safe function pointers.
|
||||
TargetFeatureCast(DefId),
|
||||
}
|
||||
|
||||
impl TypeError<'_> {
|
||||
pub fn involves_regions(self) -> bool {
|
||||
match self {
|
||||
TypeError::RegionsDoesNotOutlive(_, _)
|
||||
| TypeError::RegionsInsufficientlyPolymorphic(_, _)
|
||||
| TypeError::RegionsPlaceholderMismatch => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Explains the source of a type err in a short, human readable way. This is meant to be placed
|
||||
/// 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.
|
||||
/// Explains the source of a type err in a short, human readable way.
|
||||
/// This is meant to be placed 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.
|
||||
#[extension(pub trait TypeErrorToStringExt<'tcx>)]
|
||||
impl<'tcx> TypeError<'tcx> {
|
||||
pub fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
|
||||
use self::TypeError::*;
|
||||
fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
|
||||
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).
|
||||
|
@ -95,24 +32,26 @@ impl<'tcx> TypeError<'tcx> {
|
|||
}
|
||||
|
||||
match self {
|
||||
CyclicTy(_) => "cyclic type of infinite size".into(),
|
||||
CyclicConst(_) => "encountered a self-referencing constant".into(),
|
||||
Mismatch => "types differ".into(),
|
||||
ConstnessMismatch(values) => {
|
||||
TypeError::CyclicTy(_) => "cyclic type of infinite size".into(),
|
||||
TypeError::CyclicConst(_) => "encountered a self-referencing constant".into(),
|
||||
TypeError::Mismatch => "types differ".into(),
|
||||
TypeError::ConstnessMismatch(values) => {
|
||||
format!("expected {} bound, found {} bound", values.expected, values.found).into()
|
||||
}
|
||||
PolarityMismatch(values) => {
|
||||
TypeError::PolarityMismatch(values) => {
|
||||
format!("expected {} polarity, found {} polarity", values.expected, values.found)
|
||||
.into()
|
||||
}
|
||||
SafetyMismatch(values) => {
|
||||
TypeError::SafetyMismatch(values) => {
|
||||
format!("expected {} fn, found {} fn", values.expected, values.found).into()
|
||||
}
|
||||
AbiMismatch(values) => {
|
||||
TypeError::AbiMismatch(values) => {
|
||||
format!("expected {} fn, found {} fn", values.expected, values.found).into()
|
||||
}
|
||||
ArgumentMutability(_) | Mutability => "types differ in mutability".into(),
|
||||
TupleSize(values) => format!(
|
||||
TypeError::ArgumentMutability(_) | TypeError::Mutability => {
|
||||
"types differ in mutability".into()
|
||||
}
|
||||
TypeError::TupleSize(values) => format!(
|
||||
"expected a tuple with {} element{}, found one with {} element{}",
|
||||
values.expected,
|
||||
pluralize!(values.expected),
|
||||
|
@ -120,7 +59,7 @@ impl<'tcx> TypeError<'tcx> {
|
|||
pluralize!(values.found)
|
||||
)
|
||||
.into(),
|
||||
FixedArraySize(values) => format!(
|
||||
TypeError::FixedArraySize(values) => format!(
|
||||
"expected an array with a fixed size of {} element{}, found one with {} element{}",
|
||||
values.expected,
|
||||
pluralize!(values.expected),
|
||||
|
@ -128,20 +67,21 @@ impl<'tcx> TypeError<'tcx> {
|
|||
pluralize!(values.found)
|
||||
)
|
||||
.into(),
|
||||
ArgCount => "incorrect number of function parameters".into(),
|
||||
FieldMisMatch(adt, field) => format!("field type mismatch: {adt}.{field}").into(),
|
||||
RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
|
||||
TypeError::ArgCount => "incorrect number of function parameters".into(),
|
||||
TypeError::RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
|
||||
// Actually naming the region here is a bit confusing because context is lacking
|
||||
RegionsInsufficientlyPolymorphic(..) => {
|
||||
TypeError::RegionsInsufficientlyPolymorphic(..) => {
|
||||
"one type is more general than the other".into()
|
||||
}
|
||||
RegionsPlaceholderMismatch => "one type is more general than the other".into(),
|
||||
ArgumentSorts(values, _) | Sorts(values) => {
|
||||
TypeError::RegionsPlaceholderMismatch => {
|
||||
"one type is more general than the other".into()
|
||||
}
|
||||
TypeError::ArgumentSorts(values, _) | TypeError::Sorts(values) => {
|
||||
let expected = values.expected.sort_string(tcx);
|
||||
let found = values.found.sort_string(tcx);
|
||||
report_maybe_different(&expected, &found).into()
|
||||
}
|
||||
Traits(values) => {
|
||||
TypeError::Traits(values) => {
|
||||
let (mut expected, mut found) = with_forced_trimmed_paths!((
|
||||
tcx.def_path_str(values.expected),
|
||||
tcx.def_path_str(values.found),
|
||||
|
@ -153,59 +93,34 @@ impl<'tcx> TypeError<'tcx> {
|
|||
report_maybe_different(&format!("trait `{expected}`"), &format!("trait `{found}`"))
|
||||
.into()
|
||||
}
|
||||
VariadicMismatch(ref values) => format!(
|
||||
TypeError::VariadicMismatch(ref values) => format!(
|
||||
"expected {} fn, found {} function",
|
||||
if values.expected { "variadic" } else { "non-variadic" },
|
||||
if values.found { "variadic" } else { "non-variadic" }
|
||||
)
|
||||
.into(),
|
||||
ProjectionMismatched(ref values) => format!(
|
||||
TypeError::ProjectionMismatched(ref values) => format!(
|
||||
"expected `{}`, found `{}`",
|
||||
tcx.def_path_str(values.expected),
|
||||
tcx.def_path_str(values.found)
|
||||
)
|
||||
.into(),
|
||||
ExistentialMismatch(ref values) => report_maybe_different(
|
||||
TypeError::ExistentialMismatch(ref values) => report_maybe_different(
|
||||
&format!("trait `{}`", values.expected),
|
||||
&format!("trait `{}`", values.found),
|
||||
)
|
||||
.into(),
|
||||
ConstMismatch(ref values) => {
|
||||
TypeError::ConstMismatch(ref values) => {
|
||||
format!("expected `{}`, found `{}`", values.expected, values.found).into()
|
||||
}
|
||||
IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
|
||||
TargetFeatureCast(_) => {
|
||||
TypeError::IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
|
||||
TypeError::TargetFeatureCast(_) => {
|
||||
"cannot coerce functions with `#[target_feature]` to safe function pointers".into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeError<'tcx> {
|
||||
pub fn must_include_note(self) -> bool {
|
||||
use self::TypeError::*;
|
||||
match self {
|
||||
CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | ConstnessMismatch(_)
|
||||
| PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_)
|
||||
| ArgumentSorts(..) | Sorts(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false,
|
||||
|
||||
Mutability
|
||||
| ArgumentMutability(_)
|
||||
| TupleSize(_)
|
||||
| ArgCount
|
||||
| FieldMisMatch(..)
|
||||
| RegionsDoesNotOutlive(..)
|
||||
| RegionsInsufficientlyPolymorphic(..)
|
||||
| RegionsPlaceholderMismatch
|
||||
| Traits(_)
|
||||
| ProjectionMismatched(_)
|
||||
| ExistentialMismatch(_)
|
||||
| ConstMismatch(_)
|
||||
| IntrinsicCast => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Ty<'tcx> {
|
||||
pub fn sort_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
|
||||
match *self.kind() {
|
||||
|
|
|
@ -313,38 +313,6 @@ impl Visibility {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
|
||||
pub enum BoundConstness {
|
||||
/// `Type: Trait`
|
||||
NotConst,
|
||||
/// `Type: const Trait`
|
||||
Const,
|
||||
/// `Type: ~const Trait`
|
||||
///
|
||||
/// Requires resolving to const only when we are in a const context.
|
||||
ConstIfConst,
|
||||
}
|
||||
|
||||
impl BoundConstness {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::NotConst => "",
|
||||
Self::Const => "const",
|
||||
Self::ConstIfConst => "~const",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BoundConstness {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::NotConst => f.write_str("normal"),
|
||||
Self::Const => f.write_str("const"),
|
||||
Self::ConstIfConst => f.write_str("~const"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct ClosureSizeProfileData<'tcx> {
|
||||
|
|
|
@ -296,7 +296,6 @@ TrivialTypeTraversalImpls! {
|
|||
::rustc_target::abi::FieldIdx,
|
||||
::rustc_target::abi::VariantIdx,
|
||||
crate::middle::region::Scope,
|
||||
crate::ty::FloatTy,
|
||||
::rustc_ast::InlineAsmOptions,
|
||||
::rustc_ast::InlineAsmTemplatePiece,
|
||||
::rustc_ast::NodeId,
|
||||
|
@ -316,7 +315,7 @@ TrivialTypeTraversalImpls! {
|
|||
crate::traits::Reveal,
|
||||
crate::ty::adjustment::AutoBorrowMutability,
|
||||
crate::ty::AdtKind,
|
||||
crate::ty::BoundConstness,
|
||||
crate::ty::BoundRegion,
|
||||
// Including `BoundRegionKind` is a *bit* dubious, but direct
|
||||
// references to bound region appear in `ty::Error`, and aren't
|
||||
// really meant to be folded. In general, we can only fold a fully
|
||||
|
@ -324,16 +323,11 @@ TrivialTypeTraversalImpls! {
|
|||
crate::ty::BoundRegionKind,
|
||||
crate::ty::AssocItem,
|
||||
crate::ty::AssocKind,
|
||||
crate::ty::AliasTyKind,
|
||||
crate::ty::Placeholder<crate::ty::BoundRegion>,
|
||||
crate::ty::Placeholder<crate::ty::BoundTy>,
|
||||
crate::ty::Placeholder<ty::BoundVar>,
|
||||
crate::ty::LateParamRegion,
|
||||
crate::ty::InferTy,
|
||||
crate::ty::IntVarValue,
|
||||
crate::ty::adjustment::PointerCoercion,
|
||||
crate::ty::RegionVid,
|
||||
crate::ty::Variance,
|
||||
::rustc_span::Span,
|
||||
::rustc_span::symbol::Ident,
|
||||
::rustc_errors::ErrorGuaranteed,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue