-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve the diagnostics for unused generic params in ty aliases & permit bivariant but constrained params in LTAs #120556
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,10 @@ | ||
use crate::autoderef::Autoderef; | ||
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; | ||
use crate::errors; | ||
|
||
use rustc_ast as ast; | ||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; | ||
use rustc_errors::{ | ||
codes::*, pluralize, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, | ||
}; | ||
use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; | ||
use rustc_hir as hir; | ||
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; | ||
use rustc_hir::lang_items::LangItem; | ||
|
@@ -21,7 +20,7 @@ use rustc_middle::ty::{ | |
}; | ||
use rustc_middle::ty::{GenericArgKind, GenericArgs}; | ||
use rustc_session::parse::feature_err; | ||
use rustc_span::symbol::{sym, Ident, Symbol}; | ||
use rustc_span::symbol::{sym, Ident}; | ||
use rustc_span::{Span, DUMMY_SP}; | ||
use rustc_target::spec::abi::Abi; | ||
use rustc_trait_selection::regions::InferCtxtRegionExt; | ||
|
@@ -1869,7 +1868,7 @@ 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); | ||
report_bivariance(tcx, hir_param, has_explicit_bounds, item.kind); | ||
} | ||
} | ||
} | ||
|
@@ -1879,30 +1878,38 @@ fn report_bivariance( | |
tcx: TyCtxt<'_>, | ||
param: &rustc_hir::GenericParam<'_>, | ||
has_explicit_bounds: bool, | ||
item_kind: ItemKind<'_>, | ||
) -> ErrorGuaranteed { | ||
let span = param.span; | ||
let param_name = param.name.ident().name; | ||
let mut err = error_392(tcx, span, param_name); | ||
|
||
let suggested_marker_id = tcx.lang_items().phantom_data(); | ||
// Help is available only in presence of lang items. | ||
let msg = if let Some(def_id) = suggested_marker_id { | ||
format!( | ||
"consider removing `{}`, referring to it in a field, or using a marker such as `{}`", | ||
param_name, | ||
tcx.def_path_str(def_id), | ||
) | ||
} else { | ||
format!("consider removing `{param_name}` or referring to it in a field") | ||
let param_name = param.name.ident(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm no longer extracting the |
||
|
||
let help = match item_kind { | ||
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { | ||
if let Some(def_id) = tcx.lang_items().phantom_data() { | ||
errors::UnusedGenericParameterHelp::Adt { | ||
param_name, | ||
phantom_data: tcx.def_path_str(def_id), | ||
} | ||
} else { | ||
errors::UnusedGenericParameterHelp::AdtNoPhantomData { param_name } | ||
} | ||
} | ||
ItemKind::TyAlias(..) => errors::UnusedGenericParameterHelp::TyAlias { param_name }, | ||
item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"), | ||
}; | ||
err.help(msg); | ||
|
||
if matches!(param.kind, hir::GenericParamKind::Type { .. }) && !has_explicit_bounds { | ||
err.help(format!( | ||
"if you intended `{param_name}` to be a const parameter, use `const {param_name}: usize` instead" | ||
)); | ||
} | ||
err.emit() | ||
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() | ||
} | ||
|
||
impl<'tcx> WfCheckingCtxt<'_, 'tcx> { | ||
|
@@ -1967,11 +1974,6 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error | |
res | ||
} | ||
|
||
fn error_392(tcx: TyCtxt<'_>, span: Span, param_name: Symbol) -> DiagnosticBuilder<'_> { | ||
struct_span_code_err!(tcx.dcx(), span, E0392, "parameter `{param_name}` is never used") | ||
.with_span_label(span, "unused parameter") | ||
} | ||
|
||
pub fn provide(providers: &mut Providers) { | ||
*providers = Providers { check_mod_type_wf, check_well_formed, ..*providers }; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,14 +10,14 @@ error: expected identifier, found reserved identifier `_` | |
LL | fn bad_infer_fn<_>() {} | ||
| ^ expected identifier, found reserved identifier | ||
|
||
error[E0392]: parameter `_` is never used | ||
error[E0392]: type parameter `_` is never used | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could add extra code for skipping this error entirely by delaying a bug on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be very hard to track the |
||
--> $DIR/infer-arg-test.rs:7:17 | ||
| | ||
LL | struct BadInfer<_>; | ||
| ^ unused parameter | ||
| ^ unused type parameter | ||
| | ||
= help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData` | ||
= help: if you intended `_` to be a const parameter, use `const _: usize` instead | ||
= help: if you intended `_` to be a const parameter, use `const _: /* Type */` instead | ||
|
||
error[E0107]: struct takes 2 generic arguments but 3 generic arguments were supplied | ||
--> $DIR/infer-arg-test.rs:18:10 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't want to deal with this right now but I can try to do so if you'd like me to. I think it'll be a bit nasty to implement though. Consider a hypothetical set of predicates like
[<A as TraitA>, <B as TraitB>, /*elab*/<A as Sized>]
(note: we need to merge the spans of the 0th and the 2nd predicate).Maybe it's actually not that ugly to implement, I just haven't spent any time to think about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does it rely on that? the spans differ, so both elaborated and user-written would end up in the hash set
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤦 it's a hashmap and this collect relies on the hash map impl overwriting with follow up items of the same key
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems fine to rely on this, there are tests after all