mirror of https://github.com/rust-lang/rust.git
Mention that type parameters are used recursively
This commit is contained in:
parent
3de0a7c716
commit
3716a3fd31
|
@ -382,6 +382,10 @@ hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is no
|
|||
hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
|
||||
.label = `Self` is not a generic argument, but an alias to the type of the {$what}
|
||||
|
||||
hir_analysis_recursive_generic_parameter = {$param_def_kind} `{$param_name}` is only used recursively
|
||||
.label = {$param_def_kind} must be used non-recursively in the definition
|
||||
.note = all type parameters must be used in a non-recursive way in order to constrain its variance
|
||||
|
||||
hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}`
|
||||
.note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}`
|
||||
|
||||
|
@ -549,6 +553,7 @@ hir_analysis_unused_generic_parameter =
|
|||
{$param_def_kind} `{$param_name}` is never used
|
||||
.label = unused {$param_def_kind}
|
||||
.const_param_help = if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead
|
||||
|
||||
hir_analysis_unused_generic_parameter_adt_help =
|
||||
consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}`
|
||||
hir_analysis_unused_generic_parameter_adt_no_phantom_data_help =
|
||||
|
|
|
@ -4,12 +4,12 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par
|
|||
use crate::errors;
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
use hir::intravisit::Visitor;
|
||||
use hir::intravisit::{self, Visitor};
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
||||
use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::ItemKind;
|
||||
|
@ -1799,7 +1799,7 @@ fn receiver_is_implemented<'tcx>(
|
|||
|
||||
fn check_variances_for_type_defn<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item: &hir::Item<'tcx>,
|
||||
item: &'tcx hir::Item<'tcx>,
|
||||
hir_generics: &hir::Generics<'tcx>,
|
||||
) {
|
||||
let identity_args = ty::GenericArgs::identity_for_item(tcx, item.owner_id);
|
||||
|
@ -1886,21 +1886,21 @@ fn check_variances_for_type_defn<'tcx>(
|
|||
hir::ParamName::Error => {}
|
||||
_ => {
|
||||
let has_explicit_bounds = explicitly_bounded_params.contains(¶meter);
|
||||
report_bivariance(tcx, hir_param, has_explicit_bounds, item.kind);
|
||||
report_bivariance(tcx, hir_param, has_explicit_bounds, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn report_bivariance(
|
||||
tcx: TyCtxt<'_>,
|
||||
param: &rustc_hir::GenericParam<'_>,
|
||||
fn report_bivariance<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param: &'tcx hir::GenericParam<'tcx>,
|
||||
has_explicit_bounds: bool,
|
||||
item_kind: ItemKind<'_>,
|
||||
item: &'tcx hir::Item<'tcx>,
|
||||
) -> ErrorGuaranteed {
|
||||
let param_name = param.name.ident();
|
||||
|
||||
let help = match item_kind {
|
||||
let help = match item.kind {
|
||||
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
|
||||
if let Some(def_id) = tcx.lang_items().phantom_data() {
|
||||
errors::UnusedGenericParameterHelp::Adt {
|
||||
|
@ -1915,19 +1915,60 @@ fn report_bivariance(
|
|||
item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"),
|
||||
};
|
||||
|
||||
let const_param_help =
|
||||
matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds)
|
||||
.then_some(());
|
||||
let mut usage_spans = vec![];
|
||||
intravisit::walk_item(
|
||||
&mut CollectUsageSpans { spans: &mut usage_spans, param_def_id: param.def_id.to_def_id() },
|
||||
item,
|
||||
);
|
||||
|
||||
let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter {
|
||||
span: param.span,
|
||||
param_name,
|
||||
param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
|
||||
help,
|
||||
const_param_help,
|
||||
});
|
||||
diag.code(E0392);
|
||||
diag.emit()
|
||||
if usage_spans.is_empty() {
|
||||
let const_param_help =
|
||||
matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds)
|
||||
.then_some(());
|
||||
|
||||
let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter {
|
||||
span: param.span,
|
||||
param_name,
|
||||
param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
|
||||
help,
|
||||
const_param_help,
|
||||
});
|
||||
diag.code(E0392);
|
||||
diag.emit()
|
||||
} else {
|
||||
let diag = tcx.dcx().create_err(errors::RecursiveGenericParameter {
|
||||
spans: usage_spans,
|
||||
param_span: param.span,
|
||||
param_name,
|
||||
param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
|
||||
help,
|
||||
note: (),
|
||||
});
|
||||
diag.emit()
|
||||
}
|
||||
}
|
||||
|
||||
struct CollectUsageSpans<'a> {
|
||||
spans: &'a mut Vec<Span>,
|
||||
param_def_id: DefId,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for CollectUsageSpans<'_> {
|
||||
type Result = ();
|
||||
|
||||
fn visit_generics(&mut self, _g: &'tcx rustc_hir::Generics<'tcx>) -> Self::Result {
|
||||
// Skip the generics. We only care about fields, not where clause/param bounds.
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
||||
if let hir::TyKind::Path(hir::QPath::Resolved(None, qpath)) = t.kind
|
||||
&& let Res::Def(DefKind::TyParam, def_id) = qpath.res
|
||||
&& def_id == self.param_def_id
|
||||
{
|
||||
self.spans.push(t.span);
|
||||
}
|
||||
intravisit::walk_ty(self, t);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
|
||||
|
|
|
@ -1603,6 +1603,21 @@ pub(crate) struct UnusedGenericParameter {
|
|||
pub const_param_help: Option<()>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_recursive_generic_parameter)]
|
||||
pub(crate) struct RecursiveGenericParameter {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
#[label]
|
||||
pub param_span: Span,
|
||||
pub param_name: Ident,
|
||||
pub param_def_kind: &'static str,
|
||||
#[subdiagnostic]
|
||||
pub help: UnusedGenericParameterHelp,
|
||||
#[note]
|
||||
pub note: (),
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum UnusedGenericParameterHelp {
|
||||
#[help(hir_analysis_unused_generic_parameter_adt_help)]
|
||||
|
|
|
@ -4,23 +4,27 @@ error[E0275]: overflow evaluating the requirement `Loop == _`
|
|||
LL | impl Loop {}
|
||||
| ^^^^
|
||||
|
||||
error[E0392]: type parameter `T` is never used
|
||||
--> $DIR/inherent-impls-overflow.rs:14:12
|
||||
error: type parameter `T` is only used recursively
|
||||
--> $DIR/inherent-impls-overflow.rs:14:24
|
||||
|
|
||||
LL | type Poly0<T> = Poly1<(T,)>;
|
||||
| ^ unused type parameter
|
||||
| - ^
|
||||
| |
|
||||
| type parameter must be used non-recursively in the definition
|
||||
|
|
||||
= help: consider removing `T` or referring to it in the body of the type alias
|
||||
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
|
||||
= note: all type parameters must be used in a non-recursive way in order to constrain its variance
|
||||
|
||||
error[E0392]: type parameter `T` is never used
|
||||
--> $DIR/inherent-impls-overflow.rs:17:12
|
||||
error: type parameter `T` is only used recursively
|
||||
--> $DIR/inherent-impls-overflow.rs:17:24
|
||||
|
|
||||
LL | type Poly1<T> = Poly0<(T,)>;
|
||||
| ^ unused type parameter
|
||||
| - ^
|
||||
| |
|
||||
| type parameter must be used non-recursively in the definition
|
||||
|
|
||||
= help: consider removing `T` or referring to it in the body of the type alias
|
||||
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
|
||||
= note: all type parameters must be used in a non-recursive way in order to constrain its variance
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `Poly0<()> == _`
|
||||
--> $DIR/inherent-impls-overflow.rs:21:6
|
||||
|
@ -32,5 +36,4 @@ LL | impl Poly0<()> {}
|
|||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0275, E0392.
|
||||
For more information about an error, try `rustc --explain E0275`.
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
|
|
@ -13,10 +13,10 @@ impl Loop {}
|
|||
|
||||
type Poly0<T> = Poly1<(T,)>;
|
||||
//[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
|
||||
//[next]~^^ ERROR type parameter `T` is never used
|
||||
//[next]~^^ ERROR type parameter `T` is only used recursively
|
||||
type Poly1<T> = Poly0<(T,)>;
|
||||
//[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
|
||||
//[next]~^^ ERROR type parameter `T` is never used
|
||||
//[next]~^^ ERROR type parameter `T` is only used recursively
|
||||
|
||||
impl Poly0<()> {}
|
||||
//[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
//~ ERROR overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
|
||||
struct A<T>(B<T>);
|
||||
//~^ ERROR recursive types `A` and `B` have infinite size
|
||||
//~| ERROR `T` is never used
|
||||
//~| ERROR `T` is only used recursively
|
||||
struct B<T>(A<A<T>>);
|
||||
//~^ ERROR `T` is never used
|
||||
//~^ ERROR `T` is only used recursively
|
||||
trait Foo {}
|
||||
impl<T> Foo for T where T: Send {}
|
||||
impl Foo for B<u8> {}
|
||||
|
|
|
@ -15,23 +15,27 @@ LL |
|
|||
LL ~ struct B<T>(Box<A<A<T>>>);
|
||||
|
|
||||
|
||||
error[E0392]: type parameter `T` is never used
|
||||
--> $DIR/issue-105231.rs:2:10
|
||||
error: type parameter `T` is only used recursively
|
||||
--> $DIR/issue-105231.rs:2:15
|
||||
|
|
||||
LL | struct A<T>(B<T>);
|
||||
| ^ unused type parameter
|
||||
| - ^
|
||||
| |
|
||||
| type parameter must be used non-recursively in the definition
|
||||
|
|
||||
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
||||
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
|
||||
= note: all type parameters must be used in a non-recursive way in order to constrain its variance
|
||||
|
||||
error[E0392]: type parameter `T` is never used
|
||||
--> $DIR/issue-105231.rs:5:10
|
||||
error: type parameter `T` is only used recursively
|
||||
--> $DIR/issue-105231.rs:5:17
|
||||
|
|
||||
LL | struct B<T>(A<A<T>>);
|
||||
| ^ unused type parameter
|
||||
| - ^
|
||||
| |
|
||||
| type parameter must be used non-recursively in the definition
|
||||
|
|
||||
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
||||
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
|
||||
= note: all type parameters must be used in a non-recursive way in order to constrain its variance
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
|
||||
|
|
||||
|
@ -44,5 +48,5 @@ LL | struct B<T>(A<A<T>>);
|
|||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0072, E0275, E0392.
|
||||
Some errors have detailed explanations: E0072, E0275.
|
||||
For more information about an error, try `rustc --explain E0072`.
|
||||
|
|
|
@ -11,8 +11,8 @@ enum SomeEnum<A> { Nothing }
|
|||
|
||||
// Here T might *appear* used, but in fact it isn't.
|
||||
enum ListCell<T> {
|
||||
//~^ ERROR parameter `T` is never used
|
||||
Cons(Box<ListCell<T>>),
|
||||
//~^ ERROR parameter `T` is only used recursively
|
||||
Nil
|
||||
}
|
||||
|
||||
|
|
|
@ -16,14 +16,16 @@ LL | enum SomeEnum<A> { Nothing }
|
|||
= help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData`
|
||||
= help: if you intended `A` to be a const parameter, use `const A: /* Type */` instead
|
||||
|
||||
error[E0392]: type parameter `T` is never used
|
||||
--> $DIR/variance-unused-type-param.rs:13:15
|
||||
error: type parameter `T` is only used recursively
|
||||
--> $DIR/variance-unused-type-param.rs:14:23
|
||||
|
|
||||
LL | enum ListCell<T> {
|
||||
| ^ unused type parameter
|
||||
| - type parameter must be used non-recursively in the definition
|
||||
LL | Cons(Box<ListCell<T>>),
|
||||
| ^
|
||||
|
|
||||
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
||||
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
|
||||
= note: all type parameters must be used in a non-recursive way in order to constrain its variance
|
||||
|
||||
error[E0392]: type parameter `T` is never used
|
||||
--> $DIR/variance-unused-type-param.rs:19:19
|
||||
|
|
Loading…
Reference in New Issue