|
8 | 8 | //! * Functions called by the compiler itself.
|
9 | 9 |
|
10 | 10 | use crate::check_attr::target_from_impl_item;
|
11 |
| -use crate::errors::{LangItemOnIncorrectTarget, UnknownLangItem}; |
| 11 | +use crate::errors::{ |
| 12 | + DuplicateLangItem, IncorrectTarget, LangItemOnIncorrectTarget, UnknownLangItem, |
| 13 | +}; |
12 | 14 | use crate::weak_lang_items;
|
13 | 15 |
|
14 |
| -use rustc_errors::{pluralize, struct_span_err}; |
15 | 16 | use rustc_hir as hir;
|
16 | 17 | use rustc_hir::def::DefKind;
|
17 | 18 | use rustc_hir::def_id::DefId;
|
18 | 19 | use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
|
19 | 20 | use rustc_hir::{HirId, LangItem, LanguageItems, Target};
|
20 | 21 | use rustc_middle::ty::TyCtxt;
|
21 | 22 | use rustc_session::cstore::ExternCrate;
|
22 |
| -use rustc_span::Span; |
| 23 | +use rustc_span::{Span, Symbol}; |
23 | 24 |
|
24 | 25 | use rustc_middle::ty::query::Providers;
|
25 | 26 |
|
@@ -62,74 +63,72 @@ impl<'tcx> LanguageItemCollector<'tcx> {
|
62 | 63 | // Check for duplicates.
|
63 | 64 | if let Some(original_def_id) = self.items.items[item_index] {
|
64 | 65 | if original_def_id != item_def_id {
|
65 |
| - let lang_item = LangItem::from_u32(item_index as u32).unwrap(); |
66 |
| - let name = lang_item.name(); |
67 |
| - let mut err = match self.tcx.hir().span_if_local(item_def_id) { |
68 |
| - Some(span) => struct_span_err!( |
69 |
| - self.tcx.sess, |
70 |
| - span, |
71 |
| - E0152, |
72 |
| - "found duplicate lang item `{}`", |
73 |
| - name |
74 |
| - ), |
75 |
| - None => match self.tcx.extern_crate(item_def_id) { |
76 |
| - Some(ExternCrate { dependency_of, .. }) => { |
77 |
| - self.tcx.sess.struct_err(&format!( |
78 |
| - "duplicate lang item in crate `{}` (which `{}` depends on): `{}`.", |
79 |
| - self.tcx.crate_name(item_def_id.krate), |
80 |
| - self.tcx.crate_name(*dependency_of), |
81 |
| - name |
82 |
| - )) |
83 |
| - } |
84 |
| - _ => self.tcx.sess.struct_err(&format!( |
85 |
| - "duplicate lang item in crate `{}`: `{}`.", |
86 |
| - self.tcx.crate_name(item_def_id.krate), |
87 |
| - name |
88 |
| - )), |
89 |
| - }, |
| 66 | + let local_span = self.tcx.hir().span_if_local(item_def_id); |
| 67 | + let lang_item_name = LangItem::from_u32(item_index as u32).unwrap().name(); |
| 68 | + let crate_name = self.tcx.crate_name(item_def_id.krate); |
| 69 | + let mut dependency_of = Symbol::intern(""); |
| 70 | + let is_local = item_def_id.is_local(); |
| 71 | + let path = if is_local { |
| 72 | + String::new() |
| 73 | + } else { |
| 74 | + self.tcx |
| 75 | + .crate_extern_paths(item_def_id.krate) |
| 76 | + .iter() |
| 77 | + .map(|p| p.display().to_string()) |
| 78 | + .collect::<Vec<_>>() |
| 79 | + .join(", ") |
| 80 | + .into() |
90 | 81 | };
|
91 |
| - if let Some(span) = self.tcx.hir().span_if_local(original_def_id) { |
92 |
| - err.span_note(span, "the lang item is first defined here"); |
| 82 | + let first_defined_span = self.tcx.hir().span_if_local(original_def_id); |
| 83 | + let mut orig_crate_name = Symbol::intern(""); |
| 84 | + let mut orig_dependency_of = Symbol::intern(""); |
| 85 | + let orig_is_local = original_def_id.is_local(); |
| 86 | + let orig_path = if orig_is_local { |
| 87 | + String::new() |
93 | 88 | } else {
|
94 |
| - match self.tcx.extern_crate(original_def_id) { |
95 |
| - Some(ExternCrate { dependency_of, .. }) => { |
96 |
| - err.note(&format!( |
97 |
| - "the lang item is first defined in crate `{}` (which `{}` depends on)", |
98 |
| - self.tcx.crate_name(original_def_id.krate), |
99 |
| - self.tcx.crate_name(*dependency_of) |
100 |
| - )); |
101 |
| - } |
102 |
| - _ => { |
103 |
| - err.note(&format!( |
104 |
| - "the lang item is first defined in crate `{}`.", |
105 |
| - self.tcx.crate_name(original_def_id.krate) |
106 |
| - )); |
107 |
| - } |
| 89 | + self.tcx |
| 90 | + .crate_extern_paths(original_def_id.krate) |
| 91 | + .iter() |
| 92 | + .map(|p| p.display().to_string()) |
| 93 | + .collect::<Vec<_>>() |
| 94 | + .join(", ") |
| 95 | + .into() |
| 96 | + }; |
| 97 | + if first_defined_span.is_none() { |
| 98 | + orig_crate_name = self.tcx.crate_name(original_def_id.krate); |
| 99 | + if let Some(ExternCrate { dependency_of: inner_dependency_of, .. }) = |
| 100 | + self.tcx.extern_crate(original_def_id) |
| 101 | + { |
| 102 | + orig_dependency_of = self.tcx.crate_name(*inner_dependency_of); |
108 | 103 | }
|
109 |
| - let mut note_def = |which, def_id: DefId| { |
110 |
| - let crate_name = self.tcx.crate_name(def_id.krate); |
111 |
| - let note = if def_id.is_local() { |
112 |
| - format!("{} definition in the local crate (`{}`)", which, crate_name) |
113 |
| - } else { |
114 |
| - let paths: Vec<_> = self |
115 |
| - .tcx |
116 |
| - .crate_extern_paths(def_id.krate) |
117 |
| - .iter() |
118 |
| - .map(|p| p.display().to_string()) |
119 |
| - .collect(); |
120 |
| - format!( |
121 |
| - "{} definition in `{}` loaded from {}", |
122 |
| - which, |
123 |
| - crate_name, |
124 |
| - paths.join(", ") |
125 |
| - ) |
126 |
| - }; |
127 |
| - err.note(¬e); |
128 |
| - }; |
129 |
| - note_def("first", original_def_id); |
130 |
| - note_def("second", item_def_id); |
131 | 104 | }
|
132 |
| - err.emit(); |
| 105 | + |
| 106 | + let message = if local_span.is_some() { |
| 107 | + "duplicate" |
| 108 | + } else { |
| 109 | + match self.tcx.extern_crate(item_def_id) { |
| 110 | + Some(ExternCrate { dependency_of: inner_dependency_of, .. }) => { |
| 111 | + dependency_of = self.tcx.crate_name(*inner_dependency_of); |
| 112 | + "duplicate_in_crate_depends" |
| 113 | + } |
| 114 | + _ => "duplicate_in_crate", |
| 115 | + } |
| 116 | + }; |
| 117 | + |
| 118 | + self.tcx.sess.emit_err(DuplicateLangItem { |
| 119 | + local_span, |
| 120 | + lang_item_name, |
| 121 | + crate_name, |
| 122 | + dependency_of, |
| 123 | + is_local, |
| 124 | + path, |
| 125 | + first_defined_span, |
| 126 | + orig_crate_name, |
| 127 | + orig_dependency_of, |
| 128 | + orig_is_local, |
| 129 | + orig_path, |
| 130 | + message, |
| 131 | + }); |
133 | 132 | }
|
134 | 133 | }
|
135 | 134 |
|
@@ -162,41 +161,30 @@ impl<'tcx> LanguageItemCollector<'tcx> {
|
162 | 161 | None => (0, *item_span),
|
163 | 162 | };
|
164 | 163 |
|
| 164 | + let mut at_least = false; |
165 | 165 | let required = match lang_item.required_generics() {
|
166 |
| - GenericRequirement::Exact(num) if num != actual_num => { |
167 |
| - Some((format!("{}", num), pluralize!(num))) |
168 |
| - } |
| 166 | + GenericRequirement::Exact(num) if num != actual_num => Some(num), |
169 | 167 | GenericRequirement::Minimum(num) if actual_num < num => {
|
170 |
| - Some((format!("at least {}", num), pluralize!(num))) |
171 |
| - } |
| 168 | + at_least = true; |
| 169 | + Some(num)} |
| 170 | + , |
172 | 171 | // If the number matches, or there is no requirement, handle it normally
|
173 | 172 | _ => None,
|
174 | 173 | };
|
175 | 174 |
|
176 |
| - if let Some((range_str, pluralized)) = required { |
| 175 | + if let Some(num) = required { |
177 | 176 | // We are issuing E0718 "incorrect target" here, because while the
|
178 | 177 | // item kind of the target is correct, the target is still wrong
|
179 | 178 | // because of the wrong number of generic arguments.
|
180 |
| - struct_span_err!( |
181 |
| - self.tcx.sess, |
| 179 | + self.tcx.sess.emit_err(IncorrectTarget { |
182 | 180 | span,
|
183 |
| - E0718, |
184 |
| - "`{}` language item must be applied to a {} with {} generic argument{}", |
185 |
| - name, |
186 |
| - kind.descr(), |
187 |
| - range_str, |
188 |
| - pluralized, |
189 |
| - ) |
190 |
| - .span_label( |
191 | 181 | generics_span,
|
192 |
| - format!( |
193 |
| - "this {} has {} generic argument{}", |
194 |
| - kind.descr(), |
195 |
| - actual_num, |
196 |
| - pluralize!(actual_num), |
197 |
| - ), |
198 |
| - ) |
199 |
| - .emit(); |
| 182 | + name: name.as_str(), |
| 183 | + kind: kind.descr(), |
| 184 | + num, |
| 185 | + actual_num, |
| 186 | + at_least, |
| 187 | + }); |
200 | 188 |
|
201 | 189 | // return early to not collect the lang item
|
202 | 190 | return;
|
|
0 commit comments