22
33mod check_match;
44mod const_to_pat;
5+ mod migration;
56
67use std:: cmp:: Ordering ;
78
89use rustc_abi:: { FieldIdx , Integer } ;
9- use rustc_errors:: MultiSpan ;
1010use rustc_errors:: codes:: * ;
1111use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
1212use rustc_hir:: pat_util:: EnumerateAndAdjustIterator ;
13- use rustc_hir:: { self as hir, ByRef , Mutability , RangeEnd } ;
13+ use rustc_hir:: { self as hir, RangeEnd } ;
1414use rustc_index:: Idx ;
15- use rustc_lint as lint;
1615use rustc_middle:: mir:: interpret:: LitToConstInput ;
1716use rustc_middle:: thir:: {
1817 Ascription , FieldPat , LocalVarId , Pat , PatKind , PatRange , PatRangeBoundary ,
@@ -25,8 +24,8 @@ use rustc_span::{ErrorGuaranteed, Span};
2524use tracing:: { debug, instrument} ;
2625
2726pub ( crate ) use self :: check_match:: check_match;
27+ use self :: migration:: PatMigration ;
2828use crate :: errors:: * ;
29- use crate :: fluent_generated as fluent;
3029use crate :: thir:: util:: UserAnnotatedTyHelpers ;
3130
3231struct PatCtxt < ' a , ' tcx > {
@@ -35,7 +34,7 @@ struct PatCtxt<'a, 'tcx> {
3534 typeck_results : & ' a ty:: TypeckResults < ' tcx > ,
3635
3736 /// Used by the Rust 2024 migration lint.
38- rust_2024_migration_suggestion : Option < Rust2024IncompatiblePatSugg < ' a > > ,
37+ rust_2024_migration : Option < PatMigration < ' a > > ,
3938}
4039
4140pub ( super ) fn pat_from_hir < ' a , ' tcx > (
@@ -48,42 +47,15 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
4847 tcx,
4948 typing_env,
5049 typeck_results,
51- rust_2024_migration_suggestion : typeck_results
50+ rust_2024_migration : typeck_results
5251 . rust_2024_migration_desugared_pats ( )
5352 . get ( pat. hir_id )
54- . map ( |labels| Rust2024IncompatiblePatSugg {
55- suggestion : Vec :: new ( ) ,
56- ref_pattern_count : 0 ,
57- binding_mode_count : 0 ,
58- labels : labels. as_slice ( ) ,
59- } ) ,
53+ . map ( PatMigration :: new) ,
6054 } ;
6155 let result = pcx. lower_pattern ( pat) ;
6256 debug ! ( "pat_from_hir({:?}) = {:?}" , pat, result) ;
63- if let Some ( sugg) = pcx. rust_2024_migration_suggestion {
64- let mut spans = MultiSpan :: from_spans ( sugg. labels . iter ( ) . map ( |( span, _) | * span) . collect ( ) ) ;
65- for ( span, label) in sugg. labels {
66- spans. push_span_label ( * span, label. clone ( ) ) ;
67- }
68- // If a relevant span is from at least edition 2024, this is a hard error.
69- let is_hard_error = spans. primary_spans ( ) . iter ( ) . any ( |span| span. at_least_rust_2024 ( ) ) ;
70- if is_hard_error {
71- let mut err =
72- tcx. dcx ( ) . struct_span_err ( spans, fluent:: mir_build_rust_2024_incompatible_pat) ;
73- if let Some ( info) = lint:: builtin:: RUST_2024_INCOMPATIBLE_PAT . future_incompatible {
74- // provide the same reference link as the lint
75- err. note ( format ! ( "for more information, see {}" , info. reference) ) ;
76- }
77- err. subdiagnostic ( sugg) ;
78- err. emit ( ) ;
79- } else {
80- tcx. emit_node_span_lint (
81- lint:: builtin:: RUST_2024_INCOMPATIBLE_PAT ,
82- pat. hir_id ,
83- spans,
84- Rust2024IncompatiblePat { sugg } ,
85- ) ;
86- }
57+ if let Some ( m) = pcx. rust_2024_migration {
58+ m. emit ( tcx, pat. hir_id ) ;
8759 }
8860 result
8961}
@@ -129,25 +101,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
129101 } )
130102 } ) ;
131103
132- if let Some ( s ) = & mut self . rust_2024_migration_suggestion
104+ if let Some ( m ) = & mut self . rust_2024_migration
133105 && !adjustments. is_empty ( )
134106 {
135- let suggestion_str: String = adjustments
136- . iter ( )
137- . map ( |ref_ty| {
138- let & ty:: Ref ( _, _, mutbl) = ref_ty. kind ( ) else {
139- span_bug ! ( pat. span, "pattern implicitly dereferences a non-ref type" ) ;
140- } ;
141-
142- match mutbl {
143- ty:: Mutability :: Not => "&" ,
144- ty:: Mutability :: Mut => "&mut " ,
145- }
146- } )
147- . collect ( ) ;
148- s. suggestion . push ( ( pat. span . shrink_to_lo ( ) , suggestion_str) ) ;
149- s. ref_pattern_count += adjustments. len ( ) ;
150- } ;
107+ m. visit_implicit_derefs ( pat. span , adjustments) ;
108+ }
151109
152110 adjusted_pat
153111 }
@@ -364,19 +322,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
364322 . get ( pat. hir_id )
365323 . expect ( "missing binding mode" ) ;
366324
367- if let Some ( s) = & mut self . rust_2024_migration_suggestion
368- && explicit_ba. 0 == ByRef :: No
369- && let ByRef :: Yes ( mutbl) = mode. 0
370- {
371- let sugg_str = match mutbl {
372- Mutability :: Not => "ref " ,
373- Mutability :: Mut => "ref mut " ,
374- } ;
375- s. suggestion . push ( (
376- pat. span . with_lo ( ident. span . lo ( ) ) . shrink_to_lo ( ) ,
377- sugg_str. to_owned ( ) ,
378- ) ) ;
379- s. binding_mode_count += 1 ;
325+ if let Some ( m) = & mut self . rust_2024_migration {
326+ m. visit_binding ( pat. span , mode, explicit_ba, ident) ;
380327 }
381328
382329 // A ref x pattern is the same node used for x, and as such it has
0 commit comments