Skip to content
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use rustc_middle::ty::{
Unnormalized,
};
use rustc_span::Span;
use rustc_trait_selection::diagnostics::impl_trait_overcapture_suggestion;
use rustc_trait_selection::error_reporting::infer::region::unexpected_hidden_region_diagnostic;
use rustc_trait_selection::errors::impl_trait_overcapture_suggestion;

use crate::MirBorrowckCtxt;
use crate::borrow_set::BorrowData;
Expand Down
66 changes: 21 additions & 45 deletions compiler/rustc_hir_analysis/src/coherence/orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,21 @@ pub(crate) fn orphan_check_impl(
Err(err) => match orphan_check(tcx, impl_def_id, OrphanCheckMode::Compat) {
Ok(()) => match err {
OrphanCheckErr::UncoveredTyParams(uncovered_ty_params) => {
lint_uncovered_ty_params(tcx, uncovered_ty_params, impl_def_id)
let hir_id = tcx.local_def_id_to_hir_id(impl_def_id);

for param_def_id in uncovered_ty_params.uncovered {
let ident = tcx.item_ident(param_def_id);

tcx.emit_node_span_lint(
UNCOVERED_PARAM_IN_PROJECTION,
hir_id,
ident.span,
diagnostics::UncoveredTyParam {
param: ident,
local_ty: uncovered_ty_params.local_ty,
},
);
}
}
OrphanCheckErr::NonLocalInputType(_) => {
bug!("orphanck: shouldn't've gotten non-local input tys in compat mode")
Expand Down Expand Up @@ -458,56 +472,18 @@ fn emit_orphan_check_error<'tcx>(
diag.emit()
}
traits::OrphanCheckErr::UncoveredTyParams(UncoveredTyParams { uncovered, local_ty }) => {
let mut reported = None;
let mut guar = None;
for param_def_id in uncovered {
let name = tcx.item_ident(param_def_id);
let span = name.span;

reported.get_or_insert(match local_ty {
Some(local_type) => tcx.dcx().emit_err(diagnostics::TyParamFirstLocal {
span,
note: (),
param: name,
local_type,
}),
None => {
tcx.dcx().emit_err(diagnostics::TyParamSome { span, note: (), param: name })
}
});
guar.get_or_insert(tcx.dcx().emit_err(diagnostics::UncoveredTyParam {
param: tcx.item_ident(param_def_id),
local_ty,
}));
}
reported.unwrap() // FIXME(fmease): This is very likely reachable.
guar.unwrap()
}
}
}

fn lint_uncovered_ty_params<'tcx>(
tcx: TyCtxt<'tcx>,
UncoveredTyParams { uncovered, local_ty }: UncoveredTyParams<TyCtxt<'tcx>, FxIndexSet<DefId>>,
impl_def_id: LocalDefId,
) {
let hir_id = tcx.local_def_id_to_hir_id(impl_def_id);

for param_def_id in uncovered {
let span = tcx.def_ident_span(param_def_id).unwrap();
let name = tcx.item_ident(param_def_id);

match local_ty {
Some(local_type) => tcx.emit_node_span_lint(
UNCOVERED_PARAM_IN_PROJECTION,
hir_id,
span,
diagnostics::TyParamFirstLocalLint { span, note: (), param: name, local_type },
),
None => tcx.emit_node_span_lint(
UNCOVERED_PARAM_IN_PROJECTION,
hir_id,
span,
diagnostics::TyParamSomeLint { span, note: (), param: name },
),
};
}
}

struct UncoveredTyParamCollector<'cx, 'tcx> {
infcx: &'cx InferCtxt<'tcx>,
uncovered_params: FxIndexSet<DefId>,
Expand Down
116 changes: 50 additions & 66 deletions compiler/rustc_hir_analysis/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1474,72 +1474,6 @@ pub struct NoFieldOnType<'tcx> {
pub field: Ident,
}

// FIXME(fmease): Deduplicate:

#[derive(Diagnostic)]
#[diag("type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)", code = E0210)]
#[note(
"implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type"
)]
pub(crate) struct TyParamFirstLocal<'tcx> {
#[primary_span]
#[label(
"type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)"
)]
pub span: Span,
#[note(
"in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last"
)]
pub note: (),
pub param: Ident,
pub local_type: Ty<'tcx>,
}

#[derive(Diagnostic)]
#[diag("type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)", code = E0210)]
#[note(
"implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type"
)]
pub(crate) struct TyParamFirstLocalLint<'tcx> {
#[label(
"type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)"
)]
pub span: Span,
#[note(
"in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last"
)]
pub note: (),
pub param: Ident,
pub local_type: Ty<'tcx>,
}

#[derive(Diagnostic)]
#[diag("type parameter `{$param}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param}>`)", code = E0210)]
#[note(
"implementing a foreign trait is only possible if at least one of the types for which it is implemented is local"
)]
pub(crate) struct TyParamSome {
#[primary_span]
#[label("type parameter `{$param}` must be used as the type parameter for some local type")]
pub span: Span,
#[note("only traits defined in the current crate can be implemented for a type parameter")]
pub note: (),
pub param: Ident,
}

#[derive(Diagnostic)]
#[diag("type parameter `{$param}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param}>`)", code = E0210)]
#[note(
"implementing a foreign trait is only possible if at least one of the types for which it is implemented is local"
)]
pub(crate) struct TyParamSomeLint {
#[label("type parameter `{$param}` must be used as the type parameter for some local type")]
pub span: Span,
#[note("only traits defined in the current crate can be implemented for a type parameter")]
pub note: (),
pub param: Ident,
}

#[derive(Diagnostic)]
pub(crate) enum OnlyCurrentTraits {
#[diag("only traits defined in the current crate can be implemented for types defined outside of the crate", code = E0117)]
Expand Down Expand Up @@ -2024,3 +1958,53 @@ pub(crate) struct PinV2OnPacked {
pub pin_v2_span: Option<Span>,
pub adt_name: Symbol,
}

pub(crate) struct UncoveredTyParam<'tcx> {
pub(crate) param: Ident,
pub(crate) local_ty: Option<Ty<'tcx>>,
}

impl<G: EmissionGuarantee> Diagnostic<'_, G> for UncoveredTyParam<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
let Self { param, local_ty } = self;

let mut diag = Diag::new(dcx, level, "")
.with_span(param.span)
.with_span_label(param.span, "uncovered type parameter");
if diag.is_error() {
diag.code(E0210);
}

let note = "\
implementing a foreign trait is only possible if \
at least one of the types for which it is implemented is local";

if let Some(local_ty) = local_ty {
diag.primary_message(format!(
"type parameter `{param}` must be covered by another type when \
it appears before the first local type (`{local_ty}`)"
));

diag.note(format!(
"{note},\nand no uncovered type parameters appear before that first local type"
));
diag.note(
"in this case, 'before' refers to the following order: \
`impl<..> ForeignTrait<T1, ..., Tn> for T0`,\n\
where `T0` is the first and `Tn` is the last",
);
} else {
diag.primary_message(format!(
"type parameter `{param}` must be used as an argument to \
some local type (e.g., `MyStruct<{param}>`)"
));

diag.note(note);
diag.note(
"only traits defined in the current crate can be implemented for a type parameter",
);
}

diag
}
}
18 changes: 1 addition & 17 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,25 +197,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(crate) fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
TypeErrCtxt {
infcx: &self.infcx,
param_env: Some(self.param_env),
typeck_results: Some(self.typeck_results.borrow()),
diverging_fallback_has_occurred: self.diverging_fallback_has_occurred.get(),
normalize_fn_sig: Box::new(|fn_sig| {
if fn_sig.skip_normalization().has_escaping_bound_vars() {
return fn_sig.skip_normalization();
}
self.probe(|_| {
let ocx = ObligationCtxt::new(self);
let normalized_fn_sig =
ocx.normalize(&ObligationCause::dummy(), self.param_env, fn_sig);
if ocx.evaluate_obligations_error_on_ambiguity().is_empty() {
let normalized_fn_sig = self.resolve_vars_if_possible(normalized_fn_sig);
if !normalized_fn_sig.has_infer() {
return normalized_fn_sig;
}
}
fn_sig.skip_normalization()
})
}),
autoderef_steps: Box::new(|ty| {
let mut autoderef = self.autoderef(DUMMY_SP, ty).silence_errors();
let mut steps = vec![];
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/impl_trait_overcaptures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use rustc_middle::{bug, span_bug};
use rustc_session::lint::fcw;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::{Span, Symbol};
use rustc_trait_selection::errors::{
use rustc_trait_selection::diagnostics::{
AddPreciseCapturingForOvercapture, impl_trait_overcapture_suggestion,
};
use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/check_call_recursion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc_middle::ty::{self, GenericArg, GenericArgs, Instance, Ty, TyCtxt, Unno
use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
use rustc_span::Span;

use crate::errors::UnconditionalRecursion;
use crate::diagnostics::UnconditionalRecursion;
use crate::pass_manager::MirLint;

pub(super) struct CheckCallRecursion;
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_mir_transform/src/check_const_item_mutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_session::lint::builtin::CONST_ITEM_MUTATION;
use rustc_span::Span;
use rustc_span::def_id::DefId;

use crate::errors;
use crate::diagnostics;

pub(super) struct CheckConstItemMutation;

Expand Down Expand Up @@ -108,7 +108,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
CONST_ITEM_MUTATION,
lint_root,
span,
errors::ConstMutate::Modify { konst: item },
diagnostics::ConstMutate::Modify { konst: item },
);
}

Expand Down Expand Up @@ -154,7 +154,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
CONST_ITEM_MUTATION,
lint_root,
span,
errors::ConstMutate::MutBorrow { method_call, konst: item },
diagnostics::ConstMutate::MutBorrow { method_call, konst: item },
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/check_inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl<'tcx> MirLint<'tcx> for CheckForceInline {
if let Err(reason) =
is_inline_valid_on_fn(tcx, def_id).and_then(|_| is_inline_valid_on_body(tcx, body))
{
tcx.dcx().emit_err(crate::errors::InvalidForceInline {
tcx.dcx().emit_err(crate::diagnostics::InvalidForceInline {
attr_span,
callee_span: tcx.def_span(def_id),
callee: tcx.def_path_str(def_id),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_transform/src/check_packed_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc_middle::mir::*;
use rustc_middle::span_bug;
use rustc_middle::ty::{self, TyCtxt};

use crate::{errors, util};
use crate::{diagnostics, util};

pub(super) struct CheckPackedRef;

Expand Down Expand Up @@ -50,7 +50,7 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
// shouldn't do.
span_bug!(self.source_info.span, "builtin derive created an unaligned reference");
} else {
self.tcx.dcx().emit_err(errors::UnalignedPackedRef {
self.tcx.dcx().emit_err(diagnostics::UnalignedPackedRef {
span: self.source_info.span,
ty_descr: adt.descr(),
align: pack.bytes(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/coroutine/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ use rustc_trait_selection::infer::TyCtxtInferExt as _;
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
use tracing::{debug, instrument, trace};

use crate::errors::{MustNotSupend, MustNotSuspendReason};
use crate::diagnostics::{MustNotSupend, MustNotSuspendReason};

const SELF_ARG: Local = Local::arg(0);

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_session::lint::builtin::FFI_UNWIND_CALLS;
use rustc_target::spec::PanicStrategy;
use tracing::debug;

use crate::errors;
use crate::diagnostics;

// Check if the body of this def_id can possibly leak a foreign unwind into Rust code.
fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
Expand Down Expand Up @@ -67,7 +67,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
FFI_UNWIND_CALLS,
lint_root,
span,
errors::AsmUnwindCall { span },
diagnostics::AsmUnwindCall { span },
);

tainted = true;
Expand Down Expand Up @@ -119,7 +119,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
FFI_UNWIND_CALLS,
lint_root,
span,
errors::FfiUnwindCall { span, foreign },
diagnostics::FfiUnwindCall { span, foreign },
);

tainted = true;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir_transform/src/function_item_references.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt};
use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
use rustc_span::{Span, Spanned, sym};

use crate::errors;
use crate::diagnostics;

pub(super) struct FunctionItemReferences;

Expand Down Expand Up @@ -179,7 +179,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
FUNCTION_ITEM_REFERENCES,
lint_root,
span,
errors::FnItemRef { span, sugg, ident },
diagnostics::FnItemRef { span, sugg, ident },
);
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> {

let call_span = callsite.source_info.span;
let callee = tcx.def_path_str(callsite.callee.def_id());
tcx.dcx().emit_err(crate::errors::ForceInlineFailure {
tcx.dcx().emit_err(crate::diagnostics::ForceInlineFailure {
call_span,
attr_span,
caller_span: tcx.def_span(self.def_id),
Expand All @@ -262,7 +262,7 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> {
callee: callee.clone(),
reason,
justification: justification
.map(|sym| crate::errors::ForceInlineJustification { sym, callee }),
.map(|sym| crate::diagnostics::ForceInlineJustification { sym, callee }),
});
}
}
Expand Down
Loading
Loading