@@ -6,7 +6,6 @@ use rustc_hir::def_id::DefId;
6
6
use rustc_hir:: { LangItem , Movability } ;
7
7
use rustc_infer:: traits:: query:: NoSolution ;
8
8
use rustc_infer:: traits:: util:: supertraits;
9
- use rustc_middle:: traits:: solve:: inspect:: CandidateKind ;
10
9
use rustc_middle:: traits:: solve:: { CanonicalResponse , Certainty , Goal , QueryResult } ;
11
10
use rustc_middle:: ty:: fast_reject:: { DeepRejectCtxt , TreatParams , TreatProjections } ;
12
11
use rustc_middle:: ty:: { self , ToPredicate , Ty , TyCtxt } ;
@@ -62,7 +61,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
62
61
} ,
63
62
} ;
64
63
65
- ecx. probe ( |r| CandidateKind :: Candidate { name : "impl" . into ( ) , result : * r } ) . enter ( |ecx| {
64
+ ecx. probe_candidate ( "impl" ) . enter ( |ecx| {
66
65
let impl_substs = ecx. fresh_substs_for_item ( impl_def_id) ;
67
66
let impl_trait_ref = impl_trait_ref. subst ( tcx, impl_substs) ;
68
67
@@ -90,16 +89,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
90
89
&& trait_clause. polarity ( ) == goal. predicate . polarity
91
90
{
92
91
// FIXME: Constness
93
- ecx. probe ( |r| CandidateKind :: Candidate { name : "assumption" . into ( ) , result : * r } )
94
- . enter ( |ecx| {
95
- let assumption_trait_pred = ecx. instantiate_binder_with_infer ( trait_clause) ;
96
- ecx. eq (
97
- goal. param_env ,
98
- goal. predicate . trait_ref ,
99
- assumption_trait_pred. trait_ref ,
100
- ) ?;
101
- then ( ecx)
102
- } )
92
+ ecx. probe_candidate ( "assumption" ) . enter ( |ecx| {
93
+ let assumption_trait_pred = ecx. instantiate_binder_with_infer ( trait_clause) ;
94
+ ecx. eq (
95
+ goal. param_env ,
96
+ goal. predicate . trait_ref ,
97
+ assumption_trait_pred. trait_ref ,
98
+ ) ?;
99
+ then ( ecx)
100
+ } )
103
101
} else {
104
102
Err ( NoSolution )
105
103
}
@@ -136,15 +134,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
136
134
137
135
let tcx = ecx. tcx ( ) ;
138
136
139
- ecx. probe ( |r| CandidateKind :: Candidate { name : "trait alias" . into ( ) , result : * r } ) . enter (
140
- |ecx| {
141
- let nested_obligations = tcx
142
- . predicates_of ( goal. predicate . def_id ( ) )
143
- . instantiate ( tcx, goal. predicate . trait_ref . substs ) ;
144
- ecx. add_goals ( nested_obligations. predicates . into_iter ( ) . map ( |p| goal. with ( tcx, p) ) ) ;
145
- ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
146
- } ,
147
- )
137
+ ecx. probe_candidate ( "trait alias" ) . enter ( |ecx| {
138
+ let nested_obligations = tcx
139
+ . predicates_of ( goal. predicate . def_id ( ) )
140
+ . instantiate ( tcx, goal. predicate . trait_ref . substs ) ;
141
+ ecx. add_goals ( nested_obligations. predicates . into_iter ( ) . map ( |p| goal. with ( tcx, p) ) ) ;
142
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
143
+ } )
148
144
}
149
145
150
146
fn consider_builtin_sized_candidate (
@@ -350,115 +346,109 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
350
346
if b_ty. is_ty_var ( ) {
351
347
return ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS ) ;
352
348
}
353
- ecx. probe ( |r| CandidateKind :: Candidate { name : "builtin unsize" . into ( ) , result : * r } ) . enter (
354
- |ecx| {
355
- match ( a_ty. kind ( ) , b_ty. kind ( ) ) {
356
- // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`
357
- ( & ty:: Dynamic ( _, _, ty:: Dyn ) , & ty:: Dynamic ( _, _, ty:: Dyn ) ) => {
358
- // Dyn upcasting is handled separately, since due to upcasting,
359
- // when there are two supertraits that differ by substs, we
360
- // may return more than one query response.
361
- Err ( NoSolution )
349
+ ecx. probe_candidate ( "builtin unsize" ) . enter ( |ecx| {
350
+ match ( a_ty. kind ( ) , b_ty. kind ( ) ) {
351
+ // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`
352
+ ( & ty:: Dynamic ( _, _, ty:: Dyn ) , & ty:: Dynamic ( _, _, ty:: Dyn ) ) => {
353
+ // Dyn upcasting is handled separately, since due to upcasting,
354
+ // when there are two supertraits that differ by substs, we
355
+ // may return more than one query response.
356
+ Err ( NoSolution )
357
+ }
358
+ // `T` -> `dyn Trait` unsizing
359
+ ( _, & ty:: Dynamic ( data, region, ty:: Dyn ) ) => {
360
+ // Can only unsize to an object-safe type
361
+ if data
362
+ . principal_def_id ( )
363
+ . is_some_and ( |def_id| !tcx. check_is_object_safe ( def_id) )
364
+ {
365
+ return Err ( NoSolution ) ;
362
366
}
363
- // `T` -> `dyn Trait` unsizing
364
- ( _, & ty:: Dynamic ( data, region, ty:: Dyn ) ) => {
365
- // Can only unsize to an object-safe type
366
- if data
367
- . principal_def_id ( )
368
- . is_some_and ( |def_id| !tcx. check_is_object_safe ( def_id) )
369
- {
370
- return Err ( NoSolution ) ;
371
- }
372
-
373
- let Some ( sized_def_id) = tcx. lang_items ( ) . sized_trait ( ) else {
367
+
368
+ let Some ( sized_def_id) = tcx. lang_items ( ) . sized_trait ( ) else {
374
369
return Err ( NoSolution ) ;
375
370
} ;
376
- // Check that the type implements all of the predicates of the def-id.
377
- // (i.e. the principal, all of the associated types match, and any auto traits)
378
- ecx. add_goals (
379
- data. iter ( ) . map ( |pred| goal. with ( tcx, pred. with_self_ty ( tcx, a_ty) ) ) ,
380
- ) ;
381
- // The type must be Sized to be unsized.
382
- ecx. add_goal ( goal. with ( tcx, ty:: TraitRef :: new ( tcx, sized_def_id, [ a_ty] ) ) ) ;
383
- // The type must outlive the lifetime of the `dyn` we're unsizing into.
384
- ecx. add_goal (
385
- goal. with ( tcx, ty:: Binder :: dummy ( ty:: OutlivesPredicate ( a_ty, region) ) ) ,
386
- ) ;
387
- ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
388
- }
389
- // `[T; n]` -> `[T]` unsizing
390
- ( & ty:: Array ( a_elem_ty, ..) , & ty:: Slice ( b_elem_ty) ) => {
391
- // We just require that the element type stays the same
392
- ecx. eq ( goal. param_env , a_elem_ty, b_elem_ty) ?;
393
- ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
394
- }
395
- // Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>`
396
- ( & ty:: Adt ( a_def, a_substs) , & ty:: Adt ( b_def, b_substs) )
397
- if a_def. is_struct ( ) && a_def. did ( ) == b_def. did ( ) =>
398
- {
399
- let unsizing_params = tcx. unsizing_params_for_adt ( a_def. did ( ) ) ;
400
- // We must be unsizing some type parameters. This also implies
401
- // that the struct has a tail field.
402
- if unsizing_params. is_empty ( ) {
403
- return Err ( NoSolution ) ;
404
- }
405
-
406
- let tail_field = a_def
407
- . non_enum_variant ( )
408
- . fields
409
- . raw
410
- . last ( )
411
- . expect ( "expected unsized ADT to have a tail field" ) ;
412
- let tail_field_ty = tcx. type_of ( tail_field. did ) ;
413
-
414
- let a_tail_ty = tail_field_ty. subst ( tcx, a_substs) ;
415
- let b_tail_ty = tail_field_ty. subst ( tcx, b_substs) ;
416
-
417
- // Substitute just the unsizing params from B into A. The type after
418
- // this substitution must be equal to B. This is so we don't unsize
419
- // unrelated type parameters.
420
- let new_a_substs =
421
- tcx. mk_substs_from_iter ( a_substs. iter ( ) . enumerate ( ) . map ( |( i, a) | {
422
- if unsizing_params. contains ( i as u32 ) { b_substs[ i] } else { a }
423
- } ) ) ;
424
- let unsized_a_ty = tcx. mk_adt ( a_def, new_a_substs) ;
425
-
426
- // Finally, we require that `TailA: Unsize<TailB>` for the tail field
427
- // types.
428
- ecx. eq ( goal. param_env , unsized_a_ty, b_ty) ?;
429
- ecx. add_goal ( goal. with (
430
- tcx,
431
- ty:: TraitRef :: new ( tcx, goal. predicate . def_id ( ) , [ a_tail_ty, b_tail_ty] ) ,
432
- ) ) ;
433
- ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
434
- }
435
- // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize<U>`
436
- ( & ty:: Tuple ( a_tys) , & ty:: Tuple ( b_tys) )
437
- if a_tys. len ( ) == b_tys. len ( ) && !a_tys. is_empty ( ) =>
438
- {
439
- let ( a_last_ty, a_rest_tys) = a_tys. split_last ( ) . unwrap ( ) ;
440
- let b_last_ty = b_tys. last ( ) . unwrap ( ) ;
441
-
442
- // Substitute just the tail field of B., and require that they're equal.
443
- let unsized_a_ty =
444
- tcx. mk_tup_from_iter ( a_rest_tys. iter ( ) . chain ( [ b_last_ty] ) . copied ( ) ) ;
445
- ecx. eq ( goal. param_env , unsized_a_ty, b_ty) ?;
446
-
447
- // Similar to ADTs, require that the rest of the fields are equal.
448
- ecx. add_goal ( goal. with (
449
- tcx,
450
- ty:: TraitRef :: new (
451
- tcx,
452
- goal. predicate . def_id ( ) ,
453
- [ * a_last_ty, * b_last_ty] ,
454
- ) ,
455
- ) ) ;
456
- ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
371
+ // Check that the type implements all of the predicates of the def-id.
372
+ // (i.e. the principal, all of the associated types match, and any auto traits)
373
+ ecx. add_goals (
374
+ data. iter ( ) . map ( |pred| goal. with ( tcx, pred. with_self_ty ( tcx, a_ty) ) ) ,
375
+ ) ;
376
+ // The type must be Sized to be unsized.
377
+ ecx. add_goal ( goal. with ( tcx, ty:: TraitRef :: new ( tcx, sized_def_id, [ a_ty] ) ) ) ;
378
+ // The type must outlive the lifetime of the `dyn` we're unsizing into.
379
+ ecx. add_goal (
380
+ goal. with ( tcx, ty:: Binder :: dummy ( ty:: OutlivesPredicate ( a_ty, region) ) ) ,
381
+ ) ;
382
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
383
+ }
384
+ // `[T; n]` -> `[T]` unsizing
385
+ ( & ty:: Array ( a_elem_ty, ..) , & ty:: Slice ( b_elem_ty) ) => {
386
+ // We just require that the element type stays the same
387
+ ecx. eq ( goal. param_env , a_elem_ty, b_elem_ty) ?;
388
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
389
+ }
390
+ // Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>`
391
+ ( & ty:: Adt ( a_def, a_substs) , & ty:: Adt ( b_def, b_substs) )
392
+ if a_def. is_struct ( ) && a_def. did ( ) == b_def. did ( ) =>
393
+ {
394
+ let unsizing_params = tcx. unsizing_params_for_adt ( a_def. did ( ) ) ;
395
+ // We must be unsizing some type parameters. This also implies
396
+ // that the struct has a tail field.
397
+ if unsizing_params. is_empty ( ) {
398
+ return Err ( NoSolution ) ;
457
399
}
458
- _ => Err ( NoSolution ) ,
400
+
401
+ let tail_field = a_def
402
+ . non_enum_variant ( )
403
+ . fields
404
+ . raw
405
+ . last ( )
406
+ . expect ( "expected unsized ADT to have a tail field" ) ;
407
+ let tail_field_ty = tcx. type_of ( tail_field. did ) ;
408
+
409
+ let a_tail_ty = tail_field_ty. subst ( tcx, a_substs) ;
410
+ let b_tail_ty = tail_field_ty. subst ( tcx, b_substs) ;
411
+
412
+ // Substitute just the unsizing params from B into A. The type after
413
+ // this substitution must be equal to B. This is so we don't unsize
414
+ // unrelated type parameters.
415
+ let new_a_substs =
416
+ tcx. mk_substs_from_iter ( a_substs. iter ( ) . enumerate ( ) . map ( |( i, a) | {
417
+ if unsizing_params. contains ( i as u32 ) { b_substs[ i] } else { a }
418
+ } ) ) ;
419
+ let unsized_a_ty = tcx. mk_adt ( a_def, new_a_substs) ;
420
+
421
+ // Finally, we require that `TailA: Unsize<TailB>` for the tail field
422
+ // types.
423
+ ecx. eq ( goal. param_env , unsized_a_ty, b_ty) ?;
424
+ ecx. add_goal ( goal. with (
425
+ tcx,
426
+ ty:: TraitRef :: new ( tcx, goal. predicate . def_id ( ) , [ a_tail_ty, b_tail_ty] ) ,
427
+ ) ) ;
428
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
459
429
}
460
- } ,
461
- )
430
+ // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize<U>`
431
+ ( & ty:: Tuple ( a_tys) , & ty:: Tuple ( b_tys) )
432
+ if a_tys. len ( ) == b_tys. len ( ) && !a_tys. is_empty ( ) =>
433
+ {
434
+ let ( a_last_ty, a_rest_tys) = a_tys. split_last ( ) . unwrap ( ) ;
435
+ let b_last_ty = b_tys. last ( ) . unwrap ( ) ;
436
+
437
+ // Substitute just the tail field of B., and require that they're equal.
438
+ let unsized_a_ty =
439
+ tcx. mk_tup_from_iter ( a_rest_tys. iter ( ) . chain ( [ b_last_ty] ) . copied ( ) ) ;
440
+ ecx. eq ( goal. param_env , unsized_a_ty, b_ty) ?;
441
+
442
+ // Similar to ADTs, require that the rest of the fields are equal.
443
+ ecx. add_goal ( goal. with (
444
+ tcx,
445
+ ty:: TraitRef :: new ( tcx, goal. predicate . def_id ( ) , [ * a_last_ty, * b_last_ty] ) ,
446
+ ) ) ;
447
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
448
+ }
449
+ _ => Err ( NoSolution ) ,
450
+ }
451
+ } )
462
452
}
463
453
464
454
fn consider_builtin_dyn_upcast_candidates (
@@ -488,11 +478,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
488
478
}
489
479
490
480
let mut unsize_dyn_to_principal = |principal : Option < ty:: PolyExistentialTraitRef < ' tcx > > | {
491
- ecx. probe ( |r| CandidateKind :: Candidate {
492
- name : "upcast dyn to principle" . into ( ) ,
493
- result : * r,
494
- } )
495
- . enter ( |ecx| -> Result < _ , NoSolution > {
481
+ ecx. probe_candidate ( "upcast dyn to principle" ) . enter ( |ecx| -> Result < _ , NoSolution > {
496
482
// Require that all of the trait predicates from A match B, except for
497
483
// the auto traits. We do this by constructing a new A type with B's
498
484
// auto traits, and equating these types.
@@ -714,21 +700,20 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
714
700
goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
715
701
constituent_tys : impl Fn ( & EvalCtxt < ' _ , ' tcx > , Ty < ' tcx > ) -> Result < Vec < Ty < ' tcx > > , NoSolution > ,
716
702
) -> QueryResult < ' tcx > {
717
- self . probe ( |r| CandidateKind :: Candidate { name : "constituent tys" . into ( ) , result : * r } )
718
- . enter ( |ecx| {
719
- ecx. add_goals (
720
- constituent_tys ( ecx, goal. predicate . self_ty ( ) ) ?
721
- . into_iter ( )
722
- . map ( |ty| {
723
- goal. with (
724
- ecx. tcx ( ) ,
725
- ty:: Binder :: dummy ( goal. predicate . with_self_ty ( ecx. tcx ( ) , ty) ) ,
726
- )
727
- } )
728
- . collect :: < Vec < _ > > ( ) ,
729
- ) ;
730
- ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
731
- } )
703
+ self . probe_candidate ( "constituent tys" ) . enter ( |ecx| {
704
+ ecx. add_goals (
705
+ constituent_tys ( ecx, goal. predicate . self_ty ( ) ) ?
706
+ . into_iter ( )
707
+ . map ( |ty| {
708
+ goal. with (
709
+ ecx. tcx ( ) ,
710
+ ty:: Binder :: dummy ( goal. predicate . with_self_ty ( ecx. tcx ( ) , ty) ) ,
711
+ )
712
+ } )
713
+ . collect :: < Vec < _ > > ( ) ,
714
+ ) ;
715
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
716
+ } )
732
717
}
733
718
734
719
#[ instrument( level = "debug" , skip( self ) ) ]
0 commit comments