22
33mod check_match;
44mod const_to_pat;
5+ mod migration;
56
67use std:: cmp:: Ordering ;
78use std:: sync:: Arc ;
89
910use rustc_abi:: { FieldIdx , Integer } ;
10- use rustc_errors:: MultiSpan ;
1111use rustc_errors:: codes:: * ;
1212use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
1313use rustc_hir:: pat_util:: EnumerateAndAdjustIterator ;
1414use rustc_hir:: { self as hir, ByRef , Mutability , RangeEnd } ;
1515use rustc_index:: Idx ;
16- use rustc_lint as lint;
1716use rustc_middle:: mir:: interpret:: LitToConstInput ;
1817use rustc_middle:: thir:: {
1918 Ascription , FieldPat , LocalVarId , Pat , PatKind , PatRange , PatRangeBoundary ,
@@ -26,16 +25,16 @@ use rustc_span::{ErrorGuaranteed, Span};
2625use tracing:: { debug, instrument} ;
2726
2827pub ( crate ) use self :: check_match:: check_match;
28+ use self :: migration:: PatMigration ;
2929use crate :: errors:: * ;
30- use crate :: fluent_generated as fluent;
3130
3231struct PatCtxt < ' a , ' tcx > {
3332 tcx : TyCtxt < ' tcx > ,
3433 typing_env : ty:: TypingEnv < ' tcx > ,
3534 typeck_results : & ' a ty:: TypeckResults < ' tcx > ,
3635
3736 /// Used by the Rust 2024 migration lint.
38- rust_2024_migration_suggestion : Option < Rust2024IncompatiblePatSugg > ,
37+ rust_2024_migration : Option < PatMigration < ' a > > ,
3938}
4039
4140pub ( super ) fn pat_from_hir < ' a , ' tcx > (
@@ -44,59 +43,19 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
4443 typeck_results : & ' a ty:: TypeckResults < ' tcx > ,
4544 pat : & ' tcx hir:: Pat < ' tcx > ,
4645) -> Box < Pat < ' tcx > > {
47- let migration_info = typeck_results. rust_2024_migration_desugared_pats ( ) . get ( pat. hir_id ) ;
4846 let mut pcx = PatCtxt {
4947 tcx,
5048 typing_env,
5149 typeck_results,
52- rust_2024_migration_suggestion : migration_info. and_then ( |info| {
53- Some ( Rust2024IncompatiblePatSugg {
54- suggest_eliding_modes : info. suggest_eliding_modes ,
55- suggestion : Vec :: new ( ) ,
56- ref_pattern_count : 0 ,
57- binding_mode_count : 0 ,
58- default_mode_span : None ,
59- default_mode_labels : Default :: default ( ) ,
60- } )
61- } ) ,
50+ rust_2024_migration : typeck_results
51+ . rust_2024_migration_desugared_pats ( )
52+ . get ( pat. hir_id )
53+ . map ( PatMigration :: new) ,
6254 } ;
6355 let result = pcx. lower_pattern ( pat) ;
6456 debug ! ( "pat_from_hir({:?}) = {:?}" , pat, result) ;
65- if let Some ( info) = migration_info
66- && let Some ( sugg) = pcx. rust_2024_migration_suggestion
67- {
68- let mut spans =
69- MultiSpan :: from_spans ( info. primary_labels . iter ( ) . map ( |( span, _) | * span) . collect ( ) ) ;
70- for ( span, label) in & info. primary_labels {
71- spans. push_span_label ( * span, label. clone ( ) ) ;
72- }
73- // If a relevant span is from at least edition 2024, this is a hard error.
74- let is_hard_error = spans. primary_spans ( ) . iter ( ) . any ( |span| span. at_least_rust_2024 ( ) ) ;
75- if is_hard_error {
76- let mut err =
77- tcx. dcx ( ) . struct_span_err ( spans, fluent:: mir_build_rust_2024_incompatible_pat) ;
78- if let Some ( lint_info) = lint:: builtin:: RUST_2024_INCOMPATIBLE_PAT . future_incompatible {
79- // provide the same reference link as the lint
80- err. note ( format ! ( "for more information, see {}" , lint_info. reference) ) ;
81- }
82- err. arg ( "bad_modifiers" , info. bad_modifiers ) ;
83- err. arg ( "bad_ref_pats" , info. bad_ref_pats ) ;
84- err. arg ( "is_hard_error" , true ) ;
85- err. subdiagnostic ( sugg) ;
86- err. emit ( ) ;
87- } else {
88- tcx. emit_node_span_lint (
89- lint:: builtin:: RUST_2024_INCOMPATIBLE_PAT ,
90- pat. hir_id ,
91- spans,
92- Rust2024IncompatiblePat {
93- sugg,
94- bad_modifiers : info. bad_modifiers ,
95- bad_ref_pats : info. bad_ref_pats ,
96- is_hard_error,
97- } ,
98- ) ;
99- }
57+ if let Some ( m) = pcx. rust_2024_migration {
58+ m. emit ( tcx, pat. hir_id ) ;
10059 }
10160 result
10261}
@@ -107,7 +66,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
10766 self . typeck_results . pat_adjustments ( ) . get ( pat. hir_id ) . map_or ( & [ ] , |v| & * * v) ;
10867
10968 let mut opt_old_mode_span = None ;
110- if let Some ( s) = & mut self . rust_2024_migration_suggestion
69+ if let Some ( s) = & mut self . rust_2024_migration
11170 && !adjustments. is_empty ( )
11271 {
11372 let implicit_deref_mutbls = adjustments. iter ( ) . map ( |ref_ty| {
@@ -117,7 +76,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
11776 mutbl
11877 } ) ;
11978
120- if !s. suggest_eliding_modes {
79+ if !s. info . suggest_eliding_modes {
12180 let suggestion_str: String =
12281 implicit_deref_mutbls. clone ( ) . map ( |mutbl| mutbl. ref_prefix_str ( ) ) . collect ( ) ;
12382 s. suggestion . push ( ( pat. span . shrink_to_lo ( ) , suggestion_str) ) ;
@@ -169,7 +128,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
169128 } )
170129 } ) ;
171130
172- if let Some ( s) = & mut self . rust_2024_migration_suggestion
131+ if let Some ( s) = & mut self . rust_2024_migration
173132 && let Some ( old_mode_span) = opt_old_mode_span
174133 {
175134 s. default_mode_span = old_mode_span;
@@ -368,15 +327,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
368327 }
369328 hir:: PatKind :: Ref ( subpattern, _) => {
370329 // Track the default binding mode for the Rust 2024 migration suggestion.
371- let old_mode_span = self . rust_2024_migration_suggestion . as_mut ( ) . and_then ( |s| {
330+ let old_mode_span = self . rust_2024_migration . as_mut ( ) . and_then ( |s| {
372331 if let Some ( ( default_mode_span, default_ref_mutbl) ) = s. default_mode_span {
373332 // If this eats a by-ref default binding mode, label the binding mode.
374333 s. default_mode_labels . insert ( default_mode_span, default_ref_mutbl) ;
375334 }
376335 s. default_mode_span . take ( )
377336 } ) ;
378337 let subpattern = self . lower_pattern ( subpattern) ;
379- if let Some ( s) = & mut self . rust_2024_migration_suggestion {
338+ if let Some ( s) = & mut self . rust_2024_migration {
380339 s. default_mode_span = old_mode_span;
381340 }
382341 PatKind :: Deref { subpattern }
@@ -408,19 +367,19 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
408367 . get ( pat. hir_id )
409368 . expect ( "missing binding mode" ) ;
410369
411- if let Some ( s) = & mut self . rust_2024_migration_suggestion {
370+ if let Some ( s) = & mut self . rust_2024_migration {
412371 if explicit_ba != hir:: BindingMode :: NONE
413372 && let Some ( ( default_mode_span, default_ref_mutbl) ) = s. default_mode_span
414373 {
415374 // If this overrides a by-ref default binding mode, label the binding mode.
416375 s. default_mode_labels . insert ( default_mode_span, default_ref_mutbl) ;
417376 // If our suggestion is to elide redundnt modes, this will be one of them.
418- if s. suggest_eliding_modes {
377+ if s. info . suggest_eliding_modes {
419378 s. suggestion . push ( ( pat. span . with_hi ( ident. span . lo ( ) ) , String :: new ( ) ) ) ;
420379 s. binding_mode_count += 1 ;
421380 }
422381 }
423- if !s. suggest_eliding_modes
382+ if !s. info . suggest_eliding_modes
424383 && explicit_ba. 0 == ByRef :: No
425384 && let ByRef :: Yes ( mutbl) = mode. 0
426385 {
0 commit comments