@@ -371,43 +371,108 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt<'_, '_, '_>,
371371 trait_ref) ;
372372 }
373373
374- // First, create an ordered iterator over all the type parameters to the trait, with the self
375- // type appearing first.
376- // Find the first input type that either references a type parameter OR
377- // some local type.
378- for input_ty in trait_ref. input_types ( ) {
379- if ty_is_local ( tcx, input_ty, in_crate) {
380- debug ! ( "orphan_check_trait_ref: ty_is_local `{:?}`" , input_ty) ;
381-
382- // First local input type. Check that there are no
383- // uncovered type parameters.
384- let uncovered_tys = uncovered_tys ( tcx, input_ty, in_crate) ;
385- for uncovered_ty in uncovered_tys {
386- if let Some ( param) = uncovered_ty. walk ( )
387- . find ( |t| is_possibly_remote_type ( t, in_crate) )
388- {
389- debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param) ;
390- return Err ( OrphanCheckErr :: UncoveredTy ( param) ) ;
374+ if tcx. features ( ) . re_rebalance_coherence {
375+ // Given impl<P1..=Pn> Trait<T1..=Tn> for T0, an impl is valid only
376+ // if at least one of the following is true:
377+ //
378+ // - Trait is a local trait
379+ // (already checked in orphan_check prior to calling this function)
380+ // - All of
381+ // - At least one of the types T0..=Tn must be a local type.
382+ // Let Ti be the first such type.
383+ // - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti)
384+ //
385+ for input_ty in trait_ref. input_types ( ) {
386+ debug ! ( "orphan_check_trait_ref: check ty `{:?}`" , input_ty) ;
387+ if ty_is_local ( tcx, input_ty, in_crate) {
388+ debug ! ( "orphan_check_trait_ref: ty_is_local `{:?}`" , input_ty) ;
389+ return Ok ( ( ) ) ;
390+ } else if is_uncovered_ty ( input_ty) {
391+ debug ! ( "orphan_check_trait_ref: uncovered ty: `{:?}`" , input_ty) ;
392+ return Err ( OrphanCheckErr :: UncoveredTy ( input_ty) )
393+ }
394+ }
395+ // If we exit above loop, never found a local type.
396+ debug ! ( "orphan_check_trait_ref: no local type" ) ;
397+ Err ( OrphanCheckErr :: NoLocalInputType )
398+ } else {
399+ // First, create an ordered iterator over all the type parameters to the trait, with the self
400+ // type appearing first.
401+ // Find the first input type that either references a type parameter OR
402+ // some local type.
403+ for input_ty in trait_ref. input_types ( ) {
404+ if ty_is_local ( tcx, input_ty, in_crate) {
405+ debug ! ( "orphan_check_trait_ref: ty_is_local `{:?}`" , input_ty) ;
406+
407+ // First local input type. Check that there are no
408+ // uncovered type parameters.
409+ let uncovered_tys = uncovered_tys ( tcx, input_ty, in_crate) ;
410+ for uncovered_ty in uncovered_tys {
411+ if let Some ( param) = uncovered_ty. walk ( )
412+ . find ( |t| is_possibly_remote_type ( t, in_crate) )
413+ {
414+ debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param) ;
415+ return Err ( OrphanCheckErr :: UncoveredTy ( param) ) ;
416+ }
391417 }
418+
419+ // OK, found local type, all prior types upheld invariant.
420+ return Ok ( ( ) ) ;
392421 }
393422
394- // OK, found local type, all prior types upheld invariant.
395- return Ok ( ( ) ) ;
423+ // Otherwise, enforce invariant that there are no type
424+ // parameters reachable.
425+ if let Some ( param) = input_ty. walk ( )
426+ . find ( |t| is_possibly_remote_type ( t, in_crate) )
427+ {
428+ debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param) ;
429+ return Err ( OrphanCheckErr :: UncoveredTy ( param) ) ;
430+ }
431+ }
432+ // If we exit above loop, never found a local type.
433+ debug ! ( "orphan_check_trait_ref: no local type" ) ;
434+ Err ( OrphanCheckErr :: NoLocalInputType )
435+ }
436+ }
437+
438+ fn is_uncovered_ty ( ty : Ty < ' _ > ) -> bool {
439+ match ty. sty {
440+ ty:: Bool |
441+ ty:: Char |
442+ ty:: Int ( ..) |
443+ ty:: Uint ( ..) |
444+ ty:: Float ( ..) |
445+ ty:: Str |
446+ ty:: FnDef ( ..) |
447+ ty:: FnPtr ( _) |
448+ ty:: Array ( ..) |
449+ ty:: Slice ( ..) |
450+ ty:: RawPtr ( ..) |
451+ ty:: Ref ( ..) |
452+ ty:: Never |
453+ ty:: Tuple ( ..) |
454+ ty:: Bound ( ..) |
455+ ty:: Infer ( ..) |
456+ ty:: Adt ( ..) |
457+ ty:: Foreign ( ..) |
458+ ty:: Dynamic ( ..) |
459+ ty:: Error |
460+ ty:: Projection ( ..) => {
461+ false
462+ }
463+
464+ ty:: Param ( ..) => {
465+ true
396466 }
397467
398- // Otherwise, enforce invariant that there are no type
399- // parameters reachable.
400- if let Some ( param) = input_ty. walk ( )
401- . find ( |t| is_possibly_remote_type ( t, in_crate) )
402- {
403- debug ! ( "orphan_check_trait_ref: uncovered type `{:?}`" , param) ;
404- return Err ( OrphanCheckErr :: UncoveredTy ( param) ) ;
468+ ty:: UnnormalizedProjection ( ..) |
469+ ty:: Closure ( ..) |
470+ ty:: Generator ( ..) |
471+ ty:: GeneratorWitness ( ..) |
472+ ty:: Opaque ( ..) => {
473+ bug ! ( "is_uncovered_ty invoked on unexpected type: {:?}" , ty)
405474 }
406475 }
407-
408- // If we exit above loop, never found a local type.
409- debug ! ( "orphan_check_trait_ref: no local type" ) ;
410- return Err ( OrphanCheckErr :: NoLocalInputType ) ;
411476}
412477
413478fn uncovered_tys < ' tcx > ( tcx : TyCtxt < ' _ , ' _ , ' _ > , ty : Ty < ' tcx > , in_crate : InCrate )
0 commit comments