11use crate :: check:: FnCtxt ;
22use rustc_infer:: infer:: InferOk ;
3+ use rustc_middle:: middle:: stability:: EvalResult ;
34use rustc_trait_selection:: infer:: InferCtxtExt as _;
45use rustc_trait_selection:: traits:: ObligationCause ;
56
@@ -363,18 +364,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
363364 }
364365 }
365366
366- let compatible_variants: Vec < ( String , Option < String > ) > = expected_adt
367+ let compatible_variants: Vec < ( String , _ , _ , Option < String > ) > = expected_adt
367368 . variants ( )
368369 . iter ( )
369370 . filter ( |variant| {
370- variant. fields . len ( ) == 1 && variant . ctor_kind == hir :: def :: CtorKind :: Fn
371+ variant. fields . len ( ) == 1
371372 } )
372373 . filter_map ( |variant| {
373374 let sole_field = & variant. fields [ 0 ] ;
374375
375376 let field_is_local = sole_field. did . is_local ( ) ;
376377 let field_is_accessible =
377- sole_field. vis . is_accessible_from ( expr. hir_id . owner . to_def_id ( ) , self . tcx ) ;
378+ sole_field. vis . is_accessible_from ( expr. hir_id . owner . to_def_id ( ) , self . tcx )
379+ // Skip suggestions for unstable public fields (for example `Pin::pointer`)
380+ && matches ! ( self . tcx. eval_stability( sole_field. did, None , expr. span, None ) , EvalResult :: Allow | EvalResult :: Unmarked ) ;
378381
379382 if !field_is_local && !field_is_accessible {
380383 return None ;
@@ -391,33 +394,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
391394 if let Some ( path) = variant_path. strip_prefix ( "std::prelude::" )
392395 && let Some ( ( _, path) ) = path. split_once ( "::" )
393396 {
394- return Some ( ( path. to_string ( ) , note_about_variant_field_privacy) ) ;
397+ return Some ( ( path. to_string ( ) , variant . ctor_kind , sole_field . name , note_about_variant_field_privacy) ) ;
395398 }
396- Some ( ( variant_path, note_about_variant_field_privacy) )
399+ Some ( ( variant_path, variant . ctor_kind , sole_field . name , note_about_variant_field_privacy) )
397400 } else {
398401 None
399402 }
400403 } )
401404 . collect ( ) ;
402405
403- let prefix = match self . maybe_get_struct_pattern_shorthand_field ( expr) {
404- Some ( ident) => format ! ( "{ident}: " ) ,
405- None => String :: new ( ) ,
406+ let suggestions_for = |variant : & _ , ctor, field_name| {
407+ let prefix = match self . maybe_get_struct_pattern_shorthand_field ( expr) {
408+ Some ( ident) => format ! ( "{ident}: " ) ,
409+ None => String :: new ( ) ,
410+ } ;
411+
412+ let ( open, close) = match ctor {
413+ hir:: def:: CtorKind :: Fn => ( "(" . to_owned ( ) , ")" ) ,
414+ hir:: def:: CtorKind :: Fictive => ( format ! ( " {{ {field_name}: " ) , " }" ) ,
415+
416+ // unit variants don't have fields
417+ hir:: def:: CtorKind :: Const => unreachable ! ( ) ,
418+ } ;
419+
420+ vec ! [
421+ ( expr. span. shrink_to_lo( ) , format!( "{prefix}{variant}{open}" ) ) ,
422+ ( expr. span. shrink_to_hi( ) , close. to_owned( ) ) ,
423+ ]
406424 } ;
407425
408426 match & compatible_variants[ ..] {
409427 [ ] => { /* No variants to format */ }
410- [ ( variant, note) ] => {
428+ [ ( variant, ctor_kind , field_name , note) ] => {
411429 // Just a single matching variant.
412430 err. multipart_suggestion_verbose (
413431 & format ! (
414432 "try wrapping the expression in `{variant}`{note}" ,
415433 note = note. as_deref( ) . unwrap_or( "" )
416434 ) ,
417- vec ! [
418- ( expr. span. shrink_to_lo( ) , format!( "{prefix}{variant}(" ) ) ,
419- ( expr. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
420- ] ,
435+ suggestions_for ( & * * variant, * ctor_kind, * field_name) ,
421436 Applicability :: MaybeIncorrect ,
422437 ) ;
423438 }
@@ -428,12 +443,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
428443 "try wrapping the expression in a variant of `{}`" ,
429444 self . tcx. def_path_str( expected_adt. did( ) )
430445 ) ,
431- compatible_variants. into_iter ( ) . map ( |( variant, _) | {
432- vec ! [
433- ( expr. span. shrink_to_lo( ) , format!( "{prefix}{variant}(" ) ) ,
434- ( expr. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
435- ]
436- } ) ,
446+ compatible_variants. into_iter ( ) . map (
447+ |( variant, ctor_kind, field_name, _) | {
448+ suggestions_for ( & variant, ctor_kind, field_name)
449+ } ,
450+ ) ,
437451 Applicability :: MaybeIncorrect ,
438452 ) ;
439453 }
0 commit comments