@@ -8,12 +8,17 @@ use rustc_data_structures::{
8
8
use rustc_hir as hir;
9
9
use rustc_hir:: intravisit:: Visitor ;
10
10
use rustc_hir:: HirId ;
11
- use rustc_infer:: infer:: { DefineOpaqueTypes , InferOk } ;
12
11
use rustc_middle:: bug;
12
+ use rustc_infer:: {
13
+ infer:: { DefineOpaqueTypes , InferOk } ,
14
+ traits:: ObligationCause ,
15
+ } ;
13
16
use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable } ;
14
17
use rustc_session:: lint;
15
18
use rustc_span:: DUMMY_SP ;
16
19
use rustc_span:: { def_id:: LocalDefId , Span } ;
20
+ use rustc_trait_selection:: traits:: ObligationCtxt ;
21
+ use rustc_type_ir:: TyVid ;
17
22
18
23
#[ derive( Copy , Clone ) ]
19
24
pub enum DivergingFallbackBehavior {
@@ -344,6 +349,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
344
349
// `!`.
345
350
let mut diverging_fallback = UnordMap :: with_capacity ( diverging_vids. len ( ) ) ;
346
351
let unsafe_infer_vars = OnceCell :: new ( ) ;
352
+
353
+ self . lint_obligations_broken_by_never_type_fallback_change ( behavior, & diverging_vids) ;
354
+
347
355
for & diverging_vid in & diverging_vids {
348
356
let diverging_ty = Ty :: new_var ( self . tcx , diverging_vid) ;
349
357
let root_vid = self . root_var ( diverging_vid) ;
@@ -469,6 +477,46 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
469
477
}
470
478
}
471
479
480
+ fn lint_obligations_broken_by_never_type_fallback_change (
481
+ & self ,
482
+ behavior : DivergingFallbackBehavior ,
483
+ diverging_vids : & [ TyVid ] ,
484
+ ) {
485
+ let DivergingFallbackBehavior :: FallbackToUnit = behavior else { return } ;
486
+
487
+ // Returns errors which happen if fallback is set to `fallback`
488
+ let try_out = |fallback| {
489
+ self . probe ( |_| {
490
+ let obligations = self . fulfillment_cx . borrow ( ) . pending_obligations ( ) ;
491
+ let ocx = ObligationCtxt :: new ( & self . infcx ) ;
492
+ ocx. register_obligations ( obligations. iter ( ) . cloned ( ) ) ;
493
+
494
+ for & diverging_vid in diverging_vids {
495
+ let diverging_ty = Ty :: new_var ( self . tcx , diverging_vid) ;
496
+
497
+ _ = ocx. eq ( & ObligationCause :: dummy ( ) , self . param_env , diverging_ty, fallback) ;
498
+ }
499
+
500
+ ocx. select_where_possible ( )
501
+ } )
502
+ } ;
503
+
504
+ // If we have no errors with `fallback = ()`, but *do* have errors with `fallback = !`,
505
+ // then this code will be broken by the never type fallback change.qba
506
+ let unit_errors = try_out ( self . tcx . types . unit ) ;
507
+ if unit_errors. is_empty ( )
508
+ && let never_errors = try_out ( self . tcx . types . never )
509
+ && !never_errors. is_empty ( )
510
+ {
511
+ self . tcx . emit_node_span_lint (
512
+ lint:: builtin:: DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK ,
513
+ self . tcx . local_def_id_to_hir_id ( self . body_id ) ,
514
+ self . tcx . def_span ( self . body_id ) ,
515
+ errors:: DependencyOnUnitNeverTypeFallback { } ,
516
+ )
517
+ }
518
+ }
519
+
472
520
/// Returns a graph whose nodes are (unresolved) inference variables and where
473
521
/// an edge `?A -> ?B` indicates that the variable `?A` is coerced to `?B`.
474
522
fn create_coercion_graph ( & self ) -> VecGraph < ty:: TyVid , true > {
0 commit comments