Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 21 additions & 43 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,
errors::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 @@ -455,54 +469,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(errors::TyParamFirstLocal {
span,
note: (),
param: name,
local_type,
}),
None => tcx.dcx().emit_err(errors::TyParamSome { span, note: (), param: name }),
});
guar.get_or_insert(tcx.dcx().emit_err(errors::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,
errors::TyParamFirstLocalLint { span, note: (), param: name, local_type },
),
None => tcx.emit_node_span_lint(
UNCOVERED_PARAM_IN_PROJECTION,
hir_id,
span,
errors::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/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1498,72 +1498,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 @@ -2048,3 +1982,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
}
}
2 changes: 1 addition & 1 deletion tests/ui/coercion/invalid-blanket-coerce-unsized-impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#![feature(coerce_unsized)]

impl<A> std::ops::CoerceUnsized<A> for A {}
//~^ ERROR type parameter `A` must be used as the type parameter for some local type
//~^ ERROR type parameter `A` must be used as an argument to some local type
//~| ERROR the trait `CoerceUnsized` may only be implemented for a coercion between structures

const C: usize = 1;
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/coercion/invalid-blanket-coerce-unsized-impl.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct<A>`)
error[E0210]: type parameter `A` must be used as an argument to some local type (e.g., `MyStruct<A>`)
--> $DIR/invalid-blanket-coerce-unsized-impl.rs:7:6
|
LL | impl<A> std::ops::CoerceUnsized<A> for A {}
| ^ type parameter `A` must be used as the type parameter for some local type
| ^ uncovered type parameter
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/coherence/coherence-all-remote.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct<T>`)
--> $DIR/coherence-all-remote.rs:6:6
|
LL | impl<T> Remote1<T> for isize { }
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ uncovered type parameter
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
Expand Down
8 changes: 5 additions & 3 deletions tests/ui/coherence/coherence-bigint-param.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ error[E0210]: type parameter `T` must be covered by another type when it appears
--> $DIR/coherence-bigint-param.rs:8:6
|
LL | impl<T> Remote1<BigInt> for T { }
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`)
| ^ uncovered type parameter
|
= 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
= 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
= 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
= 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

error: aborting due to 1 previous error

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/coherence/coherence-cross-crate-conflict.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct<A>`)
error[E0210]: type parameter `A` must be used as an argument to some local type (e.g., `MyStruct<A>`)
--> $DIR/coherence-cross-crate-conflict.rs:9:6
|
LL | impl<A> Foo for A {
| ^ type parameter `A` must be used as the type parameter for some local type
| ^ uncovered type parameter
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/coherence/coherence-lone-type-parameter.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct<T>`)
--> $DIR/coherence-lone-type-parameter.rs:6:6
|
LL | impl<T> Remote for T { }
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ uncovered type parameter
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/coherence/impl[t]-foreign-for-fundamental[t].rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ use std::rc::Rc;
struct Local;

impl<T> Remote for Box<T> {
//~^ ERROR type parameter `T` must be used as the type parameter for
// | some local type (e.g., `MyStruct<T>`)
//~^ ERROR type parameter `T` must be used as an argument to some local type
}

fn main() {}
4 changes: 2 additions & 2 deletions tests/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct<T>`)
--> $DIR/impl[t]-foreign-for-fundamental[t].rs:10:6
|
LL | impl<T> Remote for Box<T> {
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ uncovered type parameter
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use std::rc::Rc;
struct Local;

impl<T> Remote1<u32> for Box<T> {
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
//~^ ERROR type parameter `T` must be used as an argument to some local type
}

impl<'a, T> Remote1<u32> for &'a T {
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
//~^ ERROR type parameter `T` must be used as an argument to some local type
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct<T>`)
--> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:10:6
|
LL | impl<T> Remote1<u32> for Box<T> {
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ uncovered type parameter
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct<T>`)
--> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:14:10
|
LL | impl<'a, T> Remote1<u32> for &'a T {
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ uncovered type parameter
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/coherence/impl[t]-foreign[foreign]-for-t.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::rc::Rc;
struct Local;

impl<T> Remote1<u32> for T {
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
//~^ ERROR type parameter `T` must be used as an argument to some local type
}

fn main() {}
4 changes: 2 additions & 2 deletions tests/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct<T>`)
--> $DIR/impl[t]-foreign[foreign]-for-t.rs:10:6
|
LL | impl<T> Remote1<u32> for T {
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ uncovered type parameter
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use std::rc::Rc;
struct Local;

impl<T> Remote1<Box<T>> for u32 {
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
//~^ ERROR type parameter `T` must be used as an argument to some local type
}

impl<'a, T> Remote1<&'a T> for u32 {
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
//~^ ERROR type parameter `T` must be used as an argument to some local type
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct<T>`)
--> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:10:6
|
LL | impl<T> Remote1<Box<T>> for u32 {
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ uncovered type parameter
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct<T>`)
--> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:14:10
|
LL | impl<'a, T> Remote1<&'a T> for u32 {
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ uncovered type parameter
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
Expand Down
Loading
Loading