@@ -147,83 +147,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
147147 ecx : & mut EvalCtxt < ' _ , ' tcx > ,
148148 goal : Goal < ' tcx , Self > ,
149149 ) -> QueryResult < ' tcx > {
150- let self_ty = goal. predicate . self_ty ( ) ;
151- match * self_ty. kind ( ) {
152- // Stall int and float vars until they are resolved to a concrete
153- // numerical type. That's because the check for impls below treats
154- // int vars as matching any impl. Even if we filtered such impls,
155- // we probably don't want to treat an `impl !AutoTrait for i32` as
156- // disqualifying the built-in auto impl for `i64: AutoTrait` either.
157- ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) ) => {
158- return ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS ) ;
159- }
160-
161- // These types cannot be structurally decomposed into constitutent
162- // types, and therefore have no builtin impl.
163- ty:: Dynamic ( ..)
164- | ty:: Param ( ..)
165- | ty:: Foreign ( ..)
166- | ty:: Alias ( ty:: Projection , ..)
167- | ty:: Placeholder ( ..) => return Err ( NoSolution ) ,
168-
169- ty:: Infer ( _) | ty:: Bound ( _, _) => bug ! ( "unexpected type `{self_ty}`" ) ,
170-
171- // Generators have one special built-in candidate, `Unpin`, which
172- // takes precedence over the structural auto trait candidate being
173- // assembled.
174- ty:: Generator ( _, _, movability)
175- if Some ( goal. predicate . def_id ( ) ) == ecx. tcx ( ) . lang_items ( ) . unpin_trait ( ) =>
176- {
177- match movability {
178- Movability :: Static => {
179- return Err ( NoSolution ) ;
180- }
181- Movability :: Movable => {
182- return ecx
183- . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes ) ;
184- }
185- }
186- }
187-
188- // For rigid types, we only register a builtin auto implementation
189- // if there is no implementation that could ever apply to the self
190- // type.
191- //
192- // This differs from the current stable behavior and fixes #84857.
193- // Due to breakage found via crater, we currently instead lint
194- // patterns which can be used to exploit this unsoundness on stable,
195- // see #93367 for more details.
196- ty:: Bool
197- | ty:: Char
198- | ty:: Int ( _)
199- | ty:: Uint ( _)
200- | ty:: Float ( _)
201- | ty:: Str
202- | ty:: Array ( _, _)
203- | ty:: Slice ( _)
204- | ty:: RawPtr ( _)
205- | ty:: Ref ( _, _, _)
206- | ty:: FnDef ( _, _)
207- | ty:: FnPtr ( _)
208- | ty:: Closure ( _, _)
209- | ty:: Generator ( _, _, _)
210- | ty:: GeneratorWitness ( _)
211- | ty:: GeneratorWitnessMIR ( _, _)
212- | ty:: Never
213- | ty:: Tuple ( _)
214- | ty:: Error ( _)
215- | ty:: Adt ( _, _)
216- | ty:: Alias ( ty:: Opaque , _) => {
217- if let Some ( def_id) = ecx. tcx ( ) . find_map_relevant_impl (
218- goal. predicate . def_id ( ) ,
219- goal. predicate . self_ty ( ) ,
220- TreatProjections :: NextSolverLookup ,
221- Some ,
222- ) {
223- debug ! ( ?def_id, ?goal, "disqualified auto-trait implementation" ) ;
224- return Err ( NoSolution ) ;
225- }
226- }
150+ if let Some ( result) = ecx. disqualify_auto_trait_candidate_due_to_possible_impl ( goal) {
151+ return result;
227152 }
228153
229154 ecx. probe_and_evaluate_goal_for_constituent_tys (
@@ -647,6 +572,97 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
647572}
648573
649574impl < ' tcx > EvalCtxt < ' _ , ' tcx > {
575+ // Return `Some` if there is an impl (built-in or user provided) that may
576+ // hold for the self type of the goal, which for coherence and soundness
577+ // purposes must disqualify the built-in auto impl assembled by considering
578+ // the type's constituent types.
579+ fn disqualify_auto_trait_candidate_due_to_possible_impl (
580+ & mut self ,
581+ goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
582+ ) -> Option < QueryResult < ' tcx > > {
583+ let self_ty = goal. predicate . self_ty ( ) ;
584+ match * self_ty. kind ( ) {
585+ // Stall int and float vars until they are resolved to a concrete
586+ // numerical type. That's because the check for impls below treats
587+ // int vars as matching any impl. Even if we filtered such impls,
588+ // we probably don't want to treat an `impl !AutoTrait for i32` as
589+ // disqualifying the built-in auto impl for `i64: AutoTrait` either.
590+ ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) ) => {
591+ Some ( self . evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS ) )
592+ }
593+
594+ // These types cannot be structurally decomposed into constitutent
595+ // types, and therefore have no built-in auto impl.
596+ ty:: Dynamic ( ..)
597+ | ty:: Param ( ..)
598+ | ty:: Foreign ( ..)
599+ | ty:: Alias ( ty:: Projection , ..)
600+ | ty:: Placeholder ( ..) => Some ( Err ( NoSolution ) ) ,
601+
602+ ty:: Infer ( _) | ty:: Bound ( _, _) => bug ! ( "unexpected type `{self_ty}`" ) ,
603+
604+ // Generators have one special built-in candidate, `Unpin`, which
605+ // takes precedence over the structural auto trait candidate being
606+ // assembled.
607+ ty:: Generator ( _, _, movability)
608+ if Some ( goal. predicate . def_id ( ) ) == self . tcx ( ) . lang_items ( ) . unpin_trait ( ) =>
609+ {
610+ match movability {
611+ Movability :: Static => Some ( Err ( NoSolution ) ) ,
612+ Movability :: Movable => {
613+ Some ( self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes ) )
614+ }
615+ }
616+ }
617+
618+ // For rigid types, any possible implementation that could apply to
619+ // the type (even if after unification and processing nested goals
620+ // it does not hold) will disqualify the built-in auto impl.
621+ //
622+ // This differs from the current stable behavior and fixes #84857.
623+ // Due to breakage found via crater, we currently instead lint
624+ // patterns which can be used to exploit this unsoundness on stable,
625+ // see #93367 for more details.
626+ ty:: Bool
627+ | ty:: Char
628+ | ty:: Int ( _)
629+ | ty:: Uint ( _)
630+ | ty:: Float ( _)
631+ | ty:: Str
632+ | ty:: Array ( _, _)
633+ | ty:: Slice ( _)
634+ | ty:: RawPtr ( _)
635+ | ty:: Ref ( _, _, _)
636+ | ty:: FnDef ( _, _)
637+ | ty:: FnPtr ( _)
638+ | ty:: Closure ( _, _)
639+ | ty:: Generator ( _, _, _)
640+ | ty:: GeneratorWitness ( _)
641+ | ty:: GeneratorWitnessMIR ( _, _)
642+ | ty:: Never
643+ | ty:: Tuple ( _)
644+ | ty:: Adt ( _, _)
645+ // FIXME: Handling opaques here is kinda sus. Especially because we
646+ // simplify them to PlaceholderSimplifiedType.
647+ | ty:: Alias ( ty:: Opaque , _) => {
648+ if let Some ( def_id) = self . tcx ( ) . find_map_relevant_impl (
649+ goal. predicate . def_id ( ) ,
650+ goal. predicate . self_ty ( ) ,
651+ TreatProjections :: NextSolverLookup ,
652+ Some ,
653+ ) {
654+ debug ! ( ?def_id, ?goal, "disqualified auto-trait implementation" ) ;
655+ // No need to actually consider the candidate here,
656+ // since we do that in `consider_impl_candidate`.
657+ return Some ( Err ( NoSolution ) ) ;
658+ } else {
659+ None
660+ }
661+ }
662+ ty:: Error ( _) => None ,
663+ }
664+ }
665+
650666 /// Convenience function for traits that are structural, i.e. that only
651667 /// have nested subgoals that only change the self type. Unlike other
652668 /// evaluate-like helpers, this does a probe, so it doesn't need to be
0 commit comments