Uplift TypeError
This commit is contained in:
parent
c74efbca71
commit
82ef3ad980
@ -15,6 +15,7 @@
|
||||
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
|
||||
use rustc_middle::middle::stability::EvalResult;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
||||
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
|
||||
|
@ -40,7 +40,7 @@
|
||||
use rustc_infer::traits::query::NoSolution;
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError::Sorts};
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
@ -682,7 +682,8 @@ fn check_expr_break(
|
||||
self.suggest_mismatched_types_on_tail(
|
||||
&mut err, expr, ty, e_ty, target_id,
|
||||
);
|
||||
let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
|
||||
let error =
|
||||
Some(TypeError::Sorts(ExpectedFound { expected: ty, found: e_ty }));
|
||||
self.annotate_loop_expected_due_to_inference(err, expr, error);
|
||||
if let Some(val) =
|
||||
self.err_ctxt().ty_kind_suggestion(self.param_env, ty)
|
||||
|
@ -71,6 +71,7 @@
|
||||
use rustc_macros::extension;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::dep_graph::DepContext;
|
||||
use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||
use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError, PrintTraitRefExt as _};
|
||||
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::Upcast;
|
||||
|
@ -21,13 +21,12 @@ pub fn note_and_explain_type_err(
|
||||
sp: Span,
|
||||
body_owner_def_id: DefId,
|
||||
) {
|
||||
use ty::error::TypeError::*;
|
||||
debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
|
||||
|
||||
let tcx = self.tcx;
|
||||
|
||||
match err {
|
||||
ArgumentSorts(values, _) | Sorts(values) => {
|
||||
TypeError::ArgumentSorts(values, _) | TypeError::Sorts(values) => {
|
||||
match (*values.expected.kind(), *values.found.kind()) {
|
||||
(ty::Closure(..), ty::Closure(..)) => {
|
||||
diag.note("no two closures, even if identical, have the same type");
|
||||
@ -483,7 +482,7 @@ fn foo(&self, x: T) -> T { x }
|
||||
values.found.kind(),
|
||||
);
|
||||
}
|
||||
CyclicTy(ty) => {
|
||||
TypeError::CyclicTy(ty) => {
|
||||
// Watch out for various cases of cyclic types and try to explain.
|
||||
if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() {
|
||||
diag.note(
|
||||
@ -494,7 +493,7 @@ fn foo(&self, x: T) -> T { x }
|
||||
);
|
||||
}
|
||||
}
|
||||
TargetFeatureCast(def_id) => {
|
||||
TypeError::TargetFeatureCast(def_id) => {
|
||||
let target_spans = tcx.get_attrs(def_id, sym::target_feature).map(|attr| attr.span);
|
||||
diag.note(
|
||||
"functions with `#[target_feature]` can only be coerced to `unsafe` function pointers"
|
||||
|
@ -276,7 +276,7 @@ fn error(
|
||||
other_region: ty::Region<'tcx>,
|
||||
) -> TypeError<'tcx> {
|
||||
debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region);
|
||||
TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound.kind, other_region)
|
||||
TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound, other_region)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 fn new(value: T) -> Self {
|
||||
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 @@ fn report_maybe_different(expected: &str, found: &str) -> String {
|
||||
}
|
||||
|
||||
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 @@ fn report_maybe_different(expected: &str, found: &str) -> String {
|
||||
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 @@ fn report_maybe_different(expected: &str, found: &str) -> String {
|
||||
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 @@ fn report_maybe_different(expected: &str, found: &str) -> String {
|
||||
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 @@ pub fn to_string(self, def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 @@ fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
|
||||
::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 @@ fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
|
||||
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 @@ fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
|
||||
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,
|
||||
|
@ -28,7 +28,7 @@
|
||||
use rustc_macros::extension;
|
||||
use rustc_middle::hir::map;
|
||||
use rustc_middle::traits::IsConstable;
|
||||
use rustc_middle::ty::error::TypeError::{self, Sorts};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::print::PrintPolyTraitRefExt;
|
||||
use rustc_middle::ty::{
|
||||
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs,
|
||||
@ -3842,7 +3842,7 @@ fn note_function_argument_obligation<G: EmissionGuarantee>(
|
||||
&& let Some(failed_pred) = failed_pred.as_projection_clause()
|
||||
&& let Some(found) = failed_pred.skip_binder().term.as_type()
|
||||
{
|
||||
type_diffs = vec![Sorts(ty::error::ExpectedFound {
|
||||
type_diffs = vec![TypeError::Sorts(ty::error::ExpectedFound {
|
||||
expected: where_pred
|
||||
.skip_binder()
|
||||
.projection_term
|
||||
@ -3985,7 +3985,7 @@ fn look_for_iterator_item_mistakes<G: EmissionGuarantee>(
|
||||
continue;
|
||||
};
|
||||
for diff in type_diffs {
|
||||
let Sorts(expected_found) = diff else {
|
||||
let TypeError::Sorts(expected_found) = diff else {
|
||||
continue;
|
||||
};
|
||||
if tcx.is_diagnostic_item(sym::IteratorItem, *def_id)
|
||||
@ -4165,7 +4165,7 @@ fn point_at_chain<G: EmissionGuarantee>(
|
||||
};
|
||||
if primary_spans.is_empty()
|
||||
|| type_diffs.iter().any(|diff| {
|
||||
let Sorts(expected_found) = diff else {
|
||||
let TypeError::Sorts(expected_found) = diff else {
|
||||
return false;
|
||||
};
|
||||
self.can_eq(param_env, expected_found.found, ty)
|
||||
@ -4198,7 +4198,7 @@ fn point_at_chain<G: EmissionGuarantee>(
|
||||
let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
|
||||
if !self.can_eq(param_env, ty, *prev_ty) {
|
||||
if type_diffs.iter().any(|diff| {
|
||||
let Sorts(expected_found) = diff else {
|
||||
let TypeError::Sorts(expected_found) = diff else {
|
||||
return false;
|
||||
};
|
||||
self.can_eq(param_env, expected_found.found, ty)
|
||||
@ -4248,7 +4248,7 @@ fn probe_assoc_types_at_expr(
|
||||
let ocx = ObligationCtxt::new(self.infcx);
|
||||
let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
|
||||
for diff in type_diffs {
|
||||
let Sorts(expected_found) = diff else {
|
||||
let TypeError::Sorts(expected_found) = diff else {
|
||||
continue;
|
||||
};
|
||||
let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else {
|
||||
|
@ -42,6 +42,7 @@
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::_match::MatchAgainstFreshVars;
|
||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||
use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
||||
use rustc_middle::ty::relate::TypeRelation;
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
|
106
compiler/rustc_type_ir/src/error.rs
Normal file
106
compiler/rustc_type_ir/src/error.rs
Normal file
@ -0,0 +1,106 @@
|
||||
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
|
||||
use crate::solve::NoSolution;
|
||||
use crate::{self as ty, Interner};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[derive(TypeFoldable_Generic, TypeVisitable_Generic)]
|
||||
pub struct ExpectedFound<T> {
|
||||
pub expected: T,
|
||||
pub found: T,
|
||||
}
|
||||
|
||||
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(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = ""),
|
||||
Debug(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic)]
|
||||
#[rustc_pass_by_value]
|
||||
pub enum TypeError<I: Interner> {
|
||||
Mismatch,
|
||||
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
|
||||
PolarityMismatch(ExpectedFound<ty::PredicatePolarity>),
|
||||
SafetyMismatch(ExpectedFound<I::Safety>),
|
||||
AbiMismatch(ExpectedFound<I::Abi>),
|
||||
Mutability,
|
||||
ArgumentMutability(usize),
|
||||
TupleSize(ExpectedFound<usize>),
|
||||
FixedArraySize(ExpectedFound<u64>),
|
||||
ArgCount,
|
||||
|
||||
RegionsDoesNotOutlive(I::Region, I::Region),
|
||||
RegionsInsufficientlyPolymorphic(I::BoundRegion, I::Region),
|
||||
RegionsPlaceholderMismatch,
|
||||
|
||||
Sorts(ExpectedFound<I::Ty>),
|
||||
ArgumentSorts(ExpectedFound<I::Ty>, usize),
|
||||
Traits(ExpectedFound<I::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(I::Ty),
|
||||
CyclicConst(I::Const),
|
||||
ProjectionMismatched(ExpectedFound<I::DefId>),
|
||||
ExistentialMismatch(ExpectedFound<I::BoundExistentialPredicates>),
|
||||
ConstMismatch(ExpectedFound<I::Const>),
|
||||
|
||||
IntrinsicCast,
|
||||
/// Safe `#[target_feature]` functions are not assignable to safe function pointers.
|
||||
TargetFeatureCast(I::DefId),
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeError<I> {
|
||||
pub fn involves_regions(self) -> bool {
|
||||
match self {
|
||||
TypeError::RegionsDoesNotOutlive(_, _)
|
||||
| TypeError::RegionsInsufficientlyPolymorphic(_, _)
|
||||
| TypeError::RegionsPlaceholderMismatch => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
| RegionsDoesNotOutlive(..)
|
||||
| RegionsInsufficientlyPolymorphic(..)
|
||||
| RegionsPlaceholderMismatch
|
||||
| Traits(_)
|
||||
| ProjectionMismatched(_)
|
||||
| ExistentialMismatch(_)
|
||||
| ConstMismatch(_)
|
||||
| IntrinsicCast => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> From<TypeError<I>> for NoSolution {
|
||||
fn from(_: TypeError<I>) -> NoSolution {
|
||||
NoSolution
|
||||
}
|
||||
}
|
@ -21,18 +21,19 @@
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
use std::sync::Arc as Lrc;
|
||||
|
||||
// These modules are `pub` since they are not glob-imported.
|
||||
#[macro_use]
|
||||
pub mod visit;
|
||||
#[cfg(feature = "nightly")]
|
||||
pub mod codec;
|
||||
pub mod error;
|
||||
pub mod fold;
|
||||
pub mod inherent;
|
||||
pub mod ir_print;
|
||||
pub mod lift;
|
||||
pub mod solve;
|
||||
pub mod ty_info;
|
||||
pub mod ty_kind;
|
||||
|
||||
// These modules are not `pub` since they are glob-imported.
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod binder;
|
||||
@ -46,6 +47,8 @@
|
||||
mod predicate;
|
||||
mod predicate_kind;
|
||||
mod region_kind;
|
||||
mod ty_info;
|
||||
mod ty_kind;
|
||||
mod upcast;
|
||||
|
||||
pub use binder::*;
|
||||
|
@ -48,10 +48,22 @@ fn visit_with<F: $crate::visit::TypeVisitor<I>>(
|
||||
u32,
|
||||
u64,
|
||||
String,
|
||||
crate::DebruijnIndex,
|
||||
crate::AliasRelationDirection,
|
||||
crate::UniverseIndex,
|
||||
rustc_ast_ir::Mutability,
|
||||
rustc_ast_ir::Movability,
|
||||
crate::AliasTyKind,
|
||||
crate::BoundConstness,
|
||||
crate::DebruijnIndex,
|
||||
crate::FloatTy,
|
||||
crate::InferTy,
|
||||
crate::IntVarValue,
|
||||
crate::PredicatePolarity,
|
||||
crate::RegionVid,
|
||||
crate::solve::BuiltinImplSource,
|
||||
crate::solve::Certainty,
|
||||
crate::solve::GoalSource,
|
||||
crate::solve::MaybeCause,
|
||||
crate::solve::NoSolution,
|
||||
crate::UniverseIndex,
|
||||
crate::Variance,
|
||||
rustc_ast_ir::Movability,
|
||||
rustc_ast_ir::Mutability,
|
||||
}
|
||||
|
@ -793,3 +793,36 @@ pub struct CoercePredicate<I: Interner> {
|
||||
pub a: I::Ty,
|
||||
pub b: I::Ty,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, 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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
pub type QueryResult<I> = Result<CanonicalResponse<I>, NoSolution>;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
#[derive(TypeFoldable_Generic, TypeVisitable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub struct NoSolution;
|
||||
|
||||
@ -60,7 +59,7 @@ pub fn with<Q>(self, tcx: I, predicate: impl Upcast<I, Q>) -> Goal<I, Q> {
|
||||
///
|
||||
/// This is necessary as we treat nested goals different depending on
|
||||
/// their source.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub enum GoalSource {
|
||||
Misc,
|
||||
@ -170,7 +169,6 @@ pub enum CandidateSource<I: Interner> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, TyEncodable, TyDecodable))]
|
||||
pub enum BuiltinImplSource {
|
||||
/// Some builtin impl we don't need to differentiate. This should be used
|
||||
@ -214,7 +212,6 @@ pub struct Response<I: Interner> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub enum Certainty {
|
||||
Yes,
|
||||
@ -252,7 +249,6 @@ pub const fn overflow(suggest_increasing_limit: bool) -> Certainty {
|
||||
|
||||
/// Why we failed to evaluate a goal.
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub enum MaybeCause {
|
||||
/// We failed due to ambiguity. This ambiguity can either
|
||||
|
Loading…
Reference in New Issue
Block a user