Skip to content

Commit 4d87c4a

Browse files
committed
Auto merge of rust-lang#120649 - matthiaskrgr:rollup-ek80j61, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#119759 (Add FileCheck annotations to dataflow-const-prop tests) - rust-lang#120323 (On E0277 be clearer about implicit `Sized` bounds on type params and assoc types) - rust-lang#120473 (Only suggest removal of `as_*` and `to_` conversion methods on E0308) - rust-lang#120540 (add test for try-block-in-match-arm) - rust-lang#120547 (`#![feature(inline_const_pat)]` is no longer incomplete) - rust-lang#120552 (Correctly check `never_type` feature gating) - rust-lang#120555 (put pnkfelix (me) back on the review queue.) - rust-lang#120556 (Improve the diagnostics for unused generic parameters) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 268dbbb + 7fa99bf commit 4d87c4a

File tree

161 files changed

+1151
-541
lines changed

Some content is hidden

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

161 files changed

+1151
-541
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

+13
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
362362
}
363363
}
364364

365+
fn visit_generic_args(&mut self, args: &'a ast::GenericArgs) {
366+
// This check needs to happen here because the never type can be returned from a function,
367+
// but cannot be used in any other context. If this check was in `visit_fn_ret_ty`, it
368+
// include both functions and generics like `impl Fn() -> !`.
369+
if let ast::GenericArgs::Parenthesized(generic_args) = args
370+
&& let ast::FnRetTy::Ty(ref ty) = generic_args.output
371+
&& matches!(ty.kind, ast::TyKind::Never)
372+
{
373+
gate!(&self, never_type, ty.span, "the `!` type is experimental");
374+
}
375+
visit::walk_generic_args(self, args);
376+
}
377+
365378
fn visit_expr(&mut self, e: &'a ast::Expr) {
366379
match e.kind {
367380
ast::ExprKind::TryBlock(_) => {

compiler/rustc_error_codes/src/error_codes/E0091.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
An unnecessary type or const parameter was given in a type alias.
1+
An unnecessary type parameter was given in a type alias.
22

33
Erroneous code example:
44

55
```compile_fail,E0091
6-
type Foo<T> = u32; // error: type parameter `T` is unused
6+
type Foo<T> = u32; // error: type parameter `T` is never used
77
// or:
8-
type Foo<A,B> = Box<A>; // error: type parameter `B` is unused
8+
type Foo<A, B> = Box<A>; // error: type parameter `B` is never used
99
```
1010

1111
Please check you didn't write too many parameters. Example:

compiler/rustc_feature/src/unstable.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ declare_features! (
496496
/// Allow anonymous constants from an inline `const` block
497497
(unstable, inline_const, "1.49.0", Some(76001)),
498498
/// Allow anonymous constants from an inline `const` block in pattern position
499-
(incomplete, inline_const_pat, "1.58.0", Some(76001)),
499+
(unstable, inline_const_pat, "1.58.0", Some(76001)),
500500
/// Allows using `pointer` and `reference` in intra-doc links
501501
(unstable, intra_doc_pointers, "1.51.0", Some(80896)),
502502
// Allows setting the threshold for the `large_assignments` lint.

compiler/rustc_hir_analysis/messages.ftl

+11
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,17 @@ hir_analysis_unused_associated_type_bounds =
434434
.note = this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`.
435435
.suggestion = remove this bound
436436
437+
hir_analysis_unused_generic_parameter =
438+
{$param_def_kind} `{$param_name}` is never used
439+
.label = unused {$param_def_kind}
440+
.const_param_help = if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead
441+
hir_analysis_unused_generic_parameter_adt_help =
442+
consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}`
443+
hir_analysis_unused_generic_parameter_adt_no_phantom_data_help =
444+
consider removing `{$param_name}` or referring to it in a field
445+
hir_analysis_unused_generic_parameter_ty_alias_help =
446+
consider removing `{$param_name}` or referring to it in the body of the type alias
447+
437448
hir_analysis_value_of_associated_struct_already_specified =
438449
the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified
439450
.label = re-bound here

compiler/rustc_hir_analysis/src/astconv/bounds.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
2828
let tcx = self.tcx();
2929
let sized_def_id = tcx.lang_items().sized_trait();
3030
let mut seen_negative_sized_bound = false;
31+
let mut seen_positive_sized_bound = false;
3132

3233
// Try to find an unbound in bounds.
3334
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
@@ -45,6 +46,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
4546
seen_negative_sized_bound = true;
4647
}
4748
}
49+
hir::TraitBoundModifier::None => {
50+
if let Some(sized_def_id) = sized_def_id
51+
&& ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
52+
{
53+
seen_positive_sized_bound = true;
54+
}
55+
}
4856
_ => {}
4957
}
5058
}
@@ -82,11 +90,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
8290
);
8391
}
8492

85-
if seen_sized_unbound || seen_negative_sized_bound {
86-
// There was in fact a `?Sized` or `!Sized` bound;
93+
if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound {
94+
// There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound;
8795
// we don't need to do anything.
8896
} else if sized_def_id.is_some() {
89-
// There was no `?Sized` or `!Sized` bound;
97+
// There was no `?Sized`, `!Sized` or explicit `Sized` bound;
9098
// add `Sized` if it's available.
9199
bounds.push_sized(tcx, self_ty, span);
92100
}

compiler/rustc_hir_analysis/src/check/check.rs

+54-23
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
3131
use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _};
3232
use rustc_type_ir::fold::TypeFoldable;
3333

34+
use std::cell::LazyCell;
3435
use std::ops::ControlFlow;
3536

3637
pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
@@ -520,9 +521,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
520521
}
521522
}
522523
DefKind::TyAlias => {
523-
let pty_ty = tcx.type_of(def_id).instantiate_identity();
524-
let generics = tcx.generics_of(def_id);
525-
check_type_params_are_used(tcx, generics, pty_ty);
524+
check_type_alias_type_params_are_used(tcx, def_id);
526525
}
527526
DefKind::ForeignMod => {
528527
let it = tcx.hir().expect_item(def_id);
@@ -1269,28 +1268,51 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
12691268
}
12701269
}
12711270

1272-
pub(super) fn check_type_params_are_used<'tcx>(
1273-
tcx: TyCtxt<'tcx>,
1274-
generics: &ty::Generics,
1275-
ty: Ty<'tcx>,
1276-
) {
1277-
debug!("check_type_params_are_used(generics={:?}, ty={:?})", generics, ty);
1278-
1279-
assert_eq!(generics.parent, None);
1271+
fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
1272+
if tcx.type_alias_is_lazy(def_id) {
1273+
// Since we compute the variances for lazy type aliases and already reject bivariant
1274+
// parameters as unused, we can and should skip this check for lazy type aliases.
1275+
return;
1276+
}
12801277

1278+
let generics = tcx.generics_of(def_id);
12811279
if generics.own_counts().types == 0 {
12821280
return;
12831281
}
12841282

1285-
let mut params_used = BitSet::new_empty(generics.params.len());
1286-
1283+
let ty = tcx.type_of(def_id).instantiate_identity();
12871284
if ty.references_error() {
1288-
// If there is already another error, do not emit
1289-
// an error for not using a type parameter.
1285+
// If there is already another error, do not emit an error for not using a type parameter.
12901286
assert!(tcx.dcx().has_errors().is_some());
12911287
return;
12921288
}
12931289

1290+
// Lazily calculated because it is only needed in case of an error.
1291+
let bounded_params = LazyCell::new(|| {
1292+
tcx.explicit_predicates_of(def_id)
1293+
.predicates
1294+
.iter()
1295+
.filter_map(|(predicate, span)| {
1296+
let bounded_ty = match predicate.kind().skip_binder() {
1297+
ty::ClauseKind::Trait(pred) => pred.trait_ref.self_ty(),
1298+
ty::ClauseKind::TypeOutlives(pred) => pred.0,
1299+
_ => return None,
1300+
};
1301+
if let ty::Param(param) = bounded_ty.kind() {
1302+
Some((param.index, span))
1303+
} else {
1304+
None
1305+
}
1306+
})
1307+
// FIXME: This assumes that elaborated `Sized` bounds come first (which does hold at the
1308+
// time of writing). This is a bit fragile since we later use the span to detect elaborated
1309+
// `Sized` bounds. If they came last for example, this would break `Trait + /*elab*/Sized`
1310+
// since it would overwrite the span of the user-written bound. This could be fixed by
1311+
// folding the spans with `Span::to` which requires a bit of effort I think.
1312+
.collect::<FxHashMap<_, _>>()
1313+
});
1314+
1315+
let mut params_used = BitSet::new_empty(generics.params.len());
12941316
for leaf in ty.walk() {
12951317
if let GenericArgKind::Type(leaf_ty) = leaf.unpack()
12961318
&& let ty::Param(param) = leaf_ty.kind()
@@ -1305,15 +1327,24 @@ pub(super) fn check_type_params_are_used<'tcx>(
13051327
&& let ty::GenericParamDefKind::Type { .. } = param.kind
13061328
{
13071329
let span = tcx.def_span(param.def_id);
1308-
struct_span_code_err!(
1309-
tcx.dcx(),
1330+
let param_name = Ident::new(param.name, span);
1331+
1332+
// The corresponding predicates are post-`Sized`-elaboration. Therefore we
1333+
// * check for emptiness to detect lone user-written `?Sized` bounds
1334+
// * compare the param span to the pred span to detect lone user-written `Sized` bounds
1335+
let has_explicit_bounds = bounded_params.is_empty()
1336+
|| (*bounded_params).get(&param.index).is_some_and(|&&pred_sp| pred_sp != span);
1337+
let const_param_help = (!has_explicit_bounds).then_some(());
1338+
1339+
let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter {
13101340
span,
1311-
E0091,
1312-
"type parameter `{}` is unused",
1313-
param.name,
1314-
)
1315-
.with_span_label(span, "unused type parameter")
1316-
.emit();
1341+
param_name,
1342+
param_def_kind: tcx.def_descr(param.def_id),
1343+
help: errors::UnusedGenericParameterHelp::TyAlias { param_name },
1344+
const_param_help,
1345+
});
1346+
diag.code(E0091);
1347+
diag.emit();
13171348
}
13181349
}
13191350
}

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+33-31
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use crate::autoderef::Autoderef;
22
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
3+
use crate::errors;
34

45
use rustc_ast as ast;
56
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
6-
use rustc_errors::{
7-
codes::*, pluralize, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
8-
};
7+
use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
98
use rustc_hir as hir;
109
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
1110
use rustc_hir::lang_items::LangItem;
@@ -21,7 +20,7 @@ use rustc_middle::ty::{
2120
};
2221
use rustc_middle::ty::{GenericArgKind, GenericArgs};
2322
use rustc_session::parse::feature_err;
24-
use rustc_span::symbol::{sym, Ident, Symbol};
23+
use rustc_span::symbol::{sym, Ident};
2524
use rustc_span::{Span, DUMMY_SP};
2625
use rustc_target::spec::abi::Abi;
2726
use rustc_trait_selection::regions::InferCtxtRegionExt;
@@ -1869,7 +1868,7 @@ fn check_variances_for_type_defn<'tcx>(
18691868
hir::ParamName::Error => {}
18701869
_ => {
18711870
let has_explicit_bounds = explicitly_bounded_params.contains(&parameter);
1872-
report_bivariance(tcx, hir_param, has_explicit_bounds);
1871+
report_bivariance(tcx, hir_param, has_explicit_bounds, item.kind);
18731872
}
18741873
}
18751874
}
@@ -1879,30 +1878,38 @@ fn report_bivariance(
18791878
tcx: TyCtxt<'_>,
18801879
param: &rustc_hir::GenericParam<'_>,
18811880
has_explicit_bounds: bool,
1881+
item_kind: ItemKind<'_>,
18821882
) -> ErrorGuaranteed {
1883-
let span = param.span;
1884-
let param_name = param.name.ident().name;
1885-
let mut err = error_392(tcx, span, param_name);
1886-
1887-
let suggested_marker_id = tcx.lang_items().phantom_data();
1888-
// Help is available only in presence of lang items.
1889-
let msg = if let Some(def_id) = suggested_marker_id {
1890-
format!(
1891-
"consider removing `{}`, referring to it in a field, or using a marker such as `{}`",
1892-
param_name,
1893-
tcx.def_path_str(def_id),
1894-
)
1895-
} else {
1896-
format!("consider removing `{param_name}` or referring to it in a field")
1883+
let param_name = param.name.ident();
1884+
1885+
let help = match item_kind {
1886+
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
1887+
if let Some(def_id) = tcx.lang_items().phantom_data() {
1888+
errors::UnusedGenericParameterHelp::Adt {
1889+
param_name,
1890+
phantom_data: tcx.def_path_str(def_id),
1891+
}
1892+
} else {
1893+
errors::UnusedGenericParameterHelp::AdtNoPhantomData { param_name }
1894+
}
1895+
}
1896+
ItemKind::TyAlias(..) => errors::UnusedGenericParameterHelp::TyAlias { param_name },
1897+
item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"),
18971898
};
1898-
err.help(msg);
18991899

1900-
if matches!(param.kind, hir::GenericParamKind::Type { .. }) && !has_explicit_bounds {
1901-
err.help(format!(
1902-
"if you intended `{param_name}` to be a const parameter, use `const {param_name}: usize` instead"
1903-
));
1904-
}
1905-
err.emit()
1900+
let const_param_help =
1901+
matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds)
1902+
.then_some(());
1903+
1904+
let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter {
1905+
span: param.span,
1906+
param_name,
1907+
param_def_kind: tcx.def_descr(param.def_id.to_def_id()),
1908+
help,
1909+
const_param_help,
1910+
});
1911+
diag.code(E0392);
1912+
diag.emit()
19061913
}
19071914

19081915
impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
@@ -1967,11 +1974,6 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error
19671974
res
19681975
}
19691976

1970-
fn error_392(tcx: TyCtxt<'_>, span: Span, param_name: Symbol) -> DiagnosticBuilder<'_> {
1971-
struct_span_code_err!(tcx.dcx(), span, E0392, "parameter `{param_name}` is never used")
1972-
.with_span_label(span, "unused parameter")
1973-
}
1974-
19751977
pub fn provide(providers: &mut Providers) {
19761978
*providers = Providers { check_mod_type_wf, check_well_formed, ..*providers };
19771979
}

compiler/rustc_hir_analysis/src/errors.rs

+24
Original file line numberDiff line numberDiff line change
@@ -1511,3 +1511,27 @@ pub struct NotSupportedDelegation<'a> {
15111511
#[label]
15121512
pub callee_span: Span,
15131513
}
1514+
1515+
#[derive(Diagnostic)]
1516+
#[diag(hir_analysis_unused_generic_parameter)]
1517+
pub(crate) struct UnusedGenericParameter {
1518+
#[primary_span]
1519+
#[label]
1520+
pub span: Span,
1521+
pub param_name: Ident,
1522+
pub param_def_kind: &'static str,
1523+
#[subdiagnostic]
1524+
pub help: UnusedGenericParameterHelp,
1525+
#[help(hir_analysis_const_param_help)]
1526+
pub const_param_help: Option<()>,
1527+
}
1528+
1529+
#[derive(Subdiagnostic)]
1530+
pub(crate) enum UnusedGenericParameterHelp {
1531+
#[help(hir_analysis_unused_generic_parameter_adt_help)]
1532+
Adt { param_name: Ident, phantom_data: String },
1533+
#[help(hir_analysis_unused_generic_parameter_adt_no_phantom_data_help)]
1534+
AdtNoPhantomData { param_name: Ident },
1535+
#[help(hir_analysis_unused_generic_parameter_ty_alias_help)]
1536+
TyAlias { param_name: Ident },
1537+
}

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+2
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
261261
expr.kind
262262
&& let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr)
263263
&& self.can_coerce(recv_ty, expected)
264+
&& let name = method.name.as_str()
265+
&& (name.starts_with("to_") || name.starts_with("as_") || name == "into")
264266
{
265267
let span = if let Some(recv_span) = recv_expr.span.find_ancestor_inside(expr.span) {
266268
expr.span.with_lo(recv_span.hi())

0 commit comments

Comments
 (0)