Uplift TypeError

This commit is contained in:
Michael Goulet 2024-05-27 16:12:28 -04:00
parent c74efbca71
commit 82ef3ad980
16 changed files with 217 additions and 194 deletions

View File

@ -15,6 +15,7 @@ use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
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};

View File

@ -40,7 +40,7 @@ use rustc_infer::infer::InferOk;
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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)

View File

@ -71,6 +71,7 @@ use rustc_hir::lang_items::LangItem;
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;

View File

@ -21,13 +21,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
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 @@ impl<T> Trait<T> for 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 @@ impl<T> Trait<T> for 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"

View File

@ -276,7 +276,7 @@ impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> {
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)
}
}

View File

@ -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>>,

View File

@ -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() {

View File

@ -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> {

View File

@ -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,

View File

@ -28,7 +28,7 @@ use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk};
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 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
&& 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 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
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 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
};
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 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
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 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
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 {

View File

@ -42,6 +42,7 @@ use rustc_middle::dep_graph::DepNodeIndex;
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;

View 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
}
}

View File

@ -21,18 +21,19 @@ use std::hash::Hash;
#[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 interner;
mod predicate;
mod predicate_kind;
mod region_kind;
mod ty_info;
mod ty_kind;
mod upcast;
pub use binder::*;

View File

@ -48,10 +48,22 @@ TrivialTypeTraversalImpls! {
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,
}

View File

@ -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"),
}
}
}

View File

@ -20,7 +20,6 @@ pub type CanonicalResponse<I> = Canonical<I, Response<I>>;
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 @@ impl<I: Interner, P> Goal<I, P> {
///
/// 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 @@ impl 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