11use rustc_errors:: ErrorGuaranteed ;
2- use rustc_hir:: LangItem ;
32use rustc_hir:: def_id:: DefId ;
3+ use rustc_hir:: { Constness , LangItem } ;
44use rustc_infer:: infer:: TyCtxtInferExt ;
5+ use rustc_infer:: traits:: {
6+ ImplSource , Obligation , ObligationCause , ScrubbedTraitError , SelectionError ,
7+ } ;
58use rustc_middle:: bug;
69use rustc_middle:: query:: Providers ;
710use rustc_middle:: traits:: { BuiltinImplSource , CodegenObligationError } ;
@@ -10,17 +13,19 @@ use rustc_middle::ty::{
1013 Unnormalized ,
1114} ;
1215use rustc_span:: sym;
13- use rustc_trait_selection:: traits;
16+ use rustc_trait_selection:: error_reporting:: InferCtxtErrorExt as _;
17+ use rustc_trait_selection:: solve:: InferCtxtSelectExt as _;
18+ use rustc_trait_selection:: traits:: { self , ObligationCtxt } ;
1419use tracing:: debug;
1520use traits:: translate_args;
1621
1722use crate :: errors:: UnexpectedFnPtrAssociatedItem ;
1823
1924fn resolve_instance_raw < ' tcx > (
2025 tcx : TyCtxt < ' tcx > ,
21- key : ty:: PseudoCanonicalInput < ' tcx , ( DefId , GenericArgsRef < ' tcx > ) > ,
26+ key : ty:: PseudoCanonicalInput < ' tcx , ( DefId , GenericArgsRef < ' tcx > , Constness ) > ,
2227) -> Result < Option < Instance < ' tcx > > , ErrorGuaranteed > {
23- let PseudoCanonicalInput { typing_env, value : ( def_id, args) } = key;
28+ let PseudoCanonicalInput { typing_env, value : ( def_id, args, constness ) } = key;
2429
2530 let result = if let Some ( trait_def_id) = tcx. trait_of_assoc ( def_id) {
2631 debug ! ( " => associated item, attempting to find impl in typing_env {:#?}" , typing_env) ;
@@ -30,6 +35,7 @@ fn resolve_instance_raw<'tcx>(
3035 typing_env,
3136 trait_def_id,
3237 tcx. normalize_erasing_regions ( typing_env, Unnormalized :: new_wip ( args) ) ,
38+ constness,
3339 )
3440 } else {
3541 let def = if tcx. intrinsic ( def_id) . is_some ( ) {
@@ -101,24 +107,88 @@ fn resolve_instance_raw<'tcx>(
101107 result
102108}
103109
110+ #[ tracing:: instrument( level = "debug" , skip( tcx) ) ]
104111fn resolve_associated_item < ' tcx > (
105112 tcx : TyCtxt < ' tcx > ,
106113 trait_item_id : DefId ,
107114 typing_env : ty:: TypingEnv < ' tcx > ,
108115 trait_id : DefId ,
109116 rcvr_args : GenericArgsRef < ' tcx > ,
117+ constness : Constness ,
110118) -> Result < Option < Instance < ' tcx > > , ErrorGuaranteed > {
111- debug ! ( ?trait_item_id, ?typing_env, ?trait_id, ?rcvr_args, "resolve_associated_item" ) ;
112-
113119 let trait_ref = ty:: TraitRef :: from_assoc ( tcx, trait_id, rcvr_args) ;
114120
115121 let input = typing_env. as_query_input ( trait_ref) ;
116- let vtbl = match tcx. codegen_select_candidate ( input) {
117- Ok ( vtbl) => vtbl,
118- Err ( CodegenObligationError :: Ambiguity | CodegenObligationError :: Unimplemented ) => {
122+ let vtbl = if constness == Constness :: Const && tcx. next_trait_solver_globally ( ) {
123+ let ( infcx, param_env) =
124+ tcx. infer_ctxt ( ) . ignoring_regions ( ) . build_with_typing_env ( typing_env) ;
125+
126+ let obligation_cause = ObligationCause :: dummy ( ) ;
127+ let host_predicate =
128+ ty:: HostEffectPredicate { trait_ref, constness : ty:: BoundConstness :: Const } ;
129+ let obligation = Obligation :: new ( tcx, obligation_cause, param_env, host_predicate) ;
130+
131+ let selection = match infcx. select_host_effect_predicate_in_new_trait_solver ( & obligation) {
132+ Ok ( Some ( selection) ) => selection,
133+ Ok ( None ) => return Ok ( None ) ,
134+ Err ( SelectionError :: Unimplemented ) => return Ok ( None ) ,
135+ Err ( e) => {
136+ bug ! ( "Encountered error `{:?}` selecting `{:?}` during codegen" , e, host_predicate)
137+ }
138+ } ;
139+
140+ debug ! ( ?selection) ;
141+
142+ // Currently, we use a fulfillment context to completely resolve
143+ // all nested obligations. This is because they can inform the
144+ // inference of the impl's type parameters.
145+ let ocx = ObligationCtxt :: new ( & infcx) ;
146+ let impl_source = selection. map ( |obligation| {
147+ ocx. register_obligation ( obligation) ;
148+ } ) ;
149+
150+ // In principle, we only need to do this so long as `impl_source`
151+ // contains unbound type parameters. It could be a slight
152+ // optimization to stop iterating early.
153+ let errors = ocx. evaluate_obligations_error_on_ambiguity ( ) ;
154+ if !errors. is_empty ( ) {
155+ // `rustc_monomorphize::collector` assumes there are no type errors.
156+ // Cycle errors are the only post-monomorphization errors possible; emit them now so
157+ // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
158+ for err in errors {
159+ if let ScrubbedTraitError :: Cycle ( cycle) = err {
160+ infcx. err_ctxt ( ) . report_overflow_obligation_cycle ( & cycle) ;
161+ }
162+ }
119163 return Ok ( None ) ;
120164 }
121- Err ( CodegenObligationError :: UnconstrainedParam ( guar) ) => return Err ( guar) ,
165+
166+ let impl_source = infcx. resolve_vars_if_possible ( impl_source) ;
167+ let impl_source = tcx. erase_and_anonymize_regions ( impl_source) ;
168+ if impl_source. has_non_region_infer ( ) {
169+ // Unused generic types or consts on an impl get replaced with inference vars,
170+ // but never resolved, causing the return value of a query to contain inference
171+ // vars. We do not have a concept for this and will in fact ICE in stable hashing
172+ // of the return value. So bail out instead.
173+ let guar = match impl_source {
174+ ImplSource :: UserDefined ( impl_) => tcx. dcx ( ) . span_delayed_bug (
175+ tcx. def_span ( impl_. impl_def_id ) ,
176+ "this impl has unconstrained generic parameters" ,
177+ ) ,
178+ _ => unreachable ! ( ) ,
179+ } ;
180+ return Err ( guar) ;
181+ }
182+
183+ & * tcx. arena . alloc ( impl_source)
184+ } else {
185+ match tcx. codegen_select_candidate ( input) {
186+ Ok ( vtbl) => vtbl,
187+ Err ( CodegenObligationError :: Ambiguity | CodegenObligationError :: Unimplemented ) => {
188+ return Ok ( None ) ;
189+ }
190+ Err ( CodegenObligationError :: UnconstrainedParam ( guar) ) => return Err ( guar) ,
191+ }
122192 } ;
123193
124194 // Now that we know which impl is being used, we can dispatch to
0 commit comments