@@ -1449,44 +1449,73 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
14491449 ) ,
14501450 _ => ( ": val" , "literal" , Applicability :: HasPlaceholders , None ) ,
14511451 } ;
1452- let field_ids = self . r . field_def_ids ( def_id) ;
1453- let ( fields, applicability) = match field_ids {
1454- Some ( field_ids) => {
1455- let fields = field_ids. iter ( ) . map ( |& id| self . r . tcx . item_name ( id) ) ;
1456-
1457- let fields = if let Some ( old_fields) = old_fields {
1458- fields
1459- . enumerate ( )
1460- . map ( |( idx, new) | ( new, old_fields. get ( idx) ) )
1461- . map ( |( new, old) | {
1462- let new = new. to_ident_string ( ) ;
1463- if let Some ( Some ( old) ) = old
1464- && new != * old
1465- {
1466- format ! ( "{new}: {old}" )
1467- } else {
1468- new
1469- }
1470- } )
1471- . collect :: < Vec < String > > ( )
1472- } else {
1473- fields. map ( |f| format ! ( "{f}{tail}" ) ) . collect :: < Vec < String > > ( )
1474- } ;
14751452
1476- ( fields. join ( ", " ) , applicability)
1453+ let fields = match def_id. as_local ( ) {
1454+ Some ( def_id) => {
1455+ self . r . struct_constructors . get ( & def_id) . cloned ( ) . map ( |( _, _, f) | f)
14771456 }
1478- None => ( "/* fields */" . to_string ( ) , Applicability :: HasPlaceholders ) ,
1479- } ;
1480- let pad = match field_ids {
1481- Some ( field_ids) if field_ids. is_empty ( ) => "" ,
1482- _ => " " ,
1457+ None => Some (
1458+ self . r
1459+ . tcx
1460+ . associated_item_def_ids ( def_id)
1461+ . iter ( )
1462+ . map ( |field_id| self . r . tcx . visibility ( field_id) )
1463+ . collect ( ) ,
1464+ ) ,
14831465 } ;
1484- err. span_suggestion (
1485- span,
1486- format ! ( "use struct {descr} syntax instead" ) ,
1487- format ! ( "{path_str} {{{pad}{fields}{pad}}}" ) ,
1488- applicability,
1489- ) ;
1466+
1467+ let hidden_fields = fields. map_or ( false , |fields| {
1468+ fields
1469+ . iter ( )
1470+ . filter ( |vis| {
1471+ !self . r . is_accessible_from ( * * vis, self . parent_scope . module )
1472+ } )
1473+ . next ( )
1474+ . is_some ( )
1475+ } ) ;
1476+
1477+ if !hidden_fields {
1478+ // If the fields of the type are private, we shouldn't be suggesting using
1479+ // the struct literal syntax at all, as that will cause a subsequent error.
1480+ let field_ids = self . r . field_def_ids ( def_id) ;
1481+ let ( fields, applicability) = match field_ids {
1482+ Some ( field_ids) => {
1483+ let fields = field_ids. iter ( ) . map ( |& id| self . r . tcx . item_name ( id) ) ;
1484+
1485+ let fields = if let Some ( old_fields) = old_fields {
1486+ fields
1487+ . enumerate ( )
1488+ . map ( |( idx, new) | ( new, old_fields. get ( idx) ) )
1489+ . map ( |( new, old) | {
1490+ let new = new. to_ident_string ( ) ;
1491+ if let Some ( Some ( old) ) = old
1492+ && new != * old
1493+ {
1494+ format ! ( "{new}: {old}" )
1495+ } else {
1496+ new
1497+ }
1498+ } )
1499+ . collect :: < Vec < String > > ( )
1500+ } else {
1501+ fields. map ( |f| format ! ( "{f}{tail}" ) ) . collect :: < Vec < String > > ( )
1502+ } ;
1503+
1504+ ( fields. join ( ", " ) , applicability)
1505+ }
1506+ None => ( "/* fields */" . to_string ( ) , Applicability :: HasPlaceholders ) ,
1507+ } ;
1508+ let pad = match field_ids {
1509+ Some ( field_ids) if field_ids. is_empty ( ) => "" ,
1510+ _ => " " ,
1511+ } ;
1512+ err. span_suggestion (
1513+ span,
1514+ format ! ( "use struct {descr} syntax instead" ) ,
1515+ format ! ( "{path_str} {{{pad}{fields}{pad}}}" ) ,
1516+ applicability,
1517+ ) ;
1518+ }
14901519 }
14911520 _ => {
14921521 err. span_label ( span, fallback_label. to_string ( ) ) ;
0 commit comments