1use std::iter;
2
3use flux_middle::ExternSpecMappingErr;
4use flux_rustc_bridge::lowering;
5use flux_syntax::surface;
6use rustc_errors::Diagnostic;
7use rustc_hir as hir;
8use rustc_hir::{
9 BodyId, OwnerId,
10 def_id::{DefId, LocalDefId},
11};
12use rustc_middle::ty::{self, TyCtxt};
13use rustc_span::{ErrorGuaranteed, Span, symbol::kw};
14
15use super::{FluxAttrs, SpecCollector};
16
17type Result<T = ()> = std::result::Result<T, ErrorGuaranteed>;
18
19pub(super) struct ExternSpecCollector<'a, 'sess, 'tcx> {
20 inner: &'a mut SpecCollector<'sess, 'tcx>,
21 block: &'tcx hir::Block<'tcx>,
23}
24
25struct ExternImplItem {
26 impl_id: DefId,
27 item_id: DefId,
28}
29
30impl<'a, 'sess, 'tcx> ExternSpecCollector<'a, 'sess, 'tcx> {
31 pub(super) fn collect(inner: &'a mut SpecCollector<'sess, 'tcx>, body_id: BodyId) -> Result {
32 Self::new(inner, body_id)?.run()
33 }
34
35 fn new(inner: &'a mut SpecCollector<'sess, 'tcx>, body_id: BodyId) -> Result<Self> {
36 let body = inner.tcx.hir_body(body_id);
37 if let hir::ExprKind::Block(block, _) = body.value.kind {
38 Ok(Self { inner, block })
39 } else {
40 Err(inner
41 .errors
42 .emit(errors::MalformedExternSpec::new(body.value.span)))
43 }
44 }
45
46 fn run(mut self) -> Result {
47 let item = self.item_at(0)?;
48
49 let attrs = self
50 .inner
51 .parse_attrs_and_report_dups(item.owner_id.def_id)?;
52
53 match &item.kind {
54 hir::ItemKind::Fn { .. } => self.collect_extern_fn(item, attrs),
55 hir::ItemKind::Enum(_, _, enum_def) => {
56 self.collect_extern_enum(item.owner_id, enum_def, attrs)
57 }
58 hir::ItemKind::Struct(_, _, variant) => {
59 self.collect_extern_struct(item.owner_id, variant, attrs)
60 }
61 hir::ItemKind::Trait(_, _, _, _, _, bounds, items) => {
62 self.collect_extern_trait(item.owner_id, bounds, items, attrs)
63 }
64 hir::ItemKind::Impl(impl_) => self.collect_extern_impl(item.owner_id, impl_, attrs),
65 _ => Err(self.malformed()),
66 }
67 }
68
69 fn collect_extern_fn(&mut self, item: &hir::Item, mut attrs: FluxAttrs) -> Result {
70 if attrs.has_attrs() {
71 let sig = attrs.fn_sig();
72 self.inner.check_fn_sig_name(item.owner_id, sig.as_ref())?;
73 let node_id = self.inner.next_node_id();
74 self.inner.insert_item(
75 item.owner_id,
76 surface::Item {
77 attrs: attrs.into_attr_vec(),
78 kind: surface::ItemKind::Fn(sig),
79 node_id,
80 },
81 )?;
82 }
83
84 let extern_id = self.extract_extern_id_from_fn(item)?;
85 self.insert_extern_id(item.owner_id.def_id, extern_id)?;
86 self.check_generics(item.owner_id, extern_id)?;
87
88 Ok(())
89 }
90
91 fn collect_extern_struct(
92 &mut self,
93 struct_id: OwnerId,
94 variant: &hir::VariantData,
95 attrs: FluxAttrs,
96 ) -> Result {
97 let dummy_struct = self.item_at(1)?;
98 self.inner.specs.insert_dummy(dummy_struct.owner_id.def_id);
99
100 let extern_id = self.extract_extern_id_from_struct(dummy_struct).unwrap();
101 self.insert_extern_id(struct_id.def_id, extern_id)?;
102 self.check_generics(struct_id, extern_id)?;
103
104 if let Some(ctor_id) = variant.ctor_def_id() {
105 self.inner.specs.insert_dummy(ctor_id);
106 }
107
108 self.inner.collect_struct_def(struct_id, attrs, variant)?;
109
110 Ok(())
111 }
112
113 fn collect_extern_enum(
114 &mut self,
115 enum_id: OwnerId,
116 enum_def: &hir::EnumDef,
117 attrs: FluxAttrs,
118 ) -> Result {
119 let dummy_struct = self.item_at(1)?;
120 self.inner.specs.insert_dummy(dummy_struct.owner_id.def_id);
121
122 let extern_id = self.extract_extern_id_from_struct(dummy_struct).unwrap();
123 self.insert_extern_id(enum_id.def_id, extern_id)?;
124 self.check_generics(enum_id, extern_id)?;
125
126 self.inner.collect_enum_def(enum_id, attrs, enum_def)?;
127
128 let extern_enum_def = self.tcx().adt_def(extern_id);
131
132 let extern_variants = extern_enum_def.variants();
134 let enum_variants = enum_def.variants;
135 let extern_len = extern_variants.len();
136 let enum_len = enum_variants.len();
137 if extern_len != enum_len {
138 let reason = format!("expected {extern_len:?} variants but only have {enum_len:?}");
139 return Err(self.invalid_enum_extern_spec(reason));
140 }
141 for (extern_variant, variant) in extern_enum_def.variants().iter().zip(enum_def.variants) {
142 if let Some(extern_ctor) = extern_variant.ctor_def_id()
143 && let Some(ctor) = variant.data.ctor_def_id()
144 && self.tcx().def_kind(extern_ctor) == self.tcx().def_kind(ctor)
145 {
146 self.insert_extern_id(ctor, extern_ctor)?;
147 } else {
148 let reason = format!(
149 "extern variant `{}` incompatible with specified `{}`",
150 extern_variant.ident(self.tcx()),
151 rustc_hir_pretty::id_to_string(&self.tcx(), variant.hir_id)
152 );
153 return Err(self.invalid_enum_extern_spec(reason));
154 }
155 }
156 Ok(())
157 }
158
159 fn collect_extern_impl(
160 &mut self,
161 impl_id: OwnerId,
162 impl_: &hir::Impl,
163 attrs: FluxAttrs,
164 ) -> Result {
165 self.inner.collect_impl(impl_id, attrs)?;
166
167 let dummy_item = self.item_at(1)?;
168 self.inner.specs.insert_dummy(dummy_item.owner_id.def_id);
169
170 let mut impl_of_trait = None;
172 let mut local_trait_self_ty = None;
173 if let hir::ItemKind::Impl(dummy_impl) = &dummy_item.kind {
174 let (extern_id, self_ty) =
175 self.extract_extern_id_from_impl(dummy_item.owner_id, dummy_impl)?;
176 impl_of_trait = Some(extern_id);
177 local_trait_self_ty = Some(self_ty);
178
179 self.inner
180 .specs
181 .insert_dummy(self.item_at(2)?.owner_id.def_id);
182 }
183
184 let mut extern_impl_id = impl_of_trait;
185 for item_id in impl_.items {
186 let item = self.tcx().hir_impl_item(*item_id);
187 let extern_item = if let hir::ImplItemKind::Fn { .. } = item.kind {
188 let attrs = self
189 .inner
190 .parse_attrs_and_report_dups(item_id.owner_id.def_id)?;
191 self.collect_extern_impl_fn(impl_of_trait, item, attrs)?
192 } else {
193 continue;
194 };
195
196 if *extern_impl_id.get_or_insert(extern_item.impl_id) != extern_item.impl_id {
197 return Err(self.invalid_impl_block());
198 }
199 }
200
201 if let Some(extern_impl_id) = extern_impl_id {
202 self.check_generics(impl_id, extern_impl_id)?;
203 if let Some(local_self_ty) = local_trait_self_ty {
205 self.check_extern_impl_self_ty(impl_id, local_self_ty, extern_impl_id)?;
206 }
207 self.insert_extern_id(impl_id.def_id, extern_impl_id)?;
208 }
209
210 Ok(())
211 }
212
213 fn collect_extern_impl_fn(
214 &mut self,
215 impl_of_trait: Option<DefId>,
216 item: &hir::ImplItem,
217 mut attrs: FluxAttrs,
218 ) -> Result<ExternImplItem> {
219 if attrs.has_attrs() {
220 let sig = attrs.fn_sig();
221 self.inner.check_fn_sig_name(item.owner_id, sig.as_ref())?;
222 let node_id = self.inner.next_node_id();
223 self.inner.insert_impl_item(
224 item.owner_id,
225 surface::ImplItemFn { attrs: attrs.into_attr_vec(), sig, node_id },
226 )?;
227 }
228
229 let extern_impl_item = self.extract_extern_id_from_impl_fn(impl_of_trait, item)?;
230 self.insert_extern_id(item.owner_id.def_id, extern_impl_item.item_id)?;
231 self.check_generics(item.owner_id, extern_impl_item.item_id)?;
232
233 Ok(extern_impl_item)
234 }
235
236 fn collect_extern_trait(
237 &mut self,
238 trait_id: OwnerId,
239 bounds: &hir::GenericBounds,
240 items: &[hir::TraitItemId],
241 attrs: FluxAttrs,
242 ) -> Result {
243 self.inner.collect_trait(trait_id, attrs)?;
244
245 let extern_trait_id = self.extract_extern_id_from_trait(bounds)?;
246 self.insert_extern_id(trait_id.def_id, extern_trait_id)?;
247 self.check_generics(trait_id, extern_trait_id)?;
248
249 for item_id in items {
250 let item = self.tcx().hir_trait_item(*item_id);
251 if let hir::TraitItemKind::Fn { .. } = item.kind {
252 let attrs = self
253 .inner
254 .parse_attrs_and_report_dups(item.owner_id.def_id)?;
255 self.collect_extern_trait_fn(extern_trait_id, item, attrs)?;
256 } else {
257 continue;
258 }
259 }
260
261 Ok(())
262 }
263
264 fn collect_extern_trait_fn(
265 &mut self,
266 extern_trait_id: DefId,
267 item: &hir::TraitItem,
268 mut attrs: FluxAttrs,
269 ) -> Result {
270 let item_id = item.owner_id;
271 if attrs.has_attrs() {
272 let sig = attrs.fn_sig();
273 self.inner.check_fn_sig_name(item.owner_id, sig.as_ref())?;
274 let node_id = self.inner.next_node_id();
275 self.inner.insert_trait_item(
276 item.owner_id,
277 surface::TraitItemFn { attrs: attrs.into_attr_vec(), sig, node_id },
278 )?;
279 }
280
281 let extern_fn_id = self.extract_extern_id_from_trait_fn(extern_trait_id, item)?;
282 self.insert_extern_id(item.owner_id.def_id, extern_fn_id)?;
283 self.check_generics(item_id, extern_fn_id)?;
284
285 Ok(())
286 }
287
288 fn extract_extern_id_from_struct(&self, item: &hir::Item) -> Result<DefId> {
289 if let hir::ItemKind::Struct(_, _, data) = item.kind
290 && let Some(extern_field) = data.fields().last()
291 && let ty = self.tcx().type_of(extern_field.def_id)
292 && let Some(adt_def) = ty.skip_binder().ty_adt_def()
293 {
294 Ok(adt_def.did())
295 } else {
296 Err(self.malformed())
297 }
298 }
299
300 fn extract_extern_id_from_fn(&self, item: &hir::Item) -> Result<DefId> {
301 if let hir::ItemKind::Fn { body, .. } = item.kind {
302 self.extract_callee_from_body(body)
303 } else {
304 Err(self.malformed())
305 }
306 }
307
308 fn extract_extern_id_from_impl_fn(
309 &self,
310 impl_of_trait: Option<DefId>,
311 item: &hir::ImplItem,
312 ) -> Result<ExternImplItem> {
313 if let hir::ImplItemKind::Fn(_, body_id) = item.kind {
314 let callee_id = self.extract_callee_from_body(body_id)?;
315 if let Some(extern_impl_id) = impl_of_trait {
316 let map = self.tcx().impl_item_implementor_ids(extern_impl_id);
317 if let Some(extern_item_id) = map.get(&callee_id) {
318 Ok(ExternImplItem { impl_id: extern_impl_id, item_id: *extern_item_id })
319 } else {
320 Err(self.item_not_in_trait_impl(item.owner_id, callee_id, extern_impl_id))
321 }
322 } else {
323 let opt_extern_impl_id = self.tcx().impl_of_assoc(callee_id);
324 if let Some(extern_impl_id) = opt_extern_impl_id {
325 debug_assert!(!self.tcx().impl_is_of_trait(extern_impl_id));
326 Ok(ExternImplItem { impl_id: extern_impl_id, item_id: callee_id })
327 } else {
328 Err(self.invalid_item_in_inherent_impl(item.owner_id, callee_id))
329 }
330 }
331 } else {
332 Err(self.malformed())
333 }
334 }
335
336 fn extract_extern_id_from_trait(&self, bounds: &hir::GenericBounds) -> Result<DefId> {
337 if let Some(bound) = bounds.first()
338 && let Some(trait_ref) = bound.trait_ref()
339 && let Some(trait_id) = trait_ref.trait_def_id()
340 {
341 Ok(trait_id)
342 } else {
343 Err(self.malformed())
344 }
345 }
346
347 fn extract_extern_id_from_trait_fn(
348 &self,
349 trait_id: DefId,
350 item: &hir::TraitItem,
351 ) -> Result<DefId> {
352 if let hir::TraitItemKind::Fn(_, trait_fn) = item.kind
353 && let hir::TraitFn::Provided(body_id) = trait_fn
354 {
355 let callee_id = self.extract_callee_from_body(body_id)?;
356 if let Some(callee_trait_id) = self.tcx().trait_of_assoc(callee_id)
357 && trait_id == callee_trait_id
358 {
359 Ok(callee_id)
360 } else {
361 Err(self.item_not_in_trait(item.owner_id, callee_id, trait_id))
364 }
365 } else {
366 Err(self.malformed())
367 }
368 }
369
370 fn extract_extern_id_from_impl(
371 &self,
372 impl_id: OwnerId,
373 impl_: &hir::Impl,
374 ) -> Result<(DefId, ty::Ty<'tcx>)> {
375 if let Some(item_id) = impl_.items.first()
376 && let hir::ImplItemKind::Fn { .. } = self.tcx().hir_impl_item(*item_id).kind
377 && let Some((clause, _)) = self
378 .tcx()
379 .predicates_of(item_id.owner_id.def_id)
380 .predicates
381 .first()
382 && let Some(poly_trait_pred) = clause.as_trait_clause()
383 && let Some(trait_pred) = poly_trait_pred.no_bound_vars()
384 {
385 let trait_ref = trait_pred.trait_ref;
386 let local_self_ty = trait_ref.self_ty();
387 lowering::resolve_trait_ref_impl_id(self.tcx(), impl_id.to_def_id(), trait_ref)
388 .map(|(impl_id, _)| (impl_id, local_self_ty))
389 .ok_or_else(|| self.cannot_resolve_trait_impl())
390 } else {
391 Err(self.malformed())
392 }
393 }
394
395 fn extract_callee_from_body(&self, body_id: hir::BodyId) -> Result<DefId> {
396 let owner = self.tcx().hir_body_owner_def_id(body_id);
397 let typeck = self.tcx().typeck(owner);
398 if let hir::ExprKind::Block(b, _) = self.tcx().hir_body(body_id).value.kind
399 && let Some(e) = b.expr
400 {
401 let call_expr =
403 if let hir::ExprKind::Block(inner_b, _) = e.kind { inner_b.expr } else { Some(e) };
404 if let Some(e) = call_expr
405 && let hir::ExprKind::Call(callee, _) = e.kind
406 && let rustc_middle::ty::FnDef(callee_id, _) =
407 typeck.node_type(callee.hir_id).kind()
408 {
409 return Ok(*callee_id);
410 }
411 }
412 Err(self.malformed())
413 }
414
415 #[track_caller]
417 fn item_at(&self, i: usize) -> Result<&'tcx hir::Item<'tcx>> {
418 let stmts = self.block.stmts;
419 let index = stmts
420 .len()
421 .checked_sub(i + 1)
422 .ok_or_else(|| self.malformed())?;
423 let st = stmts.get(index).ok_or_else(|| self.malformed())?;
424 if let hir::StmtKind::Item(item_id) = st.kind {
425 Ok(self.tcx().hir_item(item_id))
426 } else {
427 Err(self.malformed())
428 }
429 }
430
431 fn insert_extern_id(&mut self, local_id: LocalDefId, extern_id: DefId) -> Result {
432 self.inner
433 .specs
434 .insert_extern_spec_id_mapping(local_id, extern_id)
435 .map_err(|err| {
436 match err {
437 ExternSpecMappingErr::IsLocal(extern_id_local) => {
438 self.emit(errors::ExternSpecForLocalDef {
439 span: ident_or_def_span(self.tcx(), local_id),
440 local_def_span: ident_or_def_span(self.tcx(), extern_id_local),
441 name: self.tcx().def_path_str(extern_id),
442 })
443 }
444 ExternSpecMappingErr::Dup(previous_extern_spec) => {
445 self.emit(errors::DupExternSpec {
446 span: ident_or_def_span(self.tcx(), local_id),
447 previous_span: ident_or_def_span(self.tcx(), previous_extern_spec),
448 name: self.tcx().def_path_str(extern_id),
449 })
450 }
451 }
452 })
453 }
454
455 fn check_generics(&mut self, local_id: OwnerId, extern_id: DefId) -> Result {
456 let tcx = self.tcx();
457 let local_params = &tcx.generics_of(local_id).own_params;
458 let extern_params = &tcx.generics_of(extern_id).own_params;
459
460 let mismatch = 'mismatch: {
461 if local_params.len() != extern_params.len() {
462 break 'mismatch true;
463 }
464 for (local_param, extern_param) in iter::zip(local_params, extern_params) {
465 if !cmp_generic_param_def(local_param, extern_param) {
466 break 'mismatch true;
467 }
468 if local_param.name != kw::SelfUpper {
471 #[expect(clippy::disallowed_methods)]
472 self.insert_extern_id(local_param.def_id.expect_local(), extern_param.def_id)?;
473 }
474 }
475 false
476 };
477 if mismatch {
478 let local_hir_generics = tcx.hir_get_generics(local_id.def_id).unwrap();
479 let span = local_hir_generics.span;
480 Err(self.emit(errors::MismatchedGenerics {
481 span,
482 extern_def: tcx.def_span(extern_id),
483 def_descr: tcx.def_descr(extern_id),
484 }))
485 } else {
486 Ok(())
487 }
488 }
489
490 fn check_extern_impl_self_ty(
491 &mut self,
492 local_impl_id: OwnerId,
493 local_self_ty: ty::Ty<'tcx>,
494 extern_impl_id: DefId,
495 ) -> Result {
496 let tcx = self.tcx();
497
498 let extern_self_ty = tcx.type_of(extern_impl_id).instantiate_identity();
500
501 if local_self_ty != extern_self_ty {
507 let span = tcx.def_span(local_impl_id);
511 Err(self.emit(errors::MismatchedImplSelfTy {
512 span,
513 local_self_ty: local_self_ty.to_string(),
514 extern_self_ty: extern_self_ty.to_string(),
515 extern_impl_span: tcx.def_span(extern_impl_id),
516 }))
517 } else {
518 Ok(())
519 }
520 }
521
522 #[track_caller]
523 fn malformed(&self) -> ErrorGuaranteed {
524 self.emit(errors::MalformedExternSpec::new(self.block.span))
525 }
526
527 #[track_caller]
528 fn invalid_enum_extern_spec(&self, reason: String) -> ErrorGuaranteed {
529 self.emit(errors::InvalidEnumExternSpec::new(self.block.span, reason))
530 }
531
532 #[track_caller]
533 fn item_not_in_trait_impl(
534 &self,
535 local_id: OwnerId,
536 extern_id: DefId,
537 extern_impl_id: DefId,
538 ) -> ErrorGuaranteed {
539 let tcx = self.tcx();
540 self.emit(errors::ItemNotInTraitImpl {
541 span: ident_or_def_span(tcx, local_id),
542 name: tcx.def_path_str(extern_id),
543 extern_impl_span: tcx.def_span(extern_impl_id),
544 })
545 }
546
547 fn invalid_item_in_inherent_impl(
548 &self,
549 local_id: OwnerId,
550 extern_id: DefId,
551 ) -> ErrorGuaranteed {
552 let tcx = self.tcx();
553 self.emit(errors::InvalidItemInInherentImpl {
554 span: ident_or_def_span(tcx, local_id),
555 name: tcx.def_path_str(extern_id),
556 extern_item_span: tcx.def_span(extern_id),
557 })
558 }
559
560 #[track_caller]
561 fn invalid_impl_block(&self) -> ErrorGuaranteed {
562 self.emit(errors::InvalidImplBlock { span: self.block.span })
563 }
564
565 #[track_caller]
566 fn cannot_resolve_trait_impl(&self) -> ErrorGuaranteed {
567 self.emit(errors::CannotResolveTraitImpl { span: self.block.span })
568 }
569
570 #[track_caller]
571 fn item_not_in_trait(
572 &self,
573 local_id: OwnerId,
574 extern_id: DefId,
575 extern_trait_id: DefId,
576 ) -> ErrorGuaranteed {
577 let tcx = self.tcx();
578 self.emit(errors::ItemNotInTrait {
579 span: ident_or_def_span(tcx, local_id),
580 name: tcx.def_path_str(extern_id),
581 extern_trait_span: tcx.def_span(extern_trait_id),
582 })
583 }
584
585 #[track_caller]
586 fn emit<'b>(&'b self, err: impl Diagnostic<'b>) -> ErrorGuaranteed {
587 self.inner.errors.emit(err)
588 }
589
590 fn tcx(&self) -> TyCtxt<'tcx> {
591 self.inner.tcx
592 }
593}
594
595fn cmp_generic_param_def(a: &ty::GenericParamDef, b: &ty::GenericParamDef) -> bool {
596 if a.name != b.name {
597 return false;
598 }
599 if a.index != b.index {
600 return false;
601 }
602 matches!(
603 (&a.kind, &b.kind),
604 (ty::GenericParamDefKind::Lifetime, ty::GenericParamDefKind::Lifetime)
605 | (ty::GenericParamDefKind::Type { .. }, ty::GenericParamDefKind::Type { .. })
606 | (ty::GenericParamDefKind::Const { .. }, ty::GenericParamDefKind::Const { .. })
607 )
608}
609
610fn ident_or_def_span(tcx: TyCtxt, def_id: impl Into<DefId>) -> Span {
611 let def_id = def_id.into();
612 tcx.def_ident_span(def_id)
613 .unwrap_or_else(|| tcx.def_span(def_id))
614}
615
616mod errors {
617 use flux_errors::E0999;
618 use flux_macros::Diagnostic;
619 use rustc_span::Span;
620
621 #[derive(Diagnostic)]
622 #[diag(driver_malformed_extern_spec, code = E0999)]
623 pub(super) struct MalformedExternSpec {
624 #[primary_span]
625 span: Span,
626 }
627
628 impl MalformedExternSpec {
629 pub(super) fn new(span: Span) -> Self {
630 Self { span }
631 }
632 }
633
634 #[derive(Diagnostic)]
635 #[diag(driver_invalid_enum_extern_spec, code = E0999)]
636 pub(super) struct InvalidEnumExternSpec {
637 #[primary_span]
638 span: Span,
639 reason: String,
640 }
641
642 impl InvalidEnumExternSpec {
643 pub(super) fn new(span: Span, reason: String) -> Self {
644 Self { span, reason }
645 }
646 }
647
648 #[derive(Diagnostic)]
649 #[diag(driver_cannot_resolve_trait_impl, code = E0999)]
650 #[note]
651 pub(super) struct CannotResolveTraitImpl {
652 #[primary_span]
653 pub span: Span,
654 }
655
656 #[derive(Diagnostic)]
657 #[diag(driver_invalid_impl_block, code = E0999)]
658 pub(super) struct InvalidImplBlock {
659 #[primary_span]
660 #[label]
661 pub span: Span,
662 }
663
664 #[derive(Diagnostic)]
665 #[diag(driver_item_not_in_trait_impl, code = E0999)]
666 pub(super) struct ItemNotInTraitImpl {
667 #[primary_span]
668 #[label]
669 pub span: Span,
670 pub name: String,
671 #[note]
672 pub extern_impl_span: Span,
673 }
674
675 #[derive(Diagnostic)]
676 #[diag(driver_invalid_item_in_inherent_impl, code = E0999)]
677 pub(super) struct InvalidItemInInherentImpl {
678 #[primary_span]
679 #[label]
680 pub span: Span,
681 pub name: String,
682 #[note]
683 pub extern_item_span: Span,
684 }
685
686 #[derive(Diagnostic)]
687 #[diag(driver_item_not_in_trait, code = E0999)]
688 pub(super) struct ItemNotInTrait {
689 #[primary_span]
690 #[label]
691 pub span: Span,
692 pub name: String,
693 #[note]
694 pub extern_trait_span: Span,
695 }
696
697 #[derive(Diagnostic)]
698 #[diag(driver_extern_spec_for_local_def, code = E0999)]
699 pub(super) struct ExternSpecForLocalDef {
700 #[primary_span]
701 pub span: Span,
702 #[help]
703 pub local_def_span: Span,
704 pub name: String,
705 }
706
707 #[derive(Diagnostic)]
708 #[diag(driver_dup_extern_spec, code = E0999)]
709 pub(super) struct DupExternSpec {
710 #[primary_span]
711 #[label]
712 pub span: Span,
713 #[note]
714 pub previous_span: Span,
715 pub name: String,
716 }
717
718 #[derive(Diagnostic)]
719 #[diag(driver_mismatched_generics, code = E0999)]
720 #[note]
721 pub(super) struct MismatchedGenerics {
722 #[primary_span]
723 #[label]
724 pub span: Span,
725 #[label(driver_extern_def_label)]
726 pub extern_def: Span,
727 pub def_descr: &'static str,
728 }
729
730 #[derive(Diagnostic)]
731 #[diag(driver_mismatched_impl_self_ty, code = E0999)]
732 #[note]
733 pub(super) struct MismatchedImplSelfTy {
734 #[primary_span]
735 #[label]
736 pub span: Span,
737 pub local_self_ty: String,
738 pub extern_self_ty: String,
739 #[label(driver_extern_impl_label)]
740 pub extern_impl_span: Span,
741 }
742}