@@ -917,54 +917,71 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
917917 self . suggest_using_enum_variant ( err, source, def_id, span) ;
918918 }
919919 ( Res :: Def ( DefKind :: Struct , def_id) , _) if ns == ValueNS => {
920- if let Some ( ( ctor_def, ctor_vis, fields) ) =
921- self . r . struct_constructors . get ( & def_id) . cloned ( )
920+ let ( ctor_def, ctor_vis, fields) =
921+ if let Some ( struct_ctor) = self . r . struct_constructors . get ( & def_id) . cloned ( ) {
922+ struct_ctor
923+ } else {
924+ bad_struct_syntax_suggestion ( def_id) ;
925+ return true ;
926+ } ;
927+
928+ let is_accessible = self . r . is_accessible_from ( ctor_vis, self . parent_scope . module ) ;
929+ if !is_expected ( ctor_def) || is_accessible {
930+ return true ;
931+ }
932+
933+ let field_spans = match source {
934+ // e.g. `if let Enum::TupleVariant(field1, field2) = _`
935+ PathSource :: TupleStruct ( _, pattern_spans) => {
936+ err. set_primary_message (
937+ "cannot match against a tuple struct which contains private fields" ,
938+ ) ;
939+
940+ // Use spans of the tuple struct pattern.
941+ Some ( Vec :: from ( pattern_spans) )
942+ }
943+ // e.g. `let _ = Enum::TupleVariant(field1, field2);`
944+ _ if source. is_call ( ) => {
945+ err. set_primary_message (
946+ "cannot initialize a tuple struct which contains private fields" ,
947+ ) ;
948+
949+ // Use spans of the tuple struct definition.
950+ self . r
951+ . field_names
952+ . get ( & def_id)
953+ . map ( |fields| fields. iter ( ) . map ( |f| f. span ) . collect :: < Vec < _ > > ( ) )
954+ }
955+ _ => None ,
956+ } ;
957+
958+ if let Some ( spans) =
959+ field_spans. filter ( |spans| spans. len ( ) > 0 && fields. len ( ) == spans. len ( ) )
922960 {
923- let accessible_ctor =
924- self . r . is_accessible_from ( ctor_vis, self . parent_scope . module ) ;
925- if is_expected ( ctor_def) && !accessible_ctor {
926- let mut better_diag = false ;
927- if let PathSource :: TupleStruct ( _, pattern_spans) = source {
928- if pattern_spans. len ( ) > 0 && fields. len ( ) == pattern_spans. len ( ) {
929- let non_visible_spans: Vec < Span > = fields
930- . iter ( )
931- . zip ( pattern_spans. iter ( ) )
932- . filter_map ( |( vis, span) | {
933- match self
934- . r
935- . is_accessible_from ( * vis, self . parent_scope . module )
936- {
937- true => None ,
938- false => Some ( * span) ,
939- }
940- } )
941- . collect ( ) ;
942- // Extra check to be sure
943- if non_visible_spans. len ( ) > 0 {
944- let mut m: rustc_span:: MultiSpan =
945- non_visible_spans. clone ( ) . into ( ) ;
946- non_visible_spans. into_iter ( ) . for_each ( |s| {
947- m. push_span_label ( s, "private field" . to_string ( ) )
948- } ) ;
949- err. span_note (
950- m,
951- "constructor is not visible here due to private fields" ,
952- ) ;
953- better_diag = true ;
954- }
955- }
956- }
961+ let non_visible_spans: Vec < Span > = fields
962+ . iter ( )
963+ . zip ( spans. iter ( ) )
964+ . filter ( |( vis, _) | {
965+ !self . r . is_accessible_from ( * * vis, self . parent_scope . module )
966+ } )
967+ . map ( |( _, span) | * span)
968+ . collect ( ) ;
957969
958- if !better_diag {
959- err . span_label (
960- span ,
961- "constructor is not visible here due to private fields" . to_string ( ) ,
962- ) ;
963- }
970+ if non_visible_spans . len ( ) > 0 {
971+ let mut m : rustc_span :: MultiSpan = non_visible_spans . clone ( ) . into ( ) ;
972+ non_visible_spans
973+ . into_iter ( )
974+ . for_each ( |s| m . push_span_label ( s , "private field" . to_string ( ) ) ) ;
975+ err . span_note ( m , "constructor is not visible here due to private fields" ) ;
964976 }
965- } else {
966- bad_struct_syntax_suggestion ( def_id ) ;
977+
978+ return true ;
967979 }
980+
981+ err. span_label (
982+ span,
983+ "constructor is not visible here due to private fields" . to_string ( ) ,
984+ ) ;
968985 }
969986 (
970987 Res :: Def (
0 commit comments