diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 06a7b1f6c298d..bbf36fef1ddbe 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -379,13 +379,13 @@ fn compare_method_predicate_entailment<'tcx>( // Annoyingly, asking for the WF predicates of an array (with an unevaluated const (only?)) // will give back the well-formed predicate of the same array. let mut wf_args_seen: FxHashSet<_> = wf_args.iter().copied().collect(); - while let Some(arg) = wf_args.pop() { + while let Some(term) = wf_args.pop() { let Some(obligations) = rustc_trait_selection::traits::wf::obligations( infcx, param_env, impl_m_def_id, 0, - arg, + term, impl_m_span, ) else { continue; @@ -402,9 +402,9 @@ fn compare_method_predicate_entailment<'tcx>( | ty::ClauseKind::TypeOutlives(..) | ty::ClauseKind::Projection(..), ) => ocx.register_obligation(obligation), - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { - if wf_args_seen.insert(arg) { - wf_args.push(arg) + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { + if wf_args_seen.insert(term) { + wf_args.push(term) } } _ => {} diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 33d5a86beb3b0..26111e2a1ac0d 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -76,12 +76,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { ) } - fn register_wf_obligation( - &self, - span: Span, - loc: Option, - arg: ty::GenericArg<'tcx>, - ) { + fn register_wf_obligation(&self, span: Span, loc: Option, term: ty::Term<'tcx>) { let cause = traits::ObligationCause::new( span, self.body_def_id, @@ -91,7 +86,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { self.tcx(), cause, self.param_env, - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))), + ty::ClauseKind::WellFormed(term), )); } } @@ -1486,7 +1481,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id tcx.def_span(param.def_id), matches!(param.kind, GenericParamDefKind::Type { .. }) .then(|| WellFormedLoc::Ty(param.def_id.expect_local())), - default, + default.as_term().unwrap(), ); } } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index af1107b499f4e..309221f9a127a 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -374,9 +374,12 @@ fn check_predicates<'tcx>( // Include the well-formed predicates of the type parameters of the impl. for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args { + let Some(term) = arg.as_term() else { + continue; + }; let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let obligations = - wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span) + wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, term, span) .unwrap(); assert!(!obligations.has_infer()); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index cac8237f8f61a..362c7d8efac08 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -22,8 +22,8 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{ - self, AdtKind, CanonicalUserType, GenericArgKind, GenericArgsRef, GenericParamDefKind, - IsIdentity, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs, UserSelfTy, + self, AdtKind, CanonicalUserType, GenericArgsRef, GenericParamDefKind, IsIdentity, Ty, TyCtxt, + TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs, UserSelfTy, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; @@ -573,7 +573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Registers an obligation for checking later, during regionck, that `arg` is well-formed. pub(crate) fn register_wf_obligation( &self, - arg: ty::GenericArg<'tcx>, + term: ty::Term<'tcx>, span: Span, code: traits::ObligationCauseCode<'tcx>, ) { @@ -583,16 +583,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, cause, self.param_env, - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))), + ty::ClauseKind::WellFormed(term), )); } /// Registers obligations that all `args` are well-formed. pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, span: Span) { - for arg in args.iter().filter(|arg| { - matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) - }) { - self.register_wf_obligation(arg, span, ObligationCauseCode::WellFormed(None)); + for term in args.iter().filter_map(ty::GenericArg::as_term) { + self.register_wf_obligation(term, span, ObligationCauseCode::WellFormed(None)); } } @@ -1320,27 +1318,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer_args: bool, ) -> ty::GenericArg<'tcx> { let tcx = self.fcx.tcx(); - match param.kind { - GenericParamDefKind::Lifetime => self - .fcx - .re_infer( - self.span, - rustc_hir_analysis::hir_ty_lowering::RegionInferReason::Param(param), - ) - .into(), - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { - if !infer_args && let Some(default) = param.default_value(tcx) { - // If we have a default, then it doesn't matter that we're not inferring - // the type/const arguments: We provide the default where any is missing. - return default.instantiate(tcx, preceding_args); - } - // If no type/const arguments were provided, we have to infer them. - // This case also occurs as a result of some malformed input, e.g., - // a lifetime argument being given instead of a type/const parameter. - // Using inference instead of `Error` gives better error messages. - self.fcx.var_for_def(self.span, param) - } + if !infer_args && let Some(default) = param.default_value(tcx) { + // If we have a default, then it doesn't matter that we're not inferring + // the type/const arguments: We provide the default where any is missing. + return default.instantiate(tcx, preceding_args); } + // If no type/const arguments were provided, we have to infer them. + // This case also occurs as a result of some malformed input, e.g., + // a lifetime argument being given instead of a type/const parameter. + // Using inference instead of `Error` gives better error messages. + self.fcx.var_for_def(self.span, param) } } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 3caaa7f9a9d0b..c5000171ad75e 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -863,7 +863,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { Resolver { fcx, span, body, nested_goals, should_normalize } } - fn report_error(&self, p: impl Into>) -> ErrorGuaranteed { + fn report_error(&self, p: impl Into>) -> ErrorGuaranteed { if let Some(guar) = self.fcx.tainted_by_errors() { guar } else { @@ -887,7 +887,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { new_err: impl Fn(TyCtxt<'tcx>, ErrorGuaranteed) -> T, ) -> T where - T: Into> + TypeSuperFoldable> + Copy, + T: Into> + TypeSuperFoldable> + Copy, { let tcx = self.fcx.tcx; // We must deeply normalize in the new solver, since later lints expect diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c4698e5cbb456..d25542dadd59b 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -31,9 +31,9 @@ use rustc_middle::traits::solve::Goal; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, - GenericArgsRef, GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Ty, TyCtxt, - TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, - TypingMode, fold_regions, + GenericArgsRef, GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Term, TermKind, + Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, + TypeVisitableExt, TypingEnv, TypingMode, fold_regions, }; use rustc_span::{Span, Symbol}; use snapshot::undo_log::InferCtxtUndoLogs; @@ -1401,6 +1401,16 @@ impl<'tcx> TyOrConstInferVar { } } + /// Tries to extract an inference variable from a type or a constant, returns `None` + /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and + /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`). + pub fn maybe_from_term(term: Term<'tcx>) -> Option { + match term.unpack() { + TermKind::Ty(ty) => Self::maybe_from_ty(ty), + TermKind::Const(ct) => Self::maybe_from_const(ct), + } + } + /// Tries to extract an inference variable from a type, returns `None` /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`). fn maybe_from_ty(ty: Ty<'tcx>) -> Option { diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 8de64b3bfac65..542c0b3e6ebb4 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -250,17 +250,17 @@ impl<'tcx> GenericArg<'tcx> { } #[inline] - pub fn as_type(self) -> Option> { + pub fn as_region(self) -> Option> { match self.unpack() { - GenericArgKind::Type(ty) => Some(ty), + GenericArgKind::Lifetime(re) => Some(re), _ => None, } } #[inline] - pub fn as_region(self) -> Option> { + pub fn as_type(self) -> Option> { match self.unpack() { - GenericArgKind::Lifetime(re) => Some(re), + GenericArgKind::Type(ty) => Some(ty), _ => None, } } @@ -273,6 +273,15 @@ impl<'tcx> GenericArg<'tcx> { } } + #[inline] + pub fn as_term(self) -> Option> { + match self.unpack() { + GenericArgKind::Lifetime(_) => None, + GenericArgKind::Type(ty) => Some(ty.into()), + GenericArgKind::Const(ct) => Some(ct.into()), + } + } + /// Unpack the `GenericArg` as a region when it is known certainly to be a region. pub fn expect_region(self) -> ty::Region<'tcx> { self.as_region().unwrap_or_else(|| bug!("expected a region, but found another kind")) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3698cfb98709d..be00c0e116dd3 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -110,6 +110,7 @@ use crate::ty::codec::{TyDecoder, TyEncoder}; pub use crate::ty::diagnostics::*; use crate::ty::fast_reject::SimplifiedType; use crate::ty::util::Discr; +use crate::ty::walk::TypeWalker; pub mod abstract_const; pub mod adjustment; @@ -631,6 +632,20 @@ impl<'tcx> Term<'tcx> { TermKind::Const(ct) => ct.is_ct_infer(), } } + + /// Iterator that walks `self` and any types reachable from + /// `self`, in depth-first order. Note that just walks the types + /// that appear in `self`, it does not descend into the fields of + /// structs or variants. For example: + /// + /// ```text + /// isize => { isize } + /// Foo> => { Foo>, Bar, isize } + /// [isize] => { [isize], isize } + /// ``` + pub fn walk(self) -> TypeWalker> { + TypeWalker::new(self.into()) + } } const TAG_MASK: usize = 0b11; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index d739218af5ee7..1df3bff524422 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3247,7 +3247,7 @@ define_print! { ty::ClauseKind::ConstArgHasType(ct, ty) => { p!("the constant `", print(ct), "` has type `", print(ty), "`") }, - ty::ClauseKind::WellFormed(arg) => p!(print(arg), " well-formed"), + ty::ClauseKind::WellFormed(term) => p!(print(term), " well-formed"), ty::ClauseKind::ConstEvaluatable(ct) => { p!("the constant `", print(ct), "` can be evaluated") } diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index c4b6b18c45d6f..25493970a0ceb 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -36,7 +36,7 @@ pub trait SolverDelegate: Deref + Sized { fn well_formed_goals( &self, param_env: ::ParamEnv, - arg: ::GenericArg, + term: ::Term, ) -> Option::Predicate>>>; fn clone_opaque_types_for_query_response( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 27ca8787db5c5..dfe742f46f7ab 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -533,8 +533,8 @@ where ty::PredicateKind::DynCompatible(trait_def_id) => { self.compute_dyn_compatible_goal(trait_def_id) } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { - self.compute_well_formed_goal(Goal { param_env, predicate: arg }) + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { + self.compute_well_formed_goal(Goal { param_env, predicate: term }) } ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => { self.compute_const_evaluatable_goal(Goal { param_env, predicate: ct }) @@ -1012,9 +1012,9 @@ where pub(super) fn well_formed_goals( &self, param_env: I::ParamEnv, - arg: I::GenericArg, + term: I::Term, ) -> Option>> { - self.delegate.well_formed_goals(param_env, arg) + self.delegate.well_formed_goals(param_env, term) } pub(super) fn trait_ref_is_knowable( diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 0695c5acdcab3..7b2121286ea29 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -126,7 +126,7 @@ where } #[instrument(level = "trace", skip(self))] - fn compute_well_formed_goal(&mut self, goal: Goal) -> QueryResult { + fn compute_well_formed_goal(&mut self, goal: Goal) -> QueryResult { match self.well_formed_goals(goal.param_env, goal.predicate) { Some(goals) => { self.add_goals(GoalSource::Misc, goals); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 0bde289c85fc0..b56f3e1971cc8 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -157,7 +157,7 @@ where ty.visit_with(self) } ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self), - ty::ClauseKind::WellFormed(arg) => arg.visit_with(self), + ty::ClauseKind::WellFormed(term) => term.visit_with(self), } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index a757329bcf2ae..c0ed3b90eb416 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -638,8 +638,8 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> { const_.stable(tables), ty.stable(tables), ), - ClauseKind::WellFormed(generic_arg) => { - stable_mir::ty::ClauseKind::WellFormed(generic_arg.unpack().stable(tables)) + ClauseKind::WellFormed(term) => { + stable_mir::ty::ClauseKind::WellFormed(term.unpack().stable(tables)) } ClauseKind::ConstEvaluatable(const_) => { stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables)) diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 4b153007bd863..0ac9a0fb64785 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -1462,7 +1462,7 @@ pub enum ClauseKind { TypeOutlives(TypeOutlivesPredicate), Projection(ProjectionPredicate), ConstArgHasType(TyConst, Ty), - WellFormed(GenericArgKind), + WellFormed(TermKind), ConstEvaluatable(TyConst), } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index f45e3904212c4..eba195cb99cf0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -14,8 +14,8 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; use rustc_middle::ty::{ - self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Ty, TyCtxt, - TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, + self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind, + Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, }; use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym}; use rustc_type_ir::TypeVisitableExt; @@ -344,12 +344,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// which were stuck during inference. pub fn extract_inference_diagnostics_data( &self, - arg: GenericArg<'tcx>, + term: Term<'tcx>, highlight: ty::print::RegionHighlightMode<'tcx>, ) -> InferenceDiagnosticsData { let tcx = self.tcx; - match arg.unpack() { - GenericArgKind::Type(ty) => { + match term.unpack() { + TermKind::Ty(ty) => { if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() { let var_origin = self.infcx.type_var_origin(ty_vid); if let Some(def_id) = var_origin.param_def_id @@ -375,7 +375,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { parent: None, } } - GenericArgKind::Const(ct) => { + TermKind::Const(ct) => { if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() { let origin = self.const_var_origin(vid).expect("expected unresolved const var"); if let Some(def_id) = origin.param_def_id { @@ -411,7 +411,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } } - GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), } } @@ -472,13 +471,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &self, body_def_id: LocalDefId, failure_span: Span, - arg: GenericArg<'tcx>, + term: Term<'tcx>, error_code: TypeAnnotationNeeded, should_label_span: bool, ) -> Diag<'a> { - let arg = self.resolve_vars_if_possible(arg); - let arg_data = - self.extract_inference_diagnostics_data(arg, ty::print::RegionHighlightMode::default()); + let term = self.resolve_vars_if_possible(term); + let arg_data = self + .extract_inference_diagnostics_data(term, ty::print::RegionHighlightMode::default()); let Some(typeck_results) = &self.typeck_results else { // If we don't have any typeck results we're outside @@ -487,7 +486,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return self.bad_inference_failure_err(failure_span, arg_data, error_code); }; - let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg); + let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, term); if let Some(body) = self.tcx.hir_maybe_body_owned_by( self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(), ) { @@ -542,7 +541,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { have_turbofish, } => { let generics = self.tcx.generics_of(generics_def_id); - let is_type = matches!(arg.unpack(), GenericArgKind::Type(_)); + let is_type = term.as_type().is_some(); let (parent_exists, parent_prefix, parent_name) = InferenceDiagnosticsParentData::for_parent_def_id(self.tcx, generics_def_id) @@ -811,7 +810,7 @@ struct FindInferSourceVisitor<'a, 'tcx> { tecx: &'a TypeErrCtxt<'a, 'tcx>, typeck_results: &'a TypeckResults<'tcx>, - target: GenericArg<'tcx>, + target: Term<'tcx>, attempt: usize, infer_source_cost: usize, @@ -822,7 +821,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { fn new( tecx: &'a TypeErrCtxt<'a, 'tcx>, typeck_results: &'a TypeckResults<'tcx>, - target: GenericArg<'tcx>, + target: Term<'tcx>, ) -> Self { FindInferSourceVisitor { tecx, @@ -938,12 +937,12 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { // Check whether this generic argument is the inference variable we // are looking for. fn generic_arg_is_target(&self, arg: GenericArg<'tcx>) -> bool { - if arg == self.target { + if arg == self.target.into() { return true; } match (arg.unpack(), self.target.unpack()) { - (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => { + (GenericArgKind::Type(inner_ty), TermKind::Ty(target_ty)) => { use ty::{Infer, TyVar}; match (inner_ty.kind(), target_ty.kind()) { (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => { @@ -952,7 +951,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { _ => false, } } - (GenericArgKind::Const(inner_ct), GenericArgKind::Const(target_ct)) => { + (GenericArgKind::Const(inner_ct), TermKind::Const(target_ct)) => { use ty::InferConst::*; match (inner_ct.kind(), target_ct.kind()) { (ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 54b50851b74de..275b580d79453 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -228,13 +228,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Pick the first generic parameter that still contains inference variables as the one // we're going to emit an error for. If there are none (see above), fall back to // a more general error. - let arg = data.trait_ref.args.iter().find(|s| s.has_non_region_infer()); + let term = data + .trait_ref + .args + .iter() + .filter_map(ty::GenericArg::as_term) + .find(|s| s.has_non_region_infer()); - let mut err = if let Some(arg) = arg { + let mut err = if let Some(term) = term { self.emit_inference_failure_err( obligation.cause.body_id, span, - arg, + term, TypeAnnotationNeeded::E0283, true, ) @@ -276,7 +281,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer { if let Some(e) = self.tainted_by_errors() - && arg.is_none() + && term.is_none() { // If `arg.is_none()`, then this is probably two param-env // candidates or impl candidates that are equal modulo lifetimes. @@ -313,7 +318,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.suggest_fully_qualified_path(&mut err, def_id, span, trait_pred.def_id()); } - if let Some(ty::GenericArgKind::Type(_)) = arg.map(|arg| arg.unpack()) + if term.is_some_and(|term| term.as_type().is_some()) && let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_id) { let mut expr_finder = FindExprBySpan::new(span, self.tcx); @@ -464,11 +469,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { // Same hacky approach as above to avoid deluging user // with error messages. - if let Err(e) = arg.error_reported() { + if let Err(e) = term.error_reported() { return e; } if let Some(e) = self.tainted_by_errors() { @@ -478,7 +483,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.emit_inference_failure_err( obligation.cause.body_id, span, - arg, + term, TypeAnnotationNeeded::E0282, false, ) @@ -519,18 +524,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // other `Foo` impls are incoherent. return guar; } - let arg = data + let term = data .projection_term .args .iter() - .chain(Some(data.term.into_arg())) + .filter_map(ty::GenericArg::as_term) + .chain([data.term]) .find(|g| g.has_non_region_infer()); let predicate = self.tcx.short_string(predicate, &mut file); - if let Some(arg) = arg { + if let Some(term) = term { self.emit_inference_failure_err( obligation.cause.body_id, span, - arg, + term, TypeAnnotationNeeded::E0284, true, ) @@ -554,12 +560,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(e) = self.tainted_by_errors() { return e; } - let arg = data.walk().find(|g| g.is_non_region_infer()); - if let Some(arg) = arg { + let term = + data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer()); + if let Some(term) = term { let err = self.emit_inference_failure_err( obligation.cause.body_id, span, - arg, + term, TypeAnnotationNeeded::E0284, true, ); diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index e0b425fa7391b..a87c5ad6db966 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -92,12 +92,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< fn well_formed_goals( &self, param_env: ty::ParamEnv<'tcx>, - arg: ty::GenericArg<'tcx>, + term: ty::Term<'tcx>, ) -> Option>>> { - crate::traits::wf::unnormalized_obligations(&self.0, param_env, arg, DUMMY_SP, CRATE_DEF_ID) - .map(|obligations| { - obligations.into_iter().map(|obligation| obligation.as_goal()).collect() - }) + crate::traits::wf::unnormalized_obligations( + &self.0, + param_env, + term, + DUMMY_SP, + CRATE_DEF_ID, + ) + .map(|obligations| obligations.into_iter().map(|obligation| obligation.as_goal()).collect()) } fn clone_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index f6c650c68c01c..a024f432450c4 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -241,13 +241,13 @@ impl<'tcx> BestObligation<'tcx> { fn visit_well_formed_goal( &mut self, candidate: &inspect::InspectCandidate<'_, 'tcx>, - arg: ty::GenericArg<'tcx>, + term: ty::Term<'tcx>, ) -> ControlFlow> { let infcx = candidate.goal().infcx(); let param_env = candidate.goal().goal().param_env; let body_id = self.obligation.cause.body_id; - for obligation in wf::unnormalized_obligations(infcx, param_env, arg, self.span(), body_id) + for obligation in wf::unnormalized_obligations(infcx, param_env, term, self.span(), body_id) .into_iter() .flatten() { @@ -443,8 +443,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { polarity: ty::PredicatePolarity::Positive, })) } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { - return self.visit_well_formed_goal(candidate, arg); + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { + return self.visit_well_formed_goal(candidate, term); } _ => ChildMode::PassThrough, }; diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index a11f8d3a9ec6b..34c3c905bd977 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -540,18 +540,18 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { self.selcx.infcx.err_ctxt().report_overflow_obligation(&obligation, false); } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { match wf::obligations( self.selcx.infcx, obligation.param_env, obligation.cause.body_id, obligation.recursion_depth + 1, - arg, + term, obligation.cause.span, ) { None => { pending_obligation.stalled_on = - vec![TyOrConstInferVar::maybe_from_generic_arg(arg).unwrap()]; + vec![TyOrConstInferVar::maybe_from_term(term).unwrap()]; ProcessResult::Unchanged } Some(os) => ProcessResult::Changed(mk_pending(obligation, os)), diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs index f059bd0076897..81b5a131a32e0 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs @@ -131,12 +131,12 @@ fn relate_mir_and_user_args<'tcx>( // const CONST: () = { /* arbitrary code that depends on T being WF */ }; // } // ``` - for arg in args { + for term in args.iter().filter_map(ty::GenericArg::as_term) { ocx.register_obligation(Obligation::new( tcx, cause.clone(), param_env, - ty::ClauseKind::WellFormed(arg), + ty::ClauseKind::WellFormed(term), )); } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index f98529860ff81..1df69932c64db 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -113,8 +113,8 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( | ty::PredicateKind::AliasRelate(..) => {} // We need to search through *all* WellFormed predicates - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { - wf_args.push(arg); + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { + wf_args.push(term); } // We need to register region relationships diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs index 87fc532adaf67..18971c47831a4 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs @@ -19,10 +19,10 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { return Some(()); } - if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) = + if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) = key.value.predicate.kind().skip_binder() { - match arg.as_type()?.kind() { + match term.as_type()?.kind() { ty::Param(_) | ty::Bool | ty::Char diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c7ce13c8014f0..89febd6ce3da1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -658,7 +658,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { // So, there is a bit going on here. First, `WellFormed` predicates // are coinductive, like trait predicates with auto traits. // This means that we need to detect if we have recursively @@ -682,11 +682,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cache = previous_stack.cache; let dfn = cache.next_dfn(); - for stack_arg in previous_stack.cache.wf_args.borrow().iter().rev() { - if stack_arg.0 != arg { + for stack_term in previous_stack.cache.wf_args.borrow().iter().rev() { + if stack_term.0 != term { continue; } - debug!("WellFormed({:?}) on stack", arg); + debug!("WellFormed({:?}) on stack", term); if let Some(stack) = previous_stack.head { // Okay, let's imagine we have two different stacks: // `T: NonAutoTrait -> WF(T) -> T: NonAutoTrait` @@ -702,11 +702,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // would contain `(T, 1)`. We want to check all // trait predicates greater than `1`. The previous // stack would be `T: Auto`. - let cycle = stack.iter().take_while(|s| s.depth > stack_arg.1); + let cycle = stack.iter().take_while(|s| s.depth > stack_term.1); let tcx = self.tcx(); let cycle = cycle.map(|stack| stack.obligation.predicate.upcast(tcx)); if self.coinductive_match(cycle) { - stack.update_reached_depth(stack_arg.1); + stack.update_reached_depth(stack_term.1); return Ok(EvaluatedToOk); } else { return Ok(EvaluatedToAmbigStackDependent); @@ -720,11 +720,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.param_env, obligation.cause.body_id, obligation.recursion_depth + 1, - arg, + term, obligation.cause.span, ) { Some(obligations) => { - cache.wf_args.borrow_mut().push((arg, previous_stack.depth())); + cache.wf_args.borrow_mut().push((term, previous_stack.depth())); let result = self.evaluate_predicates_recursively(previous_stack, obligations); cache.wf_args.borrow_mut().pop(); @@ -2969,14 +2969,14 @@ struct ProvisionalEvaluationCache<'tcx> { /// means the cached value for `F`. map: RefCell, ProvisionalEvaluation>>, - /// The stack of args that we assume to be true because a `WF(arg)` predicate + /// The stack of terms that we assume to be well-formed because a `WF(term)` predicate /// is on the stack above (and because of wellformedness is coinductive). /// In an "ideal" world, this would share a stack with trait predicates in /// `TraitObligationStack`. However, trait predicates are *much* hotter than /// `WellFormed` predicates, and it's very likely that the additional matches /// will have a perf effect. The value here is the well-formed `GenericArg` /// and the depth of the trait predicate *above* that well-formed predicate. - wf_args: RefCell, usize)>>, + wf_args: RefCell, usize)>>, } /// A cache value for the provisional cache: contains the depth-first diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index cad7e42fd8212..62bd8e1af05de 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -10,8 +10,8 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; use rustc_middle::bug; use rustc_middle::ty::{ - self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, + self, GenericArgsRef, Term, TermKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, }; use rustc_session::parse::feature_err; use rustc_span::def_id::{DefId, LocalDefId}; @@ -32,12 +32,12 @@ pub fn obligations<'tcx>( param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, recursion_depth: usize, - arg: GenericArg<'tcx>, + term: Term<'tcx>, span: Span, ) -> Option> { // Handle the "cycle" case (see comment above) by bailing out if necessary. - let arg = match arg.unpack() { - GenericArgKind::Type(ty) => { + let term = match term.unpack() { + TermKind::Ty(ty) => { match ty.kind() { ty::Infer(ty::TyVar(_)) => { let resolved_ty = infcx.shallow_resolve(ty); @@ -52,7 +52,7 @@ pub fn obligations<'tcx>( } .into() } - GenericArgKind::Const(ct) => { + TermKind::Const(ct) => { match ct.kind() { ty::ConstKind::Infer(_) => { let resolved = infcx.shallow_resolve_const(ct); @@ -67,8 +67,6 @@ pub fn obligations<'tcx>( } .into() } - // There is nothing we have to do for lifetimes. - GenericArgKind::Lifetime(..) => return Some(PredicateObligations::new()), }; let mut wf = WfPredicates { @@ -80,11 +78,11 @@ pub fn obligations<'tcx>( recursion_depth, item: None, }; - wf.add_wf_preds_for_generic_arg(arg); - debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out); + wf.add_wf_preds_for_term(term); + debug!("wf::obligations({:?}, body_id={:?}) = {:?}", term, body_id, wf.out); let result = wf.normalize(infcx); - debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", arg, body_id, result); + debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", term, body_id, result); Some(result) } @@ -95,23 +93,19 @@ pub fn obligations<'tcx>( pub fn unnormalized_obligations<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - arg: GenericArg<'tcx>, + term: Term<'tcx>, span: Span, body_id: LocalDefId, ) -> Option> { - debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg)); + debug_assert_eq!(term, infcx.resolve_vars_if_possible(term)); // However, if `arg` IS an unresolved inference variable, returns `None`, // because we are not able to make any progress at all. This is to prevent // cycles where we say "?0 is WF if ?0 is WF". - if arg.is_non_region_infer() { + if term.is_infer() { return None; } - if let ty::GenericArgKind::Lifetime(..) = arg.unpack() { - return Some(PredicateObligations::new()); - } - let mut wf = WfPredicates { infcx, param_env, @@ -121,7 +115,7 @@ pub fn unnormalized_obligations<'tcx>( recursion_depth: 0, item: None, }; - wf.add_wf_preds_for_generic_arg(arg); + wf.add_wf_preds_for_term(term); Some(wf.out) } @@ -185,22 +179,22 @@ pub fn clause_obligations<'tcx>( } ty::ClauseKind::RegionOutlives(..) => {} ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => { - wf.add_wf_preds_for_generic_arg(ty.into()); + wf.add_wf_preds_for_term(ty.into()); } ty::ClauseKind::Projection(t) => { wf.add_wf_preds_for_alias_term(t.projection_term); - wf.add_wf_preds_for_generic_arg(t.term.into_arg()); + wf.add_wf_preds_for_term(t.term); } ty::ClauseKind::ConstArgHasType(ct, ty) => { - wf.add_wf_preds_for_generic_arg(ct.into()); - wf.add_wf_preds_for_generic_arg(ty.into()); + wf.add_wf_preds_for_term(ct.into()); + wf.add_wf_preds_for_term(ty.into()); } - ty::ClauseKind::WellFormed(arg) => { - wf.add_wf_preds_for_generic_arg(arg); + ty::ClauseKind::WellFormed(term) => { + wf.add_wf_preds_for_term(term); } ty::ClauseKind::ConstEvaluatable(ct) => { - wf.add_wf_preds_for_generic_arg(ct.into()); + wf.add_wf_preds_for_term(ct.into()); } } @@ -426,11 +420,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { .args .iter() .enumerate() - .filter(|(_, arg)| { - matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) - }) - .filter(|(_, arg)| !arg.has_escaping_bound_vars()) - .map(|(i, arg)| { + .filter_map(|(i, arg)| arg.as_term().map(|t| (i, t))) + .filter(|(_, term)| !term.has_escaping_bound_vars()) + .map(|(i, term)| { let mut cause = traits::ObligationCause::misc(self.span, self.body_id); // The first arg is the self ty - use the correct span for it. if i == 0 { @@ -445,9 +437,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, depth, param_env, - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( - arg, - ))), + ty::ClauseKind::WellFormed(term), ) }), ); @@ -457,7 +447,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // given that it is a *negative* trait predicate. fn add_wf_preds_for_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) { for arg in trait_ref.args { - self.add_wf_preds_for_generic_arg(arg); + if let Some(term) = arg.as_term() { + self.add_wf_preds_for_term(term); + } } } @@ -529,19 +521,15 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.out.extend( args.iter() - .filter(|arg| { - matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..)) - }) - .filter(|arg| !arg.has_escaping_bound_vars()) - .map(|arg| { + .filter_map(|arg| arg.as_term()) + .filter(|term| !term.has_escaping_bound_vars()) + .map(|term| { traits::Obligation::with_depth( tcx, cause.clone(), depth, param_env, - ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( - arg, - ))), + ty::ClauseKind::WellFormed(term), ) }), ); @@ -565,10 +553,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } - /// Pushes all the predicates needed to validate that `ty` is WF into `out`. + /// Pushes all the predicates needed to validate that `term` is WF into `out`. #[instrument(level = "debug", skip(self))] - fn add_wf_preds_for_generic_arg(&mut self, arg: GenericArg<'tcx>) { - arg.visit_with(self); + fn add_wf_preds_for_term(&mut self, term: Term<'tcx>) { + term.visit_with(self); debug!(?self.out); } diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index e9d3a149a7303..74fb148a7cc30 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -1,5 +1,3 @@ -use std::slice; - use crate::inherent::*; use crate::visit::Flags; use crate::{self as ty, Interner}; @@ -388,8 +386,8 @@ impl FlagComputation { self.add_alias_term(projection_term); self.add_term(term); } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { - self.add_args(slice::from_ref(&arg)); + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => { + self.add_term(term); } ty::PredicateKind::DynCompatible(_def_id) => {} ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => { diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 847dff156fe87..4e41fd16ffd76 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -36,7 +36,7 @@ pub enum ClauseKind { ConstArgHasType(I::Const, I::Ty), /// No syntax: `T` well-formed. - WellFormed(I::GenericArg), + WellFormed(I::Term), /// Constant initializer must evaluate successfully. ConstEvaluatable(I::Const),