|
1 | 1 | use std::cmp::Reverse;
|
| 2 | +use std::ptr; |
2 | 3 |
|
3 | 4 | use log::debug;
|
4 | 5 | use rustc::bug;
|
@@ -918,50 +919,81 @@ impl<'a> Resolver<'a> {
|
918 | 919 | err.emit();
|
919 | 920 | }
|
920 | 921 |
|
921 |
| - crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) { |
922 |
| - let PrivacyError { ident, binding, .. } = *privacy_error; |
923 |
| - let session = &self.session; |
924 |
| - let mk_struct_span_error = |is_constructor| { |
925 |
| - let mut descr = binding.res().descr().to_string(); |
926 |
| - if is_constructor { |
927 |
| - descr += " constructor"; |
928 |
| - } |
929 |
| - if binding.is_import() { |
930 |
| - descr += " import"; |
931 |
| - } |
932 |
| - |
933 |
| - let mut err = |
934 |
| - struct_span_err!(session, ident.span, E0603, "{} `{}` is private", descr, ident); |
935 |
| - |
936 |
| - err.span_label(ident.span, &format!("this {} is private", descr)); |
937 |
| - err.span_note( |
938 |
| - session.source_map().def_span(binding.span), |
939 |
| - &format!("the {} `{}` is defined here", descr, ident), |
940 |
| - ); |
941 |
| - |
942 |
| - err |
943 |
| - }; |
944 |
| - |
945 |
| - let mut err = if let NameBindingKind::Res( |
| 922 | + /// If the binding refers to a tuple struct constructor with fields, |
| 923 | + /// returns the span of its fields. |
| 924 | + fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> { |
| 925 | + if let NameBindingKind::Res( |
946 | 926 | Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id),
|
947 | 927 | _,
|
948 | 928 | ) = binding.kind
|
949 | 929 | {
|
950 | 930 | let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
|
951 | 931 | if let Some(fields) = self.field_names.get(&def_id) {
|
952 |
| - let mut err = mk_struct_span_error(true); |
953 | 932 | let first_field = fields.first().expect("empty field list in the map");
|
954 |
| - err.span_label( |
955 |
| - fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)), |
956 |
| - "a constructor is private if any of the fields is private", |
957 |
| - ); |
958 |
| - err |
959 |
| - } else { |
960 |
| - mk_struct_span_error(false) |
| 933 | + return Some(fields.iter().fold(first_field.span, |acc, field| acc.to(field.span))); |
961 | 934 | }
|
962 |
| - } else { |
963 |
| - mk_struct_span_error(false) |
964 |
| - }; |
| 935 | + } |
| 936 | + None |
| 937 | + } |
| 938 | + |
| 939 | + crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) { |
| 940 | + let PrivacyError { ident, binding, .. } = *privacy_error; |
| 941 | + |
| 942 | + let res = binding.res(); |
| 943 | + let ctor_fields_span = self.ctor_fields_span(binding); |
| 944 | + let plain_descr = res.descr().to_string(); |
| 945 | + let nonimport_descr = |
| 946 | + if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr }; |
| 947 | + let import_descr = nonimport_descr.clone() + " import"; |
| 948 | + let get_descr = |
| 949 | + |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr }; |
| 950 | + |
| 951 | + // Print the primary message. |
| 952 | + let descr = get_descr(binding); |
| 953 | + let mut err = |
| 954 | + struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident); |
| 955 | + err.span_label(ident.span, &format!("this {} is private", descr)); |
| 956 | + if let Some(span) = ctor_fields_span { |
| 957 | + err.span_label(span, "a constructor is private if any of the fields is private"); |
| 958 | + } |
| 959 | + |
| 960 | + // Print the whole import chain to make it easier to see what happens. |
| 961 | + let first_binding = binding; |
| 962 | + let mut next_binding = Some(binding); |
| 963 | + let mut next_ident = ident; |
| 964 | + while let Some(binding) = next_binding { |
| 965 | + let name = next_ident; |
| 966 | + next_binding = match binding.kind { |
| 967 | + _ if res == Res::Err => None, |
| 968 | + NameBindingKind::Import { binding, import, .. } => match import.kind { |
| 969 | + _ if binding.span.is_dummy() => None, |
| 970 | + ImportKind::Single { source, .. } => { |
| 971 | + next_ident = source; |
| 972 | + Some(binding) |
| 973 | + } |
| 974 | + ImportKind::Glob { .. } | ImportKind::MacroUse => Some(binding), |
| 975 | + ImportKind::ExternCrate { .. } => None, |
| 976 | + }, |
| 977 | + _ => None, |
| 978 | + }; |
| 979 | + |
| 980 | + let first = ptr::eq(binding, first_binding); |
| 981 | + let descr = get_descr(binding); |
| 982 | + let msg = format!( |
| 983 | + "{and_refers_to}the {item} `{name}`{which} is defined here{dots}", |
| 984 | + and_refers_to = if first { "" } else { "...and refers to " }, |
| 985 | + item = descr, |
| 986 | + name = name, |
| 987 | + which = if first { "" } else { " which" }, |
| 988 | + dots = if next_binding.is_some() { "..." } else { "" }, |
| 989 | + ); |
| 990 | + let def_span = self.session.source_map().def_span(binding.span); |
| 991 | + let mut note_span = MultiSpan::from_span(def_span); |
| 992 | + if !first && binding.vis == ty::Visibility::Public { |
| 993 | + note_span.push_span_label(def_span, "consider importing it directly".into()); |
| 994 | + } |
| 995 | + err.span_note(note_span, &msg); |
| 996 | + } |
965 | 997 |
|
966 | 998 | err.emit();
|
967 | 999 | }
|
|
0 commit comments