diff --git a/compiler/rustc_error_messages/locales/en-US/middle.ftl b/compiler/rustc_error_messages/locales/en-US/middle.ftl index f2864ec4922..bc1aebd9dbe 100644 --- a/compiler/rustc_error_messages/locales/en-US/middle.ftl +++ b/compiler/rustc_error_messages/locales/en-US/middle.ftl @@ -1,3 +1,13 @@ middle_drop_check_overflow = overflow while adding drop-check rules for {$ty} .note = {$note} + +middle_opaque_hidden_type_mismatch = + concrete type differs from previous defining opaque type use + .label = expected `{$self_ty}`, got `{$other_ty}` + +middle_conflict_types = + this expression supplies two conflicting concrete types for the same opaque type + +middle_previous_use_here = + previous use here diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index d81eb524169..27588440aac 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -12,3 +12,29 @@ pub struct DropCheckOverflow<'tcx> { pub ty: Ty<'tcx>, pub note: String, } + +#[derive(SessionDiagnostic)] +#[diag(middle::opaque_hidden_type_mismatch)] +pub struct OpaqueHiddenTypeMismatch<'tcx> { + pub self_ty: Ty<'tcx>, + pub other_ty: Ty<'tcx>, + #[primary_span] + #[label] + pub other_span: Span, + #[subdiagnostic] + pub sub: TypeMismatchReason, +} + +#[derive(SessionSubdiagnostic)] +pub enum TypeMismatchReason { + #[label(middle::conflict_types)] + ConflictType { + #[primary_span] + span: Span, + }, + #[note(middle::previous_use_here)] + PreviousUse { + #[primary_span] + span: Span, + }, +} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ed04e766033..5c38d761411 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -15,6 +15,7 @@ pub use self::BorrowKind::*; pub use self::IntVarValue::*; pub use self::Variance::*; +use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; use crate::metadata::ModChild; use crate::middle::privacy::AccessLevels; use crate::mir::{Body, GeneratorLayout}; @@ -1184,20 +1185,17 @@ pub struct OpaqueHiddenType<'tcx> { impl<'tcx> OpaqueHiddenType<'tcx> { pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) { // Found different concrete types for the opaque type. - let mut err = tcx.sess.struct_span_err( - other.span, - "concrete type differs from previous defining opaque type use", - ); - err.span_label(other.span, format!("expected `{}`, got `{}`", self.ty, other.ty)); - if self.span == other.span { - err.span_label( - self.span, - "this expression supplies two conflicting concrete types for the same opaque type", - ); + let sub_diag = if self.span == other.span { + TypeMismatchReason::ConflictType { span: self.span } } else { - err.span_note(self.span, "previous use here"); - } - err.emit(); + TypeMismatchReason::PreviousUse { span: self.span } + }; + tcx.sess.emit_err(OpaqueHiddenTypeMismatch { + self_ty: self.ty, + other_ty: other.ty, + other_span: other.span, + sub: sub_diag, + }); } }