@@ -147,83 +147,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
147
147
ecx : & mut EvalCtxt < ' _ , ' tcx > ,
148
148
goal : Goal < ' tcx , Self > ,
149
149
) -> 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;
227
152
}
228
153
229
154
ecx. probe_and_evaluate_goal_for_constituent_tys (
@@ -647,6 +572,97 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
647
572
}
648
573
649
574
impl < ' 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
+
650
666
/// Convenience function for traits that are structural, i.e. that only
651
667
/// have nested subgoals that only change the self type. Unlike other
652
668
/// evaluate-like helpers, this does a probe, so it doesn't need to be
0 commit comments