@@ -278,8 +278,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
278278 /// fall back to subtyping (`unify_and`).
279279 fn coerce_from_inference_variable ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
280280 debug ! ( "coerce_from_inference_variable(a={:?}, b={:?})" , a, b) ;
281- assert ! ( a. is_ty_var( ) && self . shallow_resolve( a) == a) ;
282- assert ! ( self . shallow_resolve( b) == b) ;
281+ debug_assert ! ( a. is_ty_var( ) && self . shallow_resolve( a) == a) ;
282+ debug_assert ! ( self . shallow_resolve( b) == b) ;
283283
284284 if b. is_ty_var ( ) {
285285 // Two unresolved type variables: create a `Coerce` predicate.
@@ -323,6 +323,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
323323 mutbl_b : hir:: Mutability ,
324324 ) -> CoerceResult < ' tcx > {
325325 debug ! ( "coerce_borrowed_pointer(a={:?}, b={:?})" , a, b) ;
326+ debug_assert ! ( self . shallow_resolve( a) == a) ;
327+ debug_assert ! ( self . shallow_resolve( b) == b) ;
326328
327329 // If we have a parameter of type `&M T_a` and the value
328330 // provided is `expr`, we will be adding an implicit borrow,
@@ -514,10 +516,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
514516 ///
515517 /// [unsized coercion](https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions)
516518 #[ instrument( skip( self ) , level = "debug" ) ]
517- fn coerce_unsized ( & self , mut source : Ty < ' tcx > , mut target : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
518- source = self . shallow_resolve ( source) ;
519- target = self . shallow_resolve ( target) ;
519+ fn coerce_unsized ( & self , source : Ty < ' tcx > , target : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
520520 debug ! ( ?source, ?target) ;
521+ debug_assert ! ( self . shallow_resolve( source) == source) ;
522+ debug_assert ! ( self . shallow_resolve( target) == target) ;
521523
522524 // We don't apply any coercions incase either the source or target
523525 // aren't sufficiently well known but tend to instead just equate
@@ -531,6 +533,54 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
531533 return Err ( TypeError :: Mismatch ) ;
532534 }
533535
536+ // This is an optimization because coercion is one of the most common
537+ // operations that we do in typeck, since it happens at every assignment
538+ // and call arg (among other positions).
539+ //
540+ // These targets are known to never be RHS in `LHS: CoerceUnsized<RHS>`.
541+ // That's because these are built-in types for which a core-provided impl
542+ // doesn't exist, and for which a user-written impl is invalid.
543+ //
544+ // This is technically incomplete when users write impossible bounds like
545+ // `where T: CoerceUnsized<usize>`, for example, but that trait is unstable
546+ // and coercion is allowed to be incomplete. The only case where this matters
547+ // is impossible bounds.
548+ //
549+ // Note that some of these types implement `LHS: Unsize<RHS>`, but they
550+ // do not implement *`CoerceUnsized`* which is the root obligation of the
551+ // check below.
552+ match target. kind ( ) {
553+ ty:: Bool
554+ | ty:: Char
555+ | ty:: Int ( _)
556+ | ty:: Uint ( _)
557+ | ty:: Float ( _)
558+ | ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
559+ | ty:: Str
560+ | ty:: Array ( _, _)
561+ | ty:: Slice ( _)
562+ | ty:: FnDef ( _, _)
563+ | ty:: FnPtr ( _, _)
564+ | ty:: Dynamic ( _, _, _)
565+ | ty:: Closure ( _, _)
566+ | ty:: CoroutineClosure ( _, _)
567+ | ty:: Coroutine ( _, _)
568+ | ty:: CoroutineWitness ( _, _)
569+ | ty:: Never
570+ | ty:: Tuple ( _) => return Err ( TypeError :: Mismatch ) ,
571+ _ => { }
572+ }
573+ // Additionally, we ignore `&str -> &str` coercions, which happen very
574+ // commonly since strings are one of the most used argument types in Rust,
575+ // we do coercions when type checking call expressions.
576+ if let ty:: Ref ( _, source_pointee, ty:: Mutability :: Not ) = * source. kind ( )
577+ && source_pointee. is_str ( )
578+ && let ty:: Ref ( _, target_pointee, ty:: Mutability :: Not ) = * target. kind ( )
579+ && target_pointee. is_str ( )
580+ {
581+ return Err ( TypeError :: Mismatch ) ;
582+ }
583+
534584 let traits =
535585 ( self . tcx . lang_items ( ) . unsize_trait ( ) , self . tcx . lang_items ( ) . coerce_unsized_trait ( ) ) ;
536586 let ( Some ( unsize_did) , Some ( coerce_unsized_did) ) = traits else {
@@ -800,6 +850,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
800850 /// - `Pin<Box<T>>` as `Pin<&mut T>`
801851 #[ instrument( skip( self ) , level = "trace" ) ]
802852 fn coerce_pin_ref ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
853+ debug_assert ! ( self . shallow_resolve( a) == a) ;
854+ debug_assert ! ( self . shallow_resolve( b) == b) ;
855+
803856 // We need to make sure the two types are compatible for coercion.
804857 // Then we will build a ReborrowPin adjustment and return that as an InferOk.
805858
@@ -848,6 +901,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
848901 b : Ty < ' tcx > ,
849902 adjustment : Option < Adjust > ,
850903 ) -> CoerceResult < ' tcx > {
904+ debug_assert ! ( self . shallow_resolve( b) == b) ;
905+
851906 self . commit_if_ok ( |snapshot| {
852907 let outer_universe = self . infcx . universe ( ) ;
853908
@@ -888,24 +943,19 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
888943 fn_ty_a : ty:: PolyFnSig < ' tcx > ,
889944 b : Ty < ' tcx > ,
890945 ) -> CoerceResult < ' tcx > {
891- //! Attempts to coerce from the type of a Rust function item
892- //! into a closure or a `proc`.
893- //!
894-
895- let b = self . shallow_resolve ( b) ;
896946 debug ! ( ?fn_ty_a, ?b, "coerce_from_fn_pointer" ) ;
947+ debug_assert ! ( self . shallow_resolve( b) == b) ;
897948
898949 self . coerce_from_safe_fn ( fn_ty_a, b, None )
899950 }
900951
901952 fn coerce_from_fn_item ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
902- //! Attempts to coerce from the type of a Rust function item
903- //! into a closure or a `proc`.
953+ debug ! ( "coerce_from_fn_item(a={:?}, b={:?})" , a, b) ;
954+ debug_assert ! ( self . shallow_resolve( a) == a) ;
955+ debug_assert ! ( self . shallow_resolve( b) == b) ;
904956
905- let b = self . shallow_resolve ( b) ;
906957 let InferOk { value : b, mut obligations } =
907958 self . at ( & self . cause , self . param_env ) . normalize ( b) ;
908- debug ! ( "coerce_from_fn_item(a={:?}, b={:?})" , a, b) ;
909959
910960 match b. kind ( ) {
911961 ty:: FnPtr ( _, b_hdr) => {
@@ -955,18 +1005,17 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
9551005 }
9561006 }
9571007
1008+ /// Attempts to coerce from the type of a non-capturing closure
1009+ /// into a function pointer.
9581010 fn coerce_closure_to_fn (
9591011 & self ,
9601012 a : Ty < ' tcx > ,
9611013 closure_def_id_a : DefId ,
9621014 args_a : GenericArgsRef < ' tcx > ,
9631015 b : Ty < ' tcx > ,
9641016 ) -> CoerceResult < ' tcx > {
965- //! Attempts to coerce from the type of a non-capturing closure
966- //! into a function pointer.
967- //!
968-
969- let b = self . shallow_resolve ( b) ;
1017+ debug_assert ! ( self . shallow_resolve( a) == a) ;
1018+ debug_assert ! ( self . shallow_resolve( b) == b) ;
9701019
9711020 match b. kind ( ) {
9721021 // At this point we haven't done capture analysis, which means
@@ -1010,6 +1059,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
10101059 mutbl_b : hir:: Mutability ,
10111060 ) -> CoerceResult < ' tcx > {
10121061 debug ! ( "coerce_raw_ptr(a={:?}, b={:?})" , a, b) ;
1062+ debug_assert ! ( self . shallow_resolve( a) == a) ;
1063+ debug_assert ! ( self . shallow_resolve( b) == b) ;
10131064
10141065 let ( is_ref, mt_a) = match * a. kind ( ) {
10151066 ty:: Ref ( _, ty, mutbl) => ( true , ty:: TypeAndMut { ty, mutbl } ) ,
0 commit comments