@@ -2,10 +2,9 @@ use std::cell::OnceCell;
22use std:: ops:: ControlFlow ;
33
44use rustc_data_structures:: fx:: FxHashSet ;
5- use rustc_data_structures:: graph:: iterate:: DepthFirstSearch ;
65use rustc_data_structures:: graph:: vec_graph:: VecGraph ;
76use rustc_data_structures:: graph:: { self } ;
8- use rustc_data_structures:: unord:: { UnordBag , UnordMap , UnordSet } ;
7+ use rustc_data_structures:: unord:: { UnordMap , UnordSet } ;
98use rustc_hir as hir;
109use rustc_hir:: HirId ;
1110use rustc_hir:: def:: { DefKind , Res } ;
@@ -18,15 +17,12 @@ use rustc_span::{DUMMY_SP, Span};
1817use rustc_trait_selection:: traits:: { ObligationCause , ObligationCtxt } ;
1918use tracing:: debug;
2019
21- use crate :: typeck_root_ctxt:: InferVarInfo ;
2220use crate :: { FnCtxt , errors} ;
2321
2422#[ derive( Copy , Clone ) ]
2523pub ( crate ) enum DivergingFallbackBehavior {
2624 /// Always fallback to `()` (aka "always spontaneous decay")
2725 ToUnit ,
28- /// Sometimes fallback to `!`, but mainly fallback to `()` so that most of the crates are not broken.
29- ContextDependent ,
3026 /// Always fallback to `!` (which should be equivalent to never falling back + not making
3127 /// never-to-any coercions unless necessary)
3228 ToNever ,
@@ -267,9 +263,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
267263 // type variable. These will typically default to `!`, unless
268264 // we find later that they are *also* reachable from some
269265 // other type variable outside this set.
270- let mut roots_reachable_from_diverging = DepthFirstSearch :: new ( & coercion_graph) ;
271266 let mut diverging_vids = vec ! [ ] ;
272- let mut non_diverging_vids = vec ! [ ] ;
273267 for unsolved_vid in unsolved_vids {
274268 let root_vid = self . root_var ( unsolved_vid) ;
275269 debug ! (
@@ -280,49 +274,17 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
280274 ) ;
281275 if diverging_roots. contains ( & root_vid) {
282276 diverging_vids. push ( unsolved_vid) ;
283- roots_reachable_from_diverging. push_start_node ( root_vid) ;
284277
285278 debug ! (
286279 "calculate_diverging_fallback: root_vid={:?} reaches {:?}" ,
287280 root_vid,
288281 graph:: depth_first_search( & coercion_graph, root_vid) . collect:: <Vec <_>>( )
289282 ) ;
290-
291- // drain the iterator to visit all nodes reachable from this node
292- roots_reachable_from_diverging. complete_search ( ) ;
293- } else {
294- non_diverging_vids. push ( unsolved_vid) ;
295283 }
296284 }
297285
298- debug ! (
299- "calculate_diverging_fallback: roots_reachable_from_diverging={:?}" ,
300- roots_reachable_from_diverging,
301- ) ;
302-
303- // Find all type variables N0 that are not reachable from a
304- // diverging variable, and then compute the set reachable from
305- // N0, which we call N. These are the *non-diverging* type
306- // variables. (Note that this set consists of "root variables".)
307- let mut roots_reachable_from_non_diverging = DepthFirstSearch :: new ( & coercion_graph) ;
308- for & non_diverging_vid in & non_diverging_vids {
309- let root_vid = self . root_var ( non_diverging_vid) ;
310- if roots_reachable_from_diverging. visited ( root_vid) {
311- continue ;
312- }
313- roots_reachable_from_non_diverging. push_start_node ( root_vid) ;
314- roots_reachable_from_non_diverging. complete_search ( ) ;
315- }
316- debug ! (
317- "calculate_diverging_fallback: roots_reachable_from_non_diverging={:?}" ,
318- roots_reachable_from_non_diverging,
319- ) ;
320-
321286 debug ! ( "obligations: {:#?}" , self . fulfillment_cx. borrow_mut( ) . pending_obligations( ) ) ;
322287
323- // For each diverging variable, figure out whether it can
324- // reach a member of N. If so, it falls back to `()`. Else
325- // `!`.
326288 let mut diverging_fallback = UnordMap :: with_capacity ( diverging_vids. len ( ) ) ;
327289 let unsafe_infer_vars = OnceCell :: new ( ) ;
328290
@@ -335,21 +297,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
335297 for & diverging_vid in & diverging_vids {
336298 let diverging_ty = Ty :: new_var ( self . tcx , diverging_vid) ;
337299 let root_vid = self . root_var ( diverging_vid) ;
338- let can_reach_non_diverging = graph:: depth_first_search ( & coercion_graph, root_vid)
339- . any ( |n| roots_reachable_from_non_diverging. visited ( n) ) ;
340-
341- let infer_var_infos: UnordBag < _ > = self
342- . infer_var_info
343- . borrow ( )
344- . items ( )
345- . filter ( |& ( vid, _) | self . infcx . root_var ( * vid) == root_vid)
346- . map ( |( _, info) | * info)
347- . collect ( ) ;
348-
349- let found_infer_var_info = InferVarInfo {
350- self_in_trait : infer_var_infos. items ( ) . any ( |info| info. self_in_trait ) ,
351- output : infer_var_infos. items ( ) . any ( |info| info. output ) ,
352- } ;
353300
354301 let mut fallback_to = |ty| {
355302 self . lint_never_type_fallback_flowing_into_unsafe_code (
@@ -366,52 +313,16 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
366313 debug ! ( "fallback to () - legacy: {:?}" , diverging_vid) ;
367314 fallback_to ( self . tcx . types . unit ) ;
368315 }
369- DivergingFallbackBehavior :: ContextDependent => {
370- if found_infer_var_info. self_in_trait && found_infer_var_info. output {
371- // This case falls back to () to ensure that the code pattern in
372- // tests/ui/never_type/fallback-closure-ret.rs continues to
373- // compile when never_type_fallback is enabled.
374- //
375- // This rule is not readily explainable from first principles,
376- // but is rather intended as a patchwork fix to ensure code
377- // which compiles before the stabilization of never type
378- // fallback continues to work.
379- //
380- // Typically this pattern is encountered in a function taking a
381- // closure as a parameter, where the return type of that closure
382- // (checked by `relationship.output`) is expected to implement
383- // some trait (checked by `relationship.self_in_trait`). This
384- // can come up in non-closure cases too, so we do not limit this
385- // rule to specifically `FnOnce`.
386- //
387- // When the closure's body is something like `panic!()`, the
388- // return type would normally be inferred to `!`. However, it
389- // needs to fall back to `()` in order to still compile, as the
390- // trait is specifically implemented for `()` but not `!`.
391- //
392- // For details on the requirements for these relationships to be
393- // set, see the relationship finding module in
394- // compiler/rustc_trait_selection/src/traits/relationships.rs.
395- debug ! ( "fallback to () - found trait and projection: {:?}" , diverging_vid) ;
396- fallback_to ( self . tcx . types . unit ) ;
397- } else if can_reach_non_diverging {
398- debug ! ( "fallback to () - reached non-diverging: {:?}" , diverging_vid) ;
399- fallback_to ( self . tcx . types . unit ) ;
400- } else {
401- debug ! ( "fallback to ! - all diverging: {:?}" , diverging_vid) ;
402- fallback_to ( self . tcx . types . never ) ;
403- }
404- }
405316 DivergingFallbackBehavior :: ToNever => {
406317 debug ! (
407- "fallback to ! - `rustc_never_type_mode = \" fallback_to_never \" )`: {:?}" ,
318+ "fallback to ! - `rustc_never_type_options::falback = \" never \" )`: {:?}" ,
408319 diverging_vid
409320 ) ;
410321 fallback_to ( self . tcx . types . never ) ;
411322 }
412323 DivergingFallbackBehavior :: NoFallback => {
413324 debug ! (
414- "no fallback - `rustc_never_type_mode = \" no_fallback \" `: {:?}" ,
325+ "no fallback - `rustc_never_type_options::fallback = \" no \" `: {:?}" ,
415326 diverging_vid
416327 ) ;
417328 }
0 commit comments