Skip to content

Commit 898f36c

Browse files
committed
Auto merge of #65153 - da-x:issue-58017, r=petrochenkov
Improve message when attempting to instantiate tuple structs with private fields Fixes #58017, fixes #39703. ``` error[E0603]: tuple struct `Error` is private --> main.rs:22:16 | 2 | pub struct Error(usize, pub usize, usize); | ----- ----- field is private | | | field is private ... 22 | let x = a::Error(3, 1, 2); | ^^^^^ | = note: a tuple struct constructor is private if any of its fields is private ```
2 parents 58b5491 + 48f8bed commit 898f36c

File tree

9 files changed

+222
-120
lines changed

9 files changed

+222
-120
lines changed

src/librustc_metadata/cstore_impl.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use syntax::source_map;
3333
use syntax::edition::Edition;
3434
use syntax::parse::source_file_to_stream;
3535
use syntax::parse::parser::emit_unclosed_delims;
36+
use syntax::source_map::Spanned;
3637
use syntax::symbol::Symbol;
3738
use syntax_pos::{Span, FileName};
3839
use rustc_index::bit_set::BitSet;
@@ -424,8 +425,8 @@ impl cstore::CStore {
424425
self.get_crate_data(cnum).root.edition
425426
}
426427

427-
pub fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name> {
428-
self.get_crate_data(def.krate).get_struct_field_names(def.index)
428+
pub fn struct_field_names_untracked(&self, def: DefId, sess: &Session) -> Vec<Spanned<Symbol>> {
429+
self.get_crate_data(def.krate).get_struct_field_names(def.index, sess)
429430
}
430431

431432
pub fn ctor_kind_untracked(&self, def: DefId) -> def::CtorKind {

src/librustc_metadata/decoder.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use std::u32;
2929
use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
3030
use syntax::attr;
3131
use syntax::ast::{self, Ident};
32-
use syntax::source_map;
32+
use syntax::source_map::{self, respan, Spanned};
3333
use syntax::symbol::{Symbol, sym};
3434
use syntax::ext::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension};
3535
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, symbol::{InternedString}};
@@ -1021,11 +1021,11 @@ impl<'a, 'tcx> CrateMetadata {
10211021
Lrc::from(self.get_attributes(&item, sess))
10221022
}
10231023

1024-
pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {
1024+
pub fn get_struct_field_names(&self, id: DefIndex, sess: &Session) -> Vec<Spanned<ast::Name>> {
10251025
self.entry(id)
10261026
.children
10271027
.decode(self)
1028-
.map(|index| self.item_name(index))
1028+
.map(|index| respan(self.get_span(index, sess), self.item_name(index)))
10291029
.collect()
10301030
}
10311031

src/librustc_resolve/build_reduced_graph.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use syntax::ext::hygiene::ExpnId;
3838
use syntax::feature_gate::is_builtin_attr;
3939
use syntax::parse::token::{self, Token};
4040
use syntax::{span_err, struct_span_err};
41+
use syntax::source_map::{respan, Spanned};
4142
use syntax::symbol::{kw, sym};
4243
use syntax::visit::{self, Visitor};
4344

@@ -301,7 +302,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
301302
}
302303
}
303304

304-
fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Name>) {
305+
fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Spanned<Name>>) {
305306
if !field_names.is_empty() {
306307
self.r.field_names.insert(def_id, field_names);
307308
}
@@ -752,12 +753,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
752753
}
753754

754755
// Record field names for error reporting.
755-
let field_names = struct_def.fields().iter().filter_map(|field| {
756+
let field_names = struct_def.fields().iter().map(|field| {
756757
let field_vis = self.resolve_visibility(&field.vis);
757758
if ctor_vis.is_at_least(field_vis, &*self.r) {
758759
ctor_vis = field_vis;
759760
}
760-
field.ident.map(|ident| ident.name)
761+
respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name))
761762
}).collect();
762763
let item_def_id = self.r.definitions.local_def_id(item.id);
763764
self.insert_field_names(item_def_id, field_names);
@@ -779,9 +780,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
779780
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
780781

781782
// Record field names for error reporting.
782-
let field_names = vdata.fields().iter().filter_map(|field| {
783+
let field_names = vdata.fields().iter().map(|field| {
783784
self.resolve_visibility(&field.vis);
784-
field.ident.map(|ident| ident.name)
785+
respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name))
785786
}).collect();
786787
let item_def_id = self.r.definitions.local_def_id(item.id);
787788
self.insert_field_names(item_def_id, field_names);
@@ -895,7 +896,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
895896
// Record some extra data for better diagnostics.
896897
match res {
897898
Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => {
898-
let field_names = self.r.cstore.struct_field_names_untracked(def_id);
899+
let field_names =
900+
self.r.cstore.struct_field_names_untracked(def_id, self.r.session);
899901
self.insert_field_names(def_id, field_names);
900902
}
901903
Res::Def(DefKind::Method, def_id) => {

src/librustc_resolve/late/diagnostics.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,8 @@ impl<'a> LateResolutionVisitor<'a, '_> {
497497
Res::Def(DefKind::Struct, did) | Res::Def(DefKind::Union, did)
498498
if resolution.unresolved_segments() == 0 => {
499499
if let Some(field_names) = self.r.field_names.get(&did) {
500-
if field_names.iter().any(|&field_name| ident.name == field_name) {
500+
if field_names.iter()
501+
.any(|&field_name| ident.name == field_name.node) {
501502
return Some(AssocSuggestion::Field);
502503
}
503504
}

src/librustc_resolve/lib.rs

+14-19
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use rustc::hir::def::{self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrK
2929
use rustc::hir::def::Namespace::*;
3030
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
3131
use rustc::hir::{TraitMap, GlobMap};
32-
use rustc::ty;
32+
use rustc::ty::{self, DefIdTree};
3333
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
3434
use rustc::span_bug;
3535

@@ -46,6 +46,7 @@ use syntax::attr;
4646
use syntax::ast::{CRATE_NODE_ID, Crate};
4747
use syntax::ast::{ItemKind, Path};
4848
use syntax::{struct_span_err, unwrap_or};
49+
use syntax::source_map::Spanned;
4950

5051
use syntax_pos::{Span, DUMMY_SP};
5152
use errors::{Applicability, DiagnosticBuilder};
@@ -829,7 +830,7 @@ pub struct Resolver<'a> {
829830

830831
/// Names of fields of an item `DefId` accessible with dot syntax.
831832
/// Used for hints during error reporting.
832-
field_names: FxHashMap<DefId, Vec<Name>>,
833+
field_names: FxHashMap<DefId, Vec<Spanned<Name>>>,
833834

834835
/// All imports known to succeed or fail.
835836
determined_imports: Vec<&'a ImportDirective<'a>>,
@@ -994,7 +995,7 @@ impl<'a> AsMut<Resolver<'a>> for Resolver<'a> {
994995
fn as_mut(&mut self) -> &mut Resolver<'a> { self }
995996
}
996997

997-
impl<'a, 'b> ty::DefIdTree for &'a Resolver<'b> {
998+
impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
998999
fn parent(self, id: DefId) -> Option<DefId> {
9991000
match id.krate {
10001001
LOCAL_CRATE => self.definitions.def_key(id.index).parent,
@@ -2386,23 +2387,17 @@ impl<'a> Resolver<'a> {
23862387
binding.res().descr(),
23872388
ident.name,
23882389
);
2389-
// FIXME: use the ctor's `def_id` to check wether any of the fields is not visible
2390-
match binding.kind {
2391-
NameBindingKind::Res(Res::Def(DefKind::Ctor(
2392-
CtorOf::Struct,
2393-
CtorKind::Fn,
2394-
), _def_id), _) => {
2395-
err.note("a tuple struct constructor is private if any of its fields \
2396-
is private");
2397-
}
2398-
NameBindingKind::Res(Res::Def(DefKind::Ctor(
2399-
CtorOf::Variant,
2400-
CtorKind::Fn,
2401-
), _def_id), _) => {
2402-
err.note("a tuple variant constructor is private if any of its fields \
2403-
is private");
2390+
if let NameBindingKind::Res(
2391+
Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id), _
2392+
) = binding.kind {
2393+
let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
2394+
if let Some(fields) = self.field_names.get(&def_id) {
2395+
let first_field = fields.first().expect("empty field list in the map");
2396+
err.span_label(
2397+
fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)),
2398+
"a tuple struct constructor is private if any of its fields is private",
2399+
);
24042400
}
2405-
_ => {}
24062401
}
24072402
err.emit();
24082403
}

0 commit comments

Comments
 (0)