From 82ef3ad98031377e20634d1f9f4aa3039db40025 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 27 May 2024 16:12:28 -0400 Subject: [PATCH] Uplift TypeError --- .../rustc_hir_analysis/src/check/check.rs | 1 + compiler/rustc_hir_typeck/src/expr.rs | 5 +- .../src/infer/error_reporting/mod.rs | 1 + .../infer/error_reporting/note_and_explain.rs | 7 +- .../infer/region_constraints/leak_check.rs | 2 +- compiler/rustc_middle/src/traits/query.rs | 7 - compiler/rustc_middle/src/ty/error.rs | 163 +++++------------- compiler/rustc_middle/src/ty/mod.rs | 32 ---- .../rustc_middle/src/ty/structural_impls.rs | 8 +- .../src/traits/error_reporting/suggestions.rs | 12 +- .../src/traits/select/mod.rs | 1 + compiler/rustc_type_ir/src/error.rs | 106 ++++++++++++ compiler/rustc_type_ir/src/lib.rs | 7 +- compiler/rustc_type_ir/src/macros.rs | 20 ++- compiler/rustc_type_ir/src/predicate.rs | 33 ++++ compiler/rustc_type_ir/src/solve.rs | 6 +- 16 files changed, 217 insertions(+), 194 deletions(-) create mode 100644 compiler/rustc_type_ir/src/error.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 8a0623ef93e..72e5995e892 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -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}; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7dd7b3ff055..f0f32ae07a9 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -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) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index fe0a246abbc..cee87f8f6e4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -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; diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 19ef2d61fca..b88677b3a4e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -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" diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 255ca52d3e9..d05ac1d8151 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -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) } } diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 3e9a2cb05fe..50b6c77e1b2 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -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>>; -impl<'tcx> From> for NoSolution { - fn from(_: TypeError<'tcx>) -> NoSolution { - NoSolution - } -} - #[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable)] pub struct DropckOutlivesResult<'tcx> { pub kinds: Vec>, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 9e2c626478a..32dc9fa5fc6 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -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 { - pub expected: T, - pub found: T, -} +pub type TypeError<'tcx> = rustc_type_ir::error::TypeError>; -impl ExpectedFound { - 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), - PolarityMismatch(ExpectedFound), - SafetyMismatch(ExpectedFound), - AbiMismatch(ExpectedFound), - Mutability, - ArgumentMutability(usize), - TupleSize(ExpectedFound), - FixedArraySize(ExpectedFound), - ArgCount, - FieldMisMatch(Symbol, Symbol), - - RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>), - RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>), - RegionsPlaceholderMismatch, - - Sorts(ExpectedFound>), - ArgumentSorts(ExpectedFound>, usize), - Traits(ExpectedFound), - VariadicMismatch(ExpectedFound), - - /// 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), - ExistentialMismatch(ExpectedFound<&'tcx ty::List>>), - ConstMismatch(ExpectedFound>), - - 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() { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e0fbf127e70..131c62d6d19 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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> { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index cf4854d1364..cc6b1d57f87 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -296,7 +296,6 @@ fn fmt>>( ::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>>( 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>>( crate::ty::BoundRegionKind, crate::ty::AssocItem, crate::ty::AssocKind, - crate::ty::AliasTyKind, crate::ty::Placeholder, crate::ty::Placeholder, crate::ty::Placeholder, 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, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6a96a03e047..c7da85bd1cc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -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( && 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( 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( }; 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( 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 { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ce4fa5fa47c..9e6ae912515 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -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; diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs new file mode 100644 index 00000000000..27623ea9cac --- /dev/null +++ b/compiler/rustc_type_ir/src/error.rs @@ -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 { + pub expected: T, + pub found: T, +} + +impl ExpectedFound { + 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 { + Mismatch, + ConstnessMismatch(ExpectedFound), + PolarityMismatch(ExpectedFound), + SafetyMismatch(ExpectedFound), + AbiMismatch(ExpectedFound), + Mutability, + ArgumentMutability(usize), + TupleSize(ExpectedFound), + FixedArraySize(ExpectedFound), + ArgCount, + + RegionsDoesNotOutlive(I::Region, I::Region), + RegionsInsufficientlyPolymorphic(I::BoundRegion, I::Region), + RegionsPlaceholderMismatch, + + Sorts(ExpectedFound), + ArgumentSorts(ExpectedFound, usize), + Traits(ExpectedFound), + VariadicMismatch(ExpectedFound), + + /// 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), + ExistentialMismatch(ExpectedFound), + ConstMismatch(ExpectedFound), + + IntrinsicCast, + /// Safe `#[target_feature]` functions are not assignable to safe function pointers. + TargetFeatureCast(I::DefId), +} + +impl TypeError { + 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 From> for NoSolution { + fn from(_: TypeError) -> NoSolution { + NoSolution + } +} diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 217c056d0ba..7d363daa420 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -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::*; diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index f2f7b165de5..aae5aeb5fb3 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -48,10 +48,22 @@ fn visit_with>( 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, } diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 9e0e52cfb4b..63a4c2e9d1f 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -793,3 +793,36 @@ pub struct CoercePredicate { 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"), + } + } +} diff --git a/compiler/rustc_type_ir/src/solve.rs b/compiler/rustc_type_ir/src/solve.rs index 3c24e851d7b..45125fe6191 100644 --- a/compiler/rustc_type_ir/src/solve.rs +++ b/compiler/rustc_type_ir/src/solve.rs @@ -20,7 +20,6 @@ pub type QueryResult = Result, 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(self, tcx: I, predicate: impl Upcast) -> Goal { /// /// 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 { } #[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 { } #[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