diff options
Diffstat (limited to 'compiler/rustc_resolve/src/diagnostics.rs')
-rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 84 |
1 files changed, 47 insertions, 37 deletions
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7add59ac6..0c9d30608 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -12,10 +12,10 @@ use rustc_errors::{struct_span_err, SuggestionStyle}; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS}; -use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::PrimTy; use rustc_middle::bug; -use rustc_middle::ty::{DefIdTree, TyCtxt}; +use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE; use rustc_session::lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS; use rustc_session::lint::BuiltinLintDiagnostics; @@ -555,25 +555,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return err; } Res::SelfTyAlias { alias_to: def_id, .. } => { - if let Some(impl_span) = self.opt_span(def_id) { - err.span_label( - reduce_impl_span_to_impl_keyword(sm, impl_span), - "`Self` type implicitly declared here, by this `impl`", - ); - } + err.span_label( + reduce_impl_span_to_impl_keyword(sm, self.def_span(def_id)), + "`Self` type implicitly declared here, by this `impl`", + ); err.span_label(span, "use a type here instead"); return err; } Res::Def(DefKind::TyParam, def_id) => { - if let Some(span) = self.opt_span(def_id) { - err.span_label(span, "type parameter from outer function"); - } + err.span_label(self.def_span(def_id), "type parameter from outer function"); def_id } Res::Def(DefKind::ConstParam, def_id) => { - if let Some(span) = self.opt_span(def_id) { - err.span_label(span, "const parameter from outer function"); - } + err.span_label( + self.def_span(def_id), + "const parameter from outer function", + ); def_id } _ => { @@ -589,7 +586,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Try to retrieve the span of the function signature and generate a new // message with a local type or const parameter. let sugg_msg = "try using a local generic parameter instead"; - let name = self.opt_name(def_id).unwrap_or(sym::T); + let name = self.tcx.item_name(def_id); let (span, snippet) = if span.is_empty() { let snippet = format!("<{}>", name); (span, snippet) @@ -1197,7 +1194,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { segms.push(ast::PathSegment::from_ident(ident)); let path = Path { span: name_binding.span, segments: segms, tokens: None }; let did = match res { - Res::Def(DefKind::Ctor(..), did) => this.opt_parent(did), + Res::Def(DefKind::Ctor(..), did) => this.tcx.opt_parent(did), _ => res.opt_def_id(), }; @@ -1216,15 +1213,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // a note about editions let note = if let Some(did) = did { let requires_note = !did.is_local() - && this.cstore().item_attrs_untracked(did, this.tcx.sess).any( + && this.tcx.get_attrs(did, sym::rustc_diagnostic_item).any( |attr| { - if attr.has_name(sym::rustc_diagnostic_item) { - [sym::TryInto, sym::TryFrom, sym::FromIterator] - .map(|x| Some(x)) - .contains(&attr.value_str()) - } else { - false - } + [sym::TryInto, sym::TryFrom, sym::FromIterator] + .map(|x| Some(x)) + .contains(&attr.value_str()) }, ); @@ -1373,8 +1366,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if ident.name == kw::Default && let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind - && let Some(span) = self.opt_span(def_id) { + let span = self.def_span(def_id); let source_map = self.tcx.sess.source_map(); let head_span = source_map.guess_head_span(span); if let Ok(head) = source_map.span_to_snippet(head_span) { @@ -1450,11 +1443,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(suggestion) if suggestion.candidate == kw::Underscore => return false, Some(suggestion) => suggestion, }; - let def_span = suggestion.res.opt_def_id().and_then(|def_id| match def_id.krate { - LOCAL_CRATE => self.opt_span(def_id), - _ => Some(self.cstore().get_span_untracked(def_id, self.tcx.sess)), - }); - if let Some(def_span) = def_span { + if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) { if span.overlaps(def_span) { // Don't suggest typo suggestion for itself like in the following: // error[E0423]: expected function, tuple struct or tuple variant, found struct `X` @@ -1591,9 +1580,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ctor_def_id, )) = binding.kind { - let def_id = self.parent(ctor_def_id); - let fields = self.field_names.get(&def_id)?; - return fields.iter().map(|name| name.span).reduce(Span::to); // None for `struct Foo()` + let def_id = self.tcx.parent(ctor_def_id); + return self + .field_def_ids(def_id)? + .iter() + .map(|&field_id| self.def_span(field_id)) + .reduce(Span::to); // None for `struct Foo()` } None } @@ -1615,7 +1607,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut err = struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident); err.span_label(ident.span, &format!("private {}", descr)); - if let Some(span) = ctor_fields_span { + + let mut non_exhaustive = None; + // If an ADT is foreign and marked as `non_exhaustive`, then that's + // probably why we have the privacy error. + // Otherwise, point out if the struct has any private fields. + if let Some(def_id) = res.opt_def_id() + && !def_id.is_local() + && let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive) + { + non_exhaustive = Some(attr.span); + } else if let Some(span) = ctor_fields_span { err.span_label(span, "a constructor is private if any of the fields is private"); if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) { err.multipart_suggestion_verbose( @@ -1664,6 +1666,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !first && binding.vis.is_public() { note_span.push_span_label(def_span, "consider importing it directly"); } + // Final step in the import chain, point out if the ADT is `non_exhaustive` + // which is probably why this privacy violation occurred. + if next_binding.is_none() && let Some(span) = non_exhaustive { + note_span.push_span_label( + span, + format!("cannot be constructed because it is `#[non_exhaustive]`"), + ); + } err.span_note(note_span, &msg); } @@ -1677,8 +1687,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ) -> Option<Symbol> { let mut candidates = self .extern_prelude - .iter() - .map(|(ident, _)| ident.name) + .keys() + .map(|ident| ident.name) .chain( self.module_map .iter() @@ -2015,7 +2025,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // 1) some consistent ordering for emitted diagnostics, and // 2) `std` suggestions before `core` suggestions. let mut extern_crate_names = - self.extern_prelude.iter().map(|(ident, _)| ident.name).collect::<Vec<_>>(); + self.extern_prelude.keys().map(|ident| ident.name).collect::<Vec<_>>(); extern_crate_names.sort_by(|a, b| b.as_str().partial_cmp(a.as_str()).unwrap()); for name in extern_crate_names.into_iter() { |