@@ -5,7 +5,7 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt;
55use rustc_type_ir:: inherent:: * ;
66use rustc_type_ir:: lang_items:: SolverTraitLangItem ;
77use rustc_type_ir:: solve:: {
8- AliasBoundKind , CandidatePreferenceMode , CanonicalResponse , MaybeInfo ,
8+ AliasBoundKind , CandidatePreferenceMode , CanonicalResponse , ExternalConstraintsData , MaybeInfo ,
99 NoSolutionOrRerunNonErased , OpaqueTypesJank , QueryResultOrRerunNonErased , RerunNonErased ,
1010 RerunReason , RerunResultExt , SizedTraitKind ,
1111} ;
@@ -236,19 +236,11 @@ where
236236 // when merging candidates anyways.
237237 //
238238 // See tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs.
239- if let ty:: Alias ( is_rigid, ty:: AliasTy { kind : ty:: Opaque { def_id } , .. } ) =
239+ if let ty:: Alias ( is_rigid, ty:: AliasTy { kind : ty:: Opaque { def_id } , args , .. } ) =
240240 goal. predicate . self_ty ( ) . kind ( )
241241 {
242242 debug_assert ! ( is_rigid == ty:: IsRigid :: Yes ) ;
243-
244- for item_bound in cx. item_self_bounds ( def_id. into ( ) ) . skip_binder ( ) {
245- if item_bound
246- . as_trait_clause ( )
247- . is_some_and ( |b| b. def_id ( ) == goal. predicate . def_id ( ) )
248- {
249- return Err ( NoSolution . into ( ) ) ;
250- }
251- }
243+ return ecx. consider_auto_trait_candidate_for_opaque_ty ( goal, def_id, args) ;
252244 }
253245
254246 // We need to make sure to stall any coroutines we are inferring to avoid query cycles.
@@ -1289,6 +1281,77 @@ where
12891281 . enter ( |ecx| ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes ) )
12901282 }
12911283
1284+ fn consider_auto_trait_candidate_for_opaque_ty (
1285+ & mut self ,
1286+ goal : Goal < I , TraitClause < I > > ,
1287+ def_id : I :: OpaqueTyId ,
1288+ args : I :: GenericArgs ,
1289+ ) -> Result < Candidate < I > , NoSolutionOrRerunNonErased > {
1290+ let cx = self . cx ( ) ;
1291+ let source = CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Misc ) ;
1292+
1293+ for item_bound in cx. item_self_bounds ( def_id. into ( ) ) . skip_binder ( ) {
1294+ if item_bound. as_trait_clause ( ) . is_some_and ( |b| b. def_id ( ) == goal. predicate . def_id ( ) ) {
1295+ return Err ( NoSolution . into ( ) ) ;
1296+ }
1297+ }
1298+
1299+ let candidate = self . probe_trait_candidate ( source) . enter ( |ecx| {
1300+ let hidden_ty = cx. type_of ( def_id. into ( ) ) . instantiate ( cx, args) . skip_norm_wip ( ) ;
1301+ ecx. add_goal (
1302+ GoalSource :: ImplWhereBound ,
1303+ goal. with ( cx, goal. predicate . with_replaced_self_ty ( cx, hidden_ty) ) ,
1304+ ) ?;
1305+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
1306+ } ) ?;
1307+
1308+ // Proving an auto trait for the hidden type must not constrain inference
1309+ // variables, as that would leak the hidden type itself.
1310+ if !candidate. result . value . var_values . is_identity_modulo_regions ( ) {
1311+ return self . forced_ambiguity ( MaybeInfo :: AMBIGUOUS ) ;
1312+ }
1313+
1314+ let ExternalConstraintsData {
1315+ region_constraints : _,
1316+ ref opaque_types,
1317+ ref normalization_nested_goals,
1318+ } = * candidate. result . value . external_constraints ;
1319+ debug_assert ! ( normalization_nested_goals. is_empty( ) ) ;
1320+
1321+ // New defining uses may leak an opaque's hidden type into the caller's
1322+ // inference state. This is safe after typeck, where hidden types are already
1323+ // fixed and only regions are inferred, but not during typeck while hidden
1324+ // types may still contain inference variables.
1325+ if !opaque_types. is_empty ( ) {
1326+ let typing_mode = self . typing_mode ( ) ;
1327+
1328+ match typing_mode {
1329+ // We're inferring regions of opaque types, but
1330+ // the type itself is already fully known, no way
1331+ // to leak the hidden type.
1332+ TypingMode :: PostTypeckUntilBorrowck { .. } => { }
1333+ // We're inferring the hidden type of opaques, could
1334+ // leak types through it.
1335+ TypingMode :: Typeck { .. } => {
1336+ return self . forced_ambiguity ( MaybeInfo :: AMBIGUOUS ) ;
1337+ }
1338+ // we never add new uses to the opaque type storage
1339+ TypingMode :: Coherence
1340+ | TypingMode :: PostBorrowck { .. }
1341+ | TypingMode :: Reflection
1342+ | TypingMode :: PostAnalysis
1343+ | TypingMode :: Codegen
1344+ | TypingMode :: ErasedNotCoherence ( MayBeErased ) => {
1345+ unreachable ! (
1346+ "we never add new uses to opaque types in typing mode {typing_mode:?}"
1347+ ) ;
1348+ }
1349+ }
1350+ }
1351+
1352+ Ok ( candidate)
1353+ }
1354+
12921355 // Return `Some` if there is an impl (built-in or user provided) that may
12931356 // hold for the self type of the goal, which for coherence and soundness
12941357 // purposes must disqualify the built-in auto impl assembled by considering
0 commit comments