2020-03-05 18:07:42 -03:00
//! Trait Resolution. See the [rustc dev guide] for more information on how this works.
2018-02-25 15:24:14 -06:00
//!
2020-03-09 18:33:04 -03:00
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
2014-09-12 10:53:35 -04:00
2018-11-27 02:59:49 +00:00
pub mod auto_trait ;
2023-03-21 16:26:23 +01:00
pub ( crate ) mod coherence ;
2020-11-22 09:37:37 +00:00
pub mod const_evaluatable ;
2018-11-27 02:59:49 +00:00
mod engine ;
2019-12-24 17:38:22 -05:00
pub mod error_reporting ;
2018-11-27 02:59:49 +00:00
mod fulfill ;
2020-01-07 19:36:50 +01:00
pub mod misc ;
2024-02-05 13:40:32 +01:00
pub mod normalize ;
2018-11-27 02:59:49 +00:00
mod object_safety ;
2022-08-22 16:53:34 -03:00
pub mod outlives_bounds ;
2023-06-15 09:41:14 +00:00
pub mod project ;
2019-12-24 17:38:22 -05:00
pub mod query ;
2023-07-12 21:38:55 -04:00
#[ allow(hidden_glob_reexports) ]
2018-11-27 02:59:49 +00:00
mod select ;
mod specialize ;
2020-01-05 23:02:07 +01:00
mod structural_match ;
2023-04-23 19:58:24 +00:00
mod structural_normalize ;
2023-07-12 21:38:55 -04:00
#[ allow(hidden_glob_reexports) ]
2018-11-27 02:59:49 +00:00
mod util ;
2023-05-17 12:28:04 +00:00
pub mod vtable ;
2020-01-05 20:52:34 +01:00
pub mod wf ;
2014-11-06 00:05:53 -08:00
2019-02-05 11:20:45 -06:00
use crate ::infer ::outlives ::env ::OutlivesEnvironment ;
2022-06-13 01:11:16 -04:00
use crate ::infer ::{ InferCtxt , TyCtxtInferExt } ;
2023-12-18 22:45:34 +00:00
use crate ::regions ::InferCtxtRegionExt ;
2022-09-09 15:08:06 -05:00
use crate ::traits ::error_reporting ::TypeErrCtxtExt as _ ;
2020-02-22 11:44:18 +01:00
use crate ::traits ::query ::evaluate_obligation ::InferCtxtExt as _ ;
2022-01-23 12:34:26 -06:00
use rustc_errors ::ErrorGuaranteed ;
2023-05-15 06:24:45 +02:00
use rustc_middle ::query ::Providers ;
2024-05-09 08:06:59 +10:00
use rustc_middle ::span_bug ;
2020-03-29 16:41:09 +02:00
use rustc_middle ::ty ::fold ::TypeFoldable ;
2023-02-22 02:18:40 +00:00
use rustc_middle ::ty ::visit ::{ TypeVisitable , TypeVisitableExt } ;
2024-05-15 10:05:25 -04:00
use rustc_middle ::ty ::{ self , Ty , TyCtxt , TypeFolder , TypeSuperVisitable , Upcast } ;
2023-07-11 22:35:29 +01:00
use rustc_middle ::ty ::{ GenericArgs , GenericArgsRef } ;
2023-03-14 14:19:06 +01:00
use rustc_span ::def_id ::DefId ;
2022-12-08 04:51:46 +00:00
use rustc_span ::Span ;
2015-09-24 19:58:00 +03:00
2018-12-07 01:40:42 +00:00
use std ::fmt ::Debug ;
2021-06-17 12:20:18 +08:00
use std ::ops ::ControlFlow ;
2018-12-07 01:40:42 +00:00
2023-10-15 13:40:17 +02:00
pub use self ::coherence ::{ add_placeholder_note , orphan_check_trait_ref , overlapping_impls } ;
pub use self ::coherence ::{ InCrate , IsFirstInputType , UncoveredTyParams } ;
pub use self ::coherence ::{ OrphanCheckErr , OrphanCheckMode , OverlapResult } ;
2022-07-07 15:12:32 +02:00
pub use self ::engine ::{ ObligationCtxt , TraitEngineExt } ;
2024-06-01 14:51:31 -04:00
pub use self ::fulfill ::{ FulfillmentContext , OldSolverError , PendingPredicateObligation } ;
2024-02-05 13:40:32 +01:00
pub use self ::normalize ::NormalizeExt ;
2024-03-15 03:21:55 +01:00
pub use self ::object_safety ::hir_ty_lowering_object_safety_violations ;
2020-01-05 18:07:29 +01:00
pub use self ::object_safety ::is_vtable_safe_method ;
2023-10-04 01:10:51 +00:00
pub use self ::object_safety ::object_safety_violations_for_assoc_item ;
2019-12-24 17:38:22 -05:00
pub use self ::object_safety ::ObjectSafetyViolation ;
2024-05-13 10:00:38 -04:00
pub use self ::project ::{ normalize_inherent_projection , normalize_projection_ty } ;
2020-01-06 20:13:24 +01:00
pub use self ::select ::{ EvaluationCache , SelectionCache , SelectionContext } ;
pub use self ::select ::{ EvaluationResult , IntercrateAmbiguityCause , OverflowError } ;
2018-12-03 23:27:25 +02:00
pub use self ::specialize ::specialization_graph ::FutureCompatOverlapError ;
pub use self ::specialize ::specialization_graph ::FutureCompatOverlapErrorKind ;
2023-05-05 15:52:53 +01:00
pub use self ::specialize ::{
2023-07-11 22:35:29 +01:00
specialization_graph , translate_args , translate_args_with_cause , OverlapError ,
2023-05-05 15:52:53 +01:00
} ;
2023-05-17 18:51:45 +00:00
pub use self ::structural_match ::search_for_structural_match_violation ;
2023-04-23 19:58:24 +00:00
pub use self ::structural_normalize ::StructurallyNormalizeExt ;
2023-04-06 23:24:03 +00:00
pub use self ::util ::elaborate ;
2024-03-22 14:20:31 +08:00
pub use self ::util ::{ expand_trait_aliases , TraitAliasExpander , TraitAliasExpansionInfo } ;
2023-06-21 05:32:35 +00:00
pub use self ::util ::{ get_vtable_index_of_object_method , impl_item_is_final , upcast_choices } ;
2024-04-27 13:58:37 -04:00
pub use self ::util ::{ supertraits , transitive_bounds , transitive_bounds_that_define_assoc_item } ;
2024-02-05 13:40:32 +01:00
pub use self ::util ::{ with_replaced_escaping_bound_vars , BoundVarReplacer , PlaceholderReplacer } ;
2014-09-12 10:53:35 -04:00
2020-02-22 11:44:18 +01:00
pub use rustc_infer ::traits ::* ;
2018-02-25 10:58:54 -05:00
2024-06-01 14:51:31 -04:00
// A trait error without any information in it. You likely want to alternately use [`ObligationCtxt::new_with_diagnostics`] to get a [`FulfillmentError`].
#[ derive(Copy, Clone, Debug) ]
pub enum ScrubbedTraitError {
TrueError ,
Ambiguity ,
}
impl ScrubbedTraitError {
fn is_true_error ( & self ) -> bool {
match self {
ScrubbedTraitError ::TrueError = > true ,
ScrubbedTraitError ::Ambiguity = > false ,
}
}
}
impl < ' tcx > FulfillmentErrorLike < ' tcx > for ScrubbedTraitError {
fn is_true_error ( & self ) -> bool {
self . is_true_error ( )
}
}
2024-06-01 14:12:34 -04:00
pub struct FulfillmentError < ' tcx > {
pub obligation : PredicateObligation < ' tcx > ,
pub code : FulfillmentErrorCode < ' tcx > ,
/// Diagnostics only: the 'root' obligation which resulted in
/// the failure to process `obligation`. This is the obligation
/// that was initially passed to `register_predicate_obligation`
pub root_obligation : PredicateObligation < ' tcx > ,
}
impl < ' tcx > FulfillmentError < ' tcx > {
pub fn new (
obligation : PredicateObligation < ' tcx > ,
code : FulfillmentErrorCode < ' tcx > ,
root_obligation : PredicateObligation < ' tcx > ,
) -> FulfillmentError < ' tcx > {
FulfillmentError { obligation , code , root_obligation }
}
pub fn is_true_error ( & self ) -> bool {
match self . code {
FulfillmentErrorCode ::Select ( _ )
| FulfillmentErrorCode ::Project ( _ )
| FulfillmentErrorCode ::Subtype ( _ , _ )
| FulfillmentErrorCode ::ConstEquate ( _ , _ ) = > true ,
FulfillmentErrorCode ::Cycle ( _ ) | FulfillmentErrorCode ::Ambiguity { overflow : _ } = > {
false
}
}
}
}
impl < ' tcx > FulfillmentErrorLike < ' tcx > for FulfillmentError < ' tcx > {
fn is_true_error ( & self ) -> bool {
self . is_true_error ( )
}
}
impl < ' tcx > Debug for FulfillmentError < ' tcx > {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
write! ( f , " FulfillmentError({:?},{:?}) " , self . obligation , self . code )
}
}
2020-01-24 15:57:01 -05:00
/// Whether to skip the leak check, as part of a future compatibility warning step.
2021-11-22 20:17:53 -05:00
///
/// The "default" for skip-leak-check corresponds to the current
/// behavior (do not skip the leak check) -- not the behavior we are
/// transitioning into.
#[ derive(Copy, Clone, PartialEq, Eq, Debug, Default) ]
2020-01-24 15:57:01 -05:00
pub enum SkipLeakCheck {
Yes ,
2021-11-22 20:17:53 -05:00
#[ default ]
2020-01-24 15:57:01 -05:00
No ,
}
impl SkipLeakCheck {
fn is_yes ( self ) -> bool {
self = = SkipLeakCheck ::Yes
}
}
2019-02-08 14:53:55 +01:00
/// The mode that trait queries run in.
2020-01-16 18:47:52 -05:00
#[ derive(Copy, Clone, PartialEq, Eq, Debug) ]
2018-04-19 02:28:03 -05:00
pub enum TraitQueryMode {
2020-11-27 14:17:25 -05:00
/// Standard/un-canonicalized queries get accurate
/// spans etc. passed in and hence can do reasonable
/// error reporting on their own.
2018-04-19 02:28:03 -05:00
Standard ,
2023-01-03 01:16:10 +00:00
/// Canonical queries get dummy spans and hence
2020-11-27 14:17:25 -05:00
/// must generally propagate errors to
/// pre-canonicalization callsites.
2018-04-19 02:28:03 -05:00
Canonical ,
}
2014-12-07 11:10:48 -05:00
/// Creates predicate obligations from the generic bounds.
2022-10-20 09:39:09 +00:00
#[ instrument(level = " debug " , skip(cause, param_env)) ]
2019-08-25 21:58:59 -07:00
pub fn predicates_for_generics < ' tcx > (
2022-08-16 06:27:22 +00:00
cause : impl Fn ( usize , Span ) -> ObligationCause < ' tcx > ,
2019-08-25 21:58:59 -07:00
param_env : ty ::ParamEnv < ' tcx > ,
2020-04-18 15:09:28 -07:00
generic_bounds : ty ::InstantiatedPredicates < ' tcx > ,
) -> impl Iterator < Item = PredicateObligation < ' tcx > > {
2023-06-22 18:17:13 +00:00
generic_bounds . into_iter ( ) . enumerate ( ) . map ( move | ( idx , ( clause , span ) ) | Obligation {
2023-01-03 03:32:59 +00:00
cause : cause ( idx , span ) ,
recursion_depth : 0 ,
param_env ,
2023-06-22 18:17:13 +00:00
predicate : clause . as_predicate ( ) ,
2023-01-03 03:32:59 +00:00
} )
2014-09-12 10:53:35 -04:00
}
2014-12-18 09:26:10 -05:00
/// Determines whether the type `ty` is known to meet `bound` and
/// returns true if so. Returns false if `ty` either does not meet
2024-04-06 23:29:59 +00:00
/// `bound` or is not known to meet bound (note that this is
/// conservative towards *no impl*, which is the opposite of the
/// `evaluate` methods).
2022-09-09 13:01:06 -05:00
pub fn type_known_to_meet_bound_modulo_regions < ' tcx > (
infcx : & InferCtxt < ' tcx > ,
2018-09-20 13:56:11 -04:00
param_env : ty ::ParamEnv < ' tcx > ,
ty : Ty < ' tcx > ,
def_id : DefId ,
) -> bool {
2023-04-26 11:48:17 +00:00
let trait_ref = ty ::TraitRef ::new ( infcx . tcx , def_id , [ ty ] ) ;
2024-04-06 23:29:59 +00:00
pred_known_to_hold_modulo_regions ( infcx , param_env , trait_ref )
}
/// FIXME(@lcnr): this function doesn't seem right and shouldn't exist?
///
/// Ping me on zulip if you want to use this method and need help with finding
/// an appropriate replacement.
#[ instrument(level = " debug " , skip(infcx, param_env, pred), ret) ]
fn pred_known_to_hold_modulo_regions < ' tcx > (
infcx : & InferCtxt < ' tcx > ,
param_env : ty ::ParamEnv < ' tcx > ,
2024-05-15 21:57:41 -04:00
pred : impl Upcast < TyCtxt < ' tcx > , ty ::Predicate < ' tcx > > ,
2024-04-06 23:29:59 +00:00
) -> bool {
let obligation = Obligation ::new ( infcx . tcx , ObligationCause ::dummy ( ) , param_env , pred ) ;
let result = infcx . evaluate_obligation_no_overflow ( & obligation ) ;
debug! ( ? result ) ;
if result . must_apply_modulo_regions ( ) {
true
} else if result . may_apply ( ) {
// Sometimes obligations are ambiguous because the recursive evaluator
// is not smart enough, so we fall back to fulfillment when we're not certain
// that an obligation holds or not. Even still, we must make sure that
// the we do no inference in the process of checking this obligation.
let goal = infcx . resolve_vars_if_possible ( ( obligation . predicate , obligation . param_env ) ) ;
infcx . probe ( | _ | {
let ocx = ObligationCtxt ::new ( infcx ) ;
ocx . register_obligation ( obligation ) ;
let errors = ocx . select_all_or_error ( ) ;
match errors . as_slice ( ) {
// Only known to hold if we did no inference.
2024-04-06 02:05:17 -04:00
[ ] = > infcx . resolve_vars_if_possible ( goal ) = = goal ,
2024-04-06 23:29:59 +00:00
errors = > {
debug! ( ? errors ) ;
false
}
}
} )
} else {
false
}
2015-01-02 04:01:30 -05:00
}
2022-06-27 17:18:49 +02:00
#[ instrument(level = " debug " , skip(tcx, elaborated_env)) ]
2019-06-12 00:11:55 +03:00
fn do_normalize_predicates < ' tcx > (
2019-06-14 00:48:52 +03:00
tcx : TyCtxt < ' tcx > ,
2019-06-12 00:11:55 +03:00
cause : ObligationCause < ' tcx > ,
elaborated_env : ty ::ParamEnv < ' tcx > ,
2023-06-22 18:17:13 +00:00
predicates : Vec < ty ::Clause < ' tcx > > ,
) -> Result < Vec < ty ::Clause < ' tcx > > , ErrorGuaranteed > {
2015-02-20 06:21:46 -05:00
let span = cause . span ;
2024-05-24 01:57:06 +01:00
2022-07-20 11:40:15 +02:00
// FIXME. We should really... do something with these region
// obligations. But this call just continues the older
// behavior (i.e., doesn't cause any new bugs), and it would
// take some further refactoring to actually solve them. In
// particular, we would have to handle implied bounds
// properly, and that code is currently largely confined to
// regionck (though I made some efforts to extract it
// out). -nmatsakis
//
// @arielby: In any case, these obligations are checked
// by wfcheck anyway, so I'm not sure we have to check
// them here too, and we will remove this function when
// we move over to lazy normalization *anyway*.
let infcx = tcx . infer_ctxt ( ) . ignoring_regions ( ) . build ( ) ;
2022-07-26 03:24:16 +00:00
let predicates = match fully_normalize ( & infcx , cause , elaborated_env , predicates ) {
Ok ( predicates ) = > predicates ,
Err ( errors ) = > {
2023-08-14 13:09:53 +00:00
let reported = infcx . err_ctxt ( ) . report_fulfillment_errors ( errors ) ;
2022-07-26 03:24:16 +00:00
return Err ( reported ) ;
}
} ;
2016-03-25 05:22:44 +02:00
2023-04-09 17:35:02 -04:00
debug! ( " do_normalize_predicates: normalized predicates = {:?} " , predicates ) ;
2016-03-25 05:22:44 +02:00
2017-12-01 05:07:52 -05:00
// We can use the `elaborated_env` here; the region code only
// cares about declarations like `'a: 'b`.
2020-06-21 12:26:17 +02:00
let outlives_env = OutlivesEnvironment ::new ( elaborated_env ) ;
2022-09-19 22:03:59 -05:00
2022-07-08 10:59:35 +02:00
// FIXME: It's very weird that we ignore region obligations but apparently
// still need to use `resolve_regions` as we need the resolved regions in
// the normalized predicates.
let errors = infcx . resolve_regions ( & outlives_env ) ;
if ! errors . is_empty ( ) {
2023-12-18 22:21:37 +11:00
tcx . dcx ( ) . span_delayed_bug (
2022-09-19 22:03:59 -05:00
span ,
2022-07-08 10:59:35 +02:00
format! ( " failed region resolution while normalizing {elaborated_env:?} : {errors:?} " ) ,
2022-09-19 22:03:59 -05:00
) ;
}
2017-12-01 05:07:52 -05:00
2022-07-08 10:59:35 +02:00
match infcx . fully_resolve ( predicates ) {
Ok ( predicates ) = > Ok ( predicates ) ,
2016-03-25 05:22:44 +02:00
Err ( fixup_err ) = > {
2022-07-08 10:59:35 +02:00
// If we encounter a fixup error, it means that some type
// variable wound up unconstrained. I actually don't know
// if this can happen, and I certainly don't expect it to
// happen often, but if it did happen it probably
// represents a legitimate failure due to some kind of
// unconstrained variable.
2022-09-19 22:03:59 -05:00
//
2022-07-08 10:59:35 +02:00
// @lcnr: Let's still ICE here for now. I want a test case
// for that.
span_bug! (
span ,
" inference variables in normalized parameter environment: {} " ,
fixup_err
) ;
}
2016-03-25 05:22:44 +02:00
}
2018-09-30 20:09:05 +03:00
}
// FIXME: this is gonna need to be removed ...
/// Normalizes the parameter environment, reporting errors if they occur.
2022-06-27 17:18:49 +02:00
#[ instrument(level = " debug " , skip(tcx)) ]
2019-06-12 00:11:55 +03:00
pub fn normalize_param_env_or_error < ' tcx > (
2019-06-14 00:48:52 +03:00
tcx : TyCtxt < ' tcx > ,
2019-06-12 00:11:55 +03:00
unnormalized_env : ty ::ParamEnv < ' tcx > ,
cause : ObligationCause < ' tcx > ,
) -> ty ::ParamEnv < ' tcx > {
2018-09-30 20:09:05 +03:00
// I'm not wild about reporting errors here; I'd prefer to
// have the errors get reported at a defined place (e.g.,
// during typeck). Instead I have all parameter
// environments, in effect, going through this function
// and hence potentially reporting errors. This ensures of
// course that we never forget to normalize (the
// alternative seemed like it would involve a lot of
// manual invocations of this fn -- and then we'd have to
// deal with the errors at each of those sites).
//
// In any case, in practice, typeck constructs all the
// parameter environments once for every fn as it goes,
2021-10-25 15:43:07 -05:00
// and errors will get reported then; so outside of type inference we
2018-09-30 20:09:05 +03:00
// can be sure that no errors should occur.
2023-05-31 02:13:47 +01:00
let mut predicates : Vec < _ > = util ::elaborate (
tcx ,
unnormalized_env . caller_bounds ( ) . into_iter ( ) . map ( | predicate | {
if tcx . features ( ) . generic_const_exprs {
return predicate ;
}
struct ConstNormalizer < ' tcx > ( TyCtxt < ' tcx > ) ;
impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for ConstNormalizer < ' tcx > {
fn interner ( & self ) -> TyCtxt < ' tcx > {
self . 0
}
fn fold_const ( & mut self , c : ty ::Const < ' tcx > ) -> ty ::Const < ' tcx > {
2023-10-31 13:45:26 +00:00
// FIXME(return_type_notation): track binders in this normalizer, as
// `ty::Const::normalize` can only work with properly preserved binders.
if c . has_escaping_bound_vars ( ) {
return ty ::Const ::new_misc_error ( self . 0 , c . ty ( ) ) ;
}
2023-05-31 02:13:47 +01:00
// While it is pretty sus to be evaluating things with an empty param env, it
// should actually be okay since without `feature(generic_const_exprs)` the only
// const arguments that have a non-empty param env are array repeat counts. These
// do not appear in the type system though.
2023-09-12 23:28:25 +02:00
c . normalize ( self . 0 , ty ::ParamEnv ::empty ( ) )
2023-05-31 02:13:47 +01:00
}
}
// This whole normalization step is a hack to work around the fact that
// `normalize_param_env_or_error` is fundamentally broken from using an
// unnormalized param env with a trait solver that expects the param env
// to be normalized.
//
// When normalizing the param env we can end up evaluating obligations
// that have been normalized but can only be proven via a where clause
// which is still in its unnormalized form. example:
//
// Attempting to prove `T: Trait<<u8 as Identity>::Assoc>` in a param env
// with a `T: Trait<<u8 as Identity>::Assoc>` where clause will fail because
// we first normalize obligations before proving them so we end up proving
// `T: Trait<u8>`. Since lazy normalization is not implemented equating `u8`
// with `<u8 as Identity>::Assoc` fails outright so we incorrectly believe that
// we cannot prove `T: Trait<u8>`.
//
// The same thing is true for const generics- attempting to prove
// `T: Trait<ConstKind::Unevaluated(...)>` with the same thing as a where clauses
// will fail. After normalization we may be attempting to prove `T: Trait<4>` with
// the unnormalized where clause `T: Trait<ConstKind::Unevaluated(...)>`. In order
// for the obligation to hold `4` must be equal to `ConstKind::Unevaluated(...)`
// but as we do not have lazy norm implemented, equating the two consts fails outright.
//
// Ideally we would not normalize consts here at all but it is required for backwards
// compatibility. Eventually when lazy norm is implemented this can just be removed.
// We do not normalize types here as there is no backwards compatibility requirement
// for us to do so.
//
2023-12-14 13:11:28 +01:00
// FIXME(-Znext-solver): remove this hack since we have deferred projection equality
2023-05-31 02:13:47 +01:00
predicate . fold_with ( & mut ConstNormalizer ( tcx ) )
} ) ,
)
. collect ( ) ;
2018-09-30 20:09:05 +03:00
2019-12-24 17:38:22 -05:00
debug! ( " normalize_param_env_or_error: elaborated-predicates={:?} " , predicates ) ;
2018-09-30 20:09:05 +03:00
2023-07-27 15:50:42 +00:00
let elaborated_env = ty ::ParamEnv ::new ( tcx . mk_clauses ( & predicates ) , unnormalized_env . reveal ( ) ) ;
2018-09-30 20:09:05 +03:00
// HACK: we are trying to normalize the param-env inside *itself*. The problem is that
// normalization expects its param-env to be already normalized, which means we have
// a circularity.
//
// The way we handle this is by normalizing the param-env inside an unnormalized version
// of the param-env, which means that if the param-env contains unnormalized projections,
// we'll have some normalization failures. This is unfortunate.
//
// Lazy normalization would basically handle this by treating just the
// normalizing-a-trait-ref-requires-itself cycles as evaluation failures.
//
// Inferred outlives bounds can create a lot of `TypeOutlives` predicates for associated
// types, so to make the situation less bad, we normalize all the predicates *but*
// the `TypeOutlives` predicates first inside the unnormalized parameter environment, and
// then we normalize the `TypeOutlives` bounds inside the normalized parameter environment.
//
2023-01-14 17:34:59 +01:00
// This works fairly well because trait matching does not actually care about param-env
2018-09-30 20:09:05 +03:00
// TypeOutlives predicates - these are normally used by regionck.
2019-12-24 17:38:22 -05:00
let outlives_predicates : Vec < _ > = predicates
2023-04-09 00:37:21 +02:00
. extract_if ( | predicate | {
2023-06-22 18:17:13 +00:00
matches! ( predicate . kind ( ) . skip_binder ( ) , ty ::ClauseKind ::TypeOutlives ( .. ) )
2019-12-24 17:38:22 -05:00
} )
. collect ( ) ;
2018-09-30 20:09:05 +03:00
2019-12-24 17:38:22 -05:00
debug! (
" normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?}) " ,
predicates , outlives_predicates
) ;
2022-02-19 00:48:31 +01:00
let Ok ( non_outlives_predicates ) =
do_normalize_predicates ( tcx , cause . clone ( ) , elaborated_env , predicates )
else {
2019-12-24 17:38:22 -05:00
// An unnormalized env is better than nothing.
2022-02-19 00:48:31 +01:00
debug! ( " normalize_param_env_or_error: errored resolving non-outlives predicates " ) ;
return elaborated_env ;
2019-12-24 17:38:22 -05:00
} ;
2016-05-11 04:14:41 +03:00
2018-09-30 20:09:05 +03:00
debug! ( " normalize_param_env_or_error: non-outlives predicates={:?} " , non_outlives_predicates ) ;
// Not sure whether it is better to include the unnormalized TypeOutlives predicates
// here. I believe they should not matter, because we are ignoring TypeOutlives param-env
// predicates here anyway. Keeping them here anyway because it seems safer.
2023-02-17 14:33:08 +11:00
let outlives_env = non_outlives_predicates . iter ( ) . chain ( & outlives_predicates ) . cloned ( ) ;
2023-07-27 15:50:42 +00:00
let outlives_env =
ty ::ParamEnv ::new ( tcx . mk_clauses_from_iter ( outlives_env ) , unnormalized_env . reveal ( ) ) ;
2022-02-19 00:48:31 +01:00
let Ok ( outlives_predicates ) =
do_normalize_predicates ( tcx , cause , outlives_env , outlives_predicates )
else {
2019-12-24 17:38:22 -05:00
// An unnormalized env is better than nothing.
2022-02-19 00:48:31 +01:00
debug! ( " normalize_param_env_or_error: errored resolving outlives predicates " ) ;
return elaborated_env ;
2019-12-24 17:38:22 -05:00
} ;
2018-09-30 20:09:05 +03:00
debug! ( " normalize_param_env_or_error: outlives predicates={:?} " , outlives_predicates ) ;
2015-12-22 19:51:29 -05:00
2018-09-30 20:09:05 +03:00
let mut predicates = non_outlives_predicates ;
predicates . extend ( outlives_predicates ) ;
debug! ( " normalize_param_env_or_error: final predicates={:?} " , predicates ) ;
2023-07-27 15:50:42 +00:00
ty ::ParamEnv ::new ( tcx . mk_clauses ( & predicates ) , unnormalized_env . reveal ( ) )
2015-01-26 14:20:38 -05:00
}
2023-06-30 10:57:17 +02:00
/// Normalize a type and process all resulting obligations, returning any errors.
///
2023-12-14 13:11:28 +01:00
/// FIXME(-Znext-solver): This should be replaced by `At::deeply_normalize`
2023-06-30 10:57:17 +02:00
/// which has the same behavior with the new solver. Because using a separate
/// fulfillment context worsens caching in the old solver, `At::deeply_normalize`
/// is still lazy with the old solver as it otherwise negatively impacts perf.
2022-11-02 00:48:44 +00:00
#[ instrument(skip_all) ]
2022-09-09 13:01:06 -05:00
pub fn fully_normalize < ' tcx , T > (
infcx : & InferCtxt < ' tcx > ,
2017-11-23 23:03:47 +02:00
cause : ObligationCause < ' tcx > ,
param_env : ty ::ParamEnv < ' tcx > ,
2020-10-24 02:21:18 +02:00
value : T ,
2019-06-14 01:32:15 +03:00
) -> Result < T , Vec < FulfillmentError < ' tcx > > >
where
2023-02-22 02:18:40 +00:00
T : TypeFoldable < TyCtxt < ' tcx > > ,
2017-11-23 23:03:47 +02:00
{
2024-06-01 14:51:31 -04:00
let ocx = ObligationCtxt ::new_with_diagnostics ( infcx ) ;
2022-11-02 00:48:44 +00:00
debug! ( ? value ) ;
2022-11-25 18:40:52 +00:00
let normalized_value = ocx . normalize ( & cause , param_env , value ) ;
2022-11-02 00:48:44 +00:00
debug! ( ? normalized_value ) ;
debug! ( " select_all_or_error start " ) ;
let errors = ocx . select_all_or_error ( ) ;
2021-11-08 23:35:23 +08:00
if ! errors . is_empty ( ) {
return Err ( errors ) ;
}
2022-11-02 00:48:44 +00:00
debug! ( " select_all_or_error complete " ) ;
2020-10-24 02:21:18 +02:00
let resolved_value = infcx . resolve_vars_if_possible ( normalized_value ) ;
2022-11-02 00:48:44 +00:00
debug! ( ? resolved_value ) ;
2015-02-13 19:51:43 -05:00
Ok ( resolved_value )
}
2020-06-22 13:22:45 +01:00
/// Normalizes the predicates and checks whether they hold in an empty environment. If this
/// returns true, then either normalize encountered an error or one of the predicates did not
/// hold. Used when creating vtables to check for unsatisfiable methods.
2023-06-22 18:17:13 +00:00
pub fn impossible_predicates < ' tcx > ( tcx : TyCtxt < ' tcx > , predicates : Vec < ty ::Clause < ' tcx > > ) -> bool {
2020-06-22 13:22:45 +01:00
debug! ( " impossible_predicates(predicates={:?}) " , predicates ) ;
2016-09-19 12:47:47 +03:00
2017-06-21 14:50:43 +03:00
let infcx = tcx . infer_ctxt ( ) . build ( ) ;
2018-02-10 13:18:02 -05:00
let param_env = ty ::ParamEnv ::reveal_all ( ) ;
2022-07-26 04:01:34 +00:00
let ocx = ObligationCtxt ::new ( & infcx ) ;
2022-11-25 18:40:52 +00:00
let predicates = ocx . normalize ( & ObligationCause ::dummy ( ) , param_env , predicates ) ;
2016-09-19 12:47:47 +03:00
for predicate in predicates {
2022-11-09 10:49:28 +00:00
let obligation = Obligation ::new ( tcx , ObligationCause ::dummy ( ) , param_env , predicate ) ;
2022-07-26 04:01:34 +00:00
ocx . register_obligation ( obligation ) ;
2016-09-19 12:47:47 +03:00
}
2022-07-26 04:01:34 +00:00
let errors = ocx . select_all_or_error ( ) ;
2021-11-08 23:35:23 +08:00
let result = ! errors . is_empty ( ) ;
2020-10-24 02:21:18 +02:00
debug! ( " impossible_predicates = {:?} " , result ) ;
2017-06-21 14:50:43 +03:00
result
2016-09-19 12:47:47 +03:00
}
2024-02-12 15:39:32 +09:00
fn instantiate_and_check_impossible_predicates < ' tcx > (
2019-06-14 00:48:52 +03:00
tcx : TyCtxt < ' tcx > ,
2023-07-11 22:35:29 +01:00
key : ( DefId , GenericArgsRef < ' tcx > ) ,
2019-06-12 00:11:55 +03:00
) -> bool {
2024-02-12 15:39:32 +09:00
debug! ( " instantiate_and_check_impossible_predicates(key={:?}) " , key ) ;
2017-12-27 12:32:44 -05:00
2020-06-22 13:22:45 +01:00
let mut predicates = tcx . predicates_of ( key . 0 ) . instantiate ( tcx , key . 1 ) . predicates ;
2022-05-07 10:24:45 +02:00
// Specifically check trait fulfillment to avoid an error when trying to resolve
// associated items.
if let Some ( trait_def_id ) = tcx . trait_of_item ( key . 0 ) {
let trait_ref = ty ::TraitRef ::from_method ( tcx , trait_def_id , key . 1 ) ;
2024-05-15 12:52:12 -04:00
predicates . push ( trait_ref . upcast ( tcx ) ) ;
2022-05-07 10:24:45 +02:00
}
2023-04-27 07:52:17 +01:00
predicates . retain ( | predicate | ! predicate . has_param ( ) ) ;
2020-06-22 13:22:45 +01:00
let result = impossible_predicates ( tcx , predicates ) ;
2017-12-27 12:32:44 -05:00
2024-02-12 15:39:32 +09:00
debug! ( " instantiate_and_check_impossible_predicates(key={:?}) = {:?} " , key , result ) ;
2017-12-27 12:32:44 -05:00
result
}
2023-07-22 12:20:17 +02:00
/// Checks whether a trait's associated item is impossible to reference on a given impl.
2022-08-07 05:47:32 +00:00
///
/// This only considers predicates that reference the impl's generics, and not
/// those that reference the method's generics.
2023-07-22 12:20:17 +02:00
fn is_impossible_associated_item (
tcx : TyCtxt < '_ > ,
( impl_def_id , trait_item_def_id ) : ( DefId , DefId ) ,
) -> bool {
2022-08-07 05:47:32 +00:00
struct ReferencesOnlyParentGenerics < ' tcx > {
tcx : TyCtxt < ' tcx > ,
generics : & ' tcx ty ::Generics ,
trait_item_def_id : DefId ,
}
2023-02-22 02:18:40 +00:00
impl < ' tcx > ty ::TypeVisitor < TyCtxt < ' tcx > > for ReferencesOnlyParentGenerics < ' tcx > {
2024-02-24 17:22:28 -05:00
type Result = ControlFlow < ( ) > ;
fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> Self ::Result {
2022-08-07 05:47:32 +00:00
// If this is a parameter from the trait item's own generics, then bail
2024-04-19 21:09:51 -04:00
if let ty ::Param ( param ) = * t . kind ( )
2022-08-07 05:47:32 +00:00
& & let param_def_id = self . generics . type_param ( param , self . tcx ) . def_id
& & self . tcx . parent ( param_def_id ) = = self . trait_item_def_id
{
2023-01-17 23:17:13 -08:00
return ControlFlow ::Break ( ( ) ) ;
2022-08-07 05:47:32 +00:00
}
t . super_visit_with ( self )
}
2024-02-24 17:22:28 -05:00
fn visit_region ( & mut self , r : ty ::Region < ' tcx > ) -> Self ::Result {
2023-11-14 13:13:27 +00:00
if let ty ::ReEarlyParam ( param ) = r . kind ( )
2024-04-19 21:09:51 -04:00
& & let param_def_id = self . generics . region_param ( param , self . tcx ) . def_id
2022-08-07 05:47:32 +00:00
& & self . tcx . parent ( param_def_id ) = = self . trait_item_def_id
{
2023-01-17 23:17:13 -08:00
return ControlFlow ::Break ( ( ) ) ;
2022-08-07 05:47:32 +00:00
}
2023-04-15 09:31:11 +10:00
ControlFlow ::Continue ( ( ) )
2022-08-07 05:47:32 +00:00
}
2024-02-24 17:22:28 -05:00
fn visit_const ( & mut self , ct : ty ::Const < ' tcx > ) -> Self ::Result {
2022-08-07 05:47:32 +00:00
if let ty ::ConstKind ::Param ( param ) = ct . kind ( )
2024-04-19 21:09:51 -04:00
& & let param_def_id = self . generics . const_param ( param , self . tcx ) . def_id
2022-08-07 05:47:32 +00:00
& & self . tcx . parent ( param_def_id ) = = self . trait_item_def_id
{
2023-01-17 23:17:13 -08:00
return ControlFlow ::Break ( ( ) ) ;
2022-08-07 05:47:32 +00:00
}
ct . super_visit_with ( self )
}
}
let generics = tcx . generics_of ( trait_item_def_id ) ;
let predicates = tcx . predicates_of ( trait_item_def_id ) ;
2023-01-10 14:22:52 -07:00
let impl_trait_ref = tcx
2023-01-10 14:57:22 -07:00
. impl_trait_ref ( impl_def_id )
2023-01-10 14:22:52 -07:00
. expect ( " expected impl to correspond to trait " )
2023-07-11 22:35:29 +01:00
. instantiate_identity ( ) ;
2022-08-07 05:47:32 +00:00
let param_env = tcx . param_env ( impl_def_id ) ;
let mut visitor = ReferencesOnlyParentGenerics { tcx , generics , trait_item_def_id } ;
let predicates_for_trait = predicates . predicates . iter ( ) . filter_map ( | ( pred , span ) | {
2023-02-15 11:43:41 +00:00
pred . visit_with ( & mut visitor ) . is_continue ( ) . then ( | | {
Obligation ::new (
2022-11-09 10:49:28 +00:00
tcx ,
2022-08-07 05:47:32 +00:00
ObligationCause ::dummy_with_span ( * span ) ,
param_env ,
2023-07-11 22:35:29 +01:00
ty ::EarlyBinder ::bind ( * pred ) . instantiate ( tcx , impl_trait_ref . args ) ,
2023-02-15 11:43:41 +00:00
)
} )
2022-08-07 05:47:32 +00:00
} ) ;
let infcx = tcx . infer_ctxt ( ) . ignoring_regions ( ) . build ( ) ;
2022-08-18 01:12:46 +00:00
for obligation in predicates_for_trait {
// Ignore overflow error, to be conservative.
if let Ok ( result ) = infcx . evaluate_obligation ( & obligation )
& & ! result . may_apply ( )
{
return true ;
}
2022-09-19 22:03:59 -05:00
}
2022-08-18 01:12:46 +00:00
false
2022-08-07 05:47:32 +00:00
}
2023-05-15 06:24:45 +02:00
pub fn provide ( providers : & mut Providers ) {
2020-02-10 19:55:49 +01:00
object_safety ::provide ( providers ) ;
2022-12-08 04:51:46 +00:00
vtable ::provide ( providers ) ;
2023-05-15 06:24:45 +02:00
* providers = Providers {
2017-05-11 16:01:19 +02:00
specialization_graph_of : specialize ::specialization_graph_provider ,
2017-08-29 09:25:25 -07:00
specializes : specialize ::specializes ,
2024-02-12 15:39:32 +09:00
instantiate_and_check_impossible_predicates ,
2023-07-22 12:20:17 +02:00
is_impossible_associated_item ,
2017-05-11 16:01:19 +02:00
.. * providers
} ;
}