Skip to content

Commit 4fa96d0

Browse files
committed
Auto merge of #157677 - fmease:orphanck-improv-diag, r=jackh726
Slightly improve diagnostic impl+output for uncovered type parameters Split out of PR #135910. No behavioral changes. See individual commit messages for details.
2 parents 1a30ed9 + 2fda233 commit 4fa96d0

57 files changed

Lines changed: 289 additions & 290 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_hir_analysis/src/coherence/orphan.rs

Lines changed: 21 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,21 @@ pub(crate) fn orphan_check_impl(
3131
Err(err) => match orphan_check(tcx, impl_def_id, OrphanCheckMode::Compat) {
3232
Ok(()) => match err {
3333
OrphanCheckErr::UncoveredTyParams(uncovered_ty_params) => {
34-
lint_uncovered_ty_params(tcx, uncovered_ty_params, impl_def_id)
34+
let hir_id = tcx.local_def_id_to_hir_id(impl_def_id);
35+
36+
for param_def_id in uncovered_ty_params.uncovered {
37+
let ident = tcx.item_ident(param_def_id);
38+
39+
tcx.emit_node_span_lint(
40+
UNCOVERED_PARAM_IN_PROJECTION,
41+
hir_id,
42+
ident.span,
43+
diagnostics::UncoveredTyParam {
44+
param: ident,
45+
local_ty: uncovered_ty_params.local_ty,
46+
},
47+
);
48+
}
3549
}
3650
OrphanCheckErr::NonLocalInputType(_) => {
3751
bug!("orphanck: shouldn't've gotten non-local input tys in compat mode")
@@ -458,56 +472,18 @@ fn emit_orphan_check_error<'tcx>(
458472
diag.emit()
459473
}
460474
traits::OrphanCheckErr::UncoveredTyParams(UncoveredTyParams { uncovered, local_ty }) => {
461-
let mut reported = None;
475+
let mut guar = None;
462476
for param_def_id in uncovered {
463-
let name = tcx.item_ident(param_def_id);
464-
let span = name.span;
465-
466-
reported.get_or_insert(match local_ty {
467-
Some(local_type) => tcx.dcx().emit_err(diagnostics::TyParamFirstLocal {
468-
span,
469-
note: (),
470-
param: name,
471-
local_type,
472-
}),
473-
None => {
474-
tcx.dcx().emit_err(diagnostics::TyParamSome { span, note: (), param: name })
475-
}
476-
});
477+
guar.get_or_insert(tcx.dcx().emit_err(diagnostics::UncoveredTyParam {
478+
param: tcx.item_ident(param_def_id),
479+
local_ty,
480+
}));
477481
}
478-
reported.unwrap() // FIXME(fmease): This is very likely reachable.
482+
guar.unwrap()
479483
}
480484
}
481485
}
482486

483-
fn lint_uncovered_ty_params<'tcx>(
484-
tcx: TyCtxt<'tcx>,
485-
UncoveredTyParams { uncovered, local_ty }: UncoveredTyParams<TyCtxt<'tcx>, FxIndexSet<DefId>>,
486-
impl_def_id: LocalDefId,
487-
) {
488-
let hir_id = tcx.local_def_id_to_hir_id(impl_def_id);
489-
490-
for param_def_id in uncovered {
491-
let span = tcx.def_ident_span(param_def_id).unwrap();
492-
let name = tcx.item_ident(param_def_id);
493-
494-
match local_ty {
495-
Some(local_type) => tcx.emit_node_span_lint(
496-
UNCOVERED_PARAM_IN_PROJECTION,
497-
hir_id,
498-
span,
499-
diagnostics::TyParamFirstLocalLint { span, note: (), param: name, local_type },
500-
),
501-
None => tcx.emit_node_span_lint(
502-
UNCOVERED_PARAM_IN_PROJECTION,
503-
hir_id,
504-
span,
505-
diagnostics::TyParamSomeLint { span, note: (), param: name },
506-
),
507-
};
508-
}
509-
}
510-
511487
struct UncoveredTyParamCollector<'cx, 'tcx> {
512488
infcx: &'cx InferCtxt<'tcx>,
513489
uncovered_params: FxIndexSet<DefId>,

compiler/rustc_hir_analysis/src/diagnostics.rs

Lines changed: 50 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,72 +1474,6 @@ pub struct NoFieldOnType<'tcx> {
14741474
pub field: Ident,
14751475
}
14761476

1477-
// FIXME(fmease): Deduplicate:
1478-
1479-
#[derive(Diagnostic)]
1480-
#[diag("type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)", code = E0210)]
1481-
#[note(
1482-
"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"
1483-
)]
1484-
pub(crate) struct TyParamFirstLocal<'tcx> {
1485-
#[primary_span]
1486-
#[label(
1487-
"type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)"
1488-
)]
1489-
pub span: Span,
1490-
#[note(
1491-
"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"
1492-
)]
1493-
pub note: (),
1494-
pub param: Ident,
1495-
pub local_type: Ty<'tcx>,
1496-
}
1497-
1498-
#[derive(Diagnostic)]
1499-
#[diag("type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)", code = E0210)]
1500-
#[note(
1501-
"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"
1502-
)]
1503-
pub(crate) struct TyParamFirstLocalLint<'tcx> {
1504-
#[label(
1505-
"type parameter `{$param}` must be covered by another type when it appears before the first local type (`{$local_type}`)"
1506-
)]
1507-
pub span: Span,
1508-
#[note(
1509-
"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"
1510-
)]
1511-
pub note: (),
1512-
pub param: Ident,
1513-
pub local_type: Ty<'tcx>,
1514-
}
1515-
1516-
#[derive(Diagnostic)]
1517-
#[diag("type parameter `{$param}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param}>`)", code = E0210)]
1518-
#[note(
1519-
"implementing a foreign trait is only possible if at least one of the types for which it is implemented is local"
1520-
)]
1521-
pub(crate) struct TyParamSome {
1522-
#[primary_span]
1523-
#[label("type parameter `{$param}` must be used as the type parameter for some local type")]
1524-
pub span: Span,
1525-
#[note("only traits defined in the current crate can be implemented for a type parameter")]
1526-
pub note: (),
1527-
pub param: Ident,
1528-
}
1529-
1530-
#[derive(Diagnostic)]
1531-
#[diag("type parameter `{$param}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param}>`)", code = E0210)]
1532-
#[note(
1533-
"implementing a foreign trait is only possible if at least one of the types for which it is implemented is local"
1534-
)]
1535-
pub(crate) struct TyParamSomeLint {
1536-
#[label("type parameter `{$param}` must be used as the type parameter for some local type")]
1537-
pub span: Span,
1538-
#[note("only traits defined in the current crate can be implemented for a type parameter")]
1539-
pub note: (),
1540-
pub param: Ident,
1541-
}
1542-
15431477
#[derive(Diagnostic)]
15441478
pub(crate) enum OnlyCurrentTraits {
15451479
#[diag("only traits defined in the current crate can be implemented for types defined outside of the crate", code = E0117)]
@@ -2024,3 +1958,53 @@ pub(crate) struct PinV2OnPacked {
20241958
pub pin_v2_span: Option<Span>,
20251959
pub adt_name: Symbol,
20261960
}
1961+
1962+
pub(crate) struct UncoveredTyParam<'tcx> {
1963+
pub(crate) param: Ident,
1964+
pub(crate) local_ty: Option<Ty<'tcx>>,
1965+
}
1966+
1967+
impl<G: EmissionGuarantee> Diagnostic<'_, G> for UncoveredTyParam<'_> {
1968+
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
1969+
let Self { param, local_ty } = self;
1970+
1971+
let mut diag = Diag::new(dcx, level, "")
1972+
.with_span(param.span)
1973+
.with_span_label(param.span, "uncovered type parameter");
1974+
if diag.is_error() {
1975+
diag.code(E0210);
1976+
}
1977+
1978+
let note = "\
1979+
implementing a foreign trait is only possible if \
1980+
at least one of the types for which it is implemented is local";
1981+
1982+
if let Some(local_ty) = local_ty {
1983+
diag.primary_message(format!(
1984+
"type parameter `{param}` must be covered by another type when \
1985+
it appears before the first local type (`{local_ty}`)"
1986+
));
1987+
1988+
diag.note(format!(
1989+
"{note},\nand no uncovered type parameters appear before that first local type"
1990+
));
1991+
diag.note(
1992+
"in this case, 'before' refers to the following order: \
1993+
`impl<..> ForeignTrait<T1, ..., Tn> for T0`,\n\
1994+
where `T0` is the first and `Tn` is the last",
1995+
);
1996+
} else {
1997+
diag.primary_message(format!(
1998+
"type parameter `{param}` must be used as an argument to \
1999+
some local type (e.g., `MyStruct<{param}>`)"
2000+
));
2001+
2002+
diag.note(note);
2003+
diag.note(
2004+
"only traits defined in the current crate can be implemented for a type parameter",
2005+
);
2006+
}
2007+
2008+
diag
2009+
}
2010+
}

tests/ui/coercion/invalid-blanket-coerce-unsized-impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#![feature(coerce_unsized)]
66

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

1111
const C: usize = 1;

tests/ui/coercion/invalid-blanket-coerce-unsized-impl.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct<A>`)
1+
error[E0210]: type parameter `A` must be used as an argument to some local type (e.g., `MyStruct<A>`)
22
--> $DIR/invalid-blanket-coerce-unsized-impl.rs:7:6
33
|
44
LL | impl<A> std::ops::CoerceUnsized<A> for A {}
5-
| ^ type parameter `A` must be used as the type parameter for some local type
5+
| ^ uncovered type parameter
66
|
77
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
88
= note: only traits defined in the current crate can be implemented for a type parameter

tests/ui/coherence/coherence-all-remote.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
1+
error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct<T>`)
22
--> $DIR/coherence-all-remote.rs:6:6
33
|
44
LL | impl<T> Remote1<T> for isize { }
5-
| ^ type parameter `T` must be used as the type parameter for some local type
5+
| ^ uncovered type parameter
66
|
77
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
88
= note: only traits defined in the current crate can be implemented for a type parameter

tests/ui/coherence/coherence-bigint-param.stderr

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ error[E0210]: type parameter `T` must be covered by another type when it appears
22
--> $DIR/coherence-bigint-param.rs:8:6
33
|
44
LL | impl<T> Remote1<BigInt> for T { }
5-
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`)
5+
| ^ uncovered type parameter
66
|
7-
= 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
8-
= 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
7+
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local,
8+
and no uncovered type parameters appear before that first local type
9+
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`,
10+
where `T0` is the first and `Tn` is the last
911

1012
error: aborting due to 1 previous error
1113

tests/ui/coherence/coherence-cross-crate-conflict.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0210]: type parameter `A` must be used as the type parameter for some local type (e.g., `MyStruct<A>`)
1+
error[E0210]: type parameter `A` must be used as an argument to some local type (e.g., `MyStruct<A>`)
22
--> $DIR/coherence-cross-crate-conflict.rs:9:6
33
|
44
LL | impl<A> Foo for A {
5-
| ^ type parameter `A` must be used as the type parameter for some local type
5+
| ^ uncovered type parameter
66
|
77
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
88
= note: only traits defined in the current crate can be implemented for a type parameter

tests/ui/coherence/coherence-lone-type-parameter.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
1+
error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct<T>`)
22
--> $DIR/coherence-lone-type-parameter.rs:6:6
33
|
44
LL | impl<T> Remote for T { }
5-
| ^ type parameter `T` must be used as the type parameter for some local type
5+
| ^ uncovered type parameter
66
|
77
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
88
= note: only traits defined in the current crate can be implemented for a type parameter

tests/ui/coherence/impl[t]-foreign-for-fundamental[t].rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use std::rc::Rc;
88
struct Local;
99

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

1514
fn main() {}

tests/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
1+
error[E0210]: type parameter `T` must be used as an argument to some local type (e.g., `MyStruct<T>`)
22
--> $DIR/impl[t]-foreign-for-fundamental[t].rs:10:6
33
|
44
LL | impl<T> Remote for Box<T> {
5-
| ^ type parameter `T` must be used as the type parameter for some local type
5+
| ^ uncovered type parameter
66
|
77
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
88
= note: only traits defined in the current crate can be implemented for a type parameter

0 commit comments

Comments
 (0)