Skip to content
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

Rollup of 8 pull requests #120649

Merged
merged 38 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
1eaeaaf
Add FileCheck for array_index.rs, boolean_identities.rs and cast.rs
sfzhu93 Jan 8, 2024
e05c779
Add FileCheck for checked.rs and default_boxed_slice.rs.
sfzhu93 Jan 8, 2024
33e5d85
Add FileCheck for enum.rs
sfzhu93 Jan 8, 2024
24aefa0
Add FileCheck for if.rs, inherit_overflow.rs, issue_81605.rs
sfzhu93 Jan 9, 2024
9452d7e
Add FileCheck to 3 tests: large_array_index, mult_by_zero, and offset_of
sfzhu93 Jan 9, 2024
e9152e2
Add FileCheck to 3 tests: ref_without_sb, repeat, repr_transparent
sfzhu93 Jan 9, 2024
3ab1d5d
Add FileCheck to 3 tests: self_assign_add, self_assign, and sibling_ptr
sfzhu93 Jan 9, 2024
d765e3a
Add FileCheck to slice_len.rs
sfzhu93 Jan 9, 2024
732f6a1
Add FileCheck to struct.rs
sfzhu93 Jan 9, 2024
1adda9a
Add FileCheck to terminator.rs and tuple.rs
sfzhu93 Jan 9, 2024
7135168
Add FileCheck for enum.rs
sfzhu93 Jan 8, 2024
d63f10b
resolve code reviews
sfzhu93 Jan 12, 2024
1c886d7
resolve code reviews
sfzhu93 Jan 12, 2024
cd77d59
update enum.rs for code review
sfzhu93 Jan 13, 2024
5747ece
add FIXME for default_boxed_slice.rs
sfzhu93 Jan 15, 2024
edba949
update misuse of check-label
sfzhu93 Jan 20, 2024
7ad307d
finish a pattern in `enum.rs`
sfzhu93 Jan 20, 2024
65b1083
update enum.rs
sfzhu93 Jan 23, 2024
699b59c
update terminator.rs
sfzhu93 Jan 29, 2024
44d8ecb
Only suggest removal of `as_*` and `to_` conversion methods on E0308
estebank Jan 29, 2024
c4c22b0
On E0277 be clearer about implicit `Sized` bounds on type params and …
estebank Jan 24, 2024
95d9009
Change incr comp test when adding explicit `Sized` bound
estebank Jan 25, 2024
8b0ab54
review comment: change wording
estebank Jan 30, 2024
4feec41
`#![feature(inline_const_pat)]` is no longer incomplete
matthewjasper Feb 1, 2024
0148da3
put pnkfelix (me) back on the review queue.
pnkfelix Feb 1, 2024
02320b5
Improve the diagnostics for unused generic parameters
fmease Feb 1, 2024
bedd81e
add test for try-block-in-match-arm
Fishrock123 Feb 1, 2024
2c0030f
Correctly check `never_type` feature gating
GuillaumeGomez Feb 1, 2024
0f21e45
Update `never_type` feature gate ui test
GuillaumeGomez Feb 1, 2024
0df6dfd
fix rebase
estebank Feb 1, 2024
2b25957
Rollup merge of #119759 - sfzhu93:master, r=cjgillot
matthiaskrgr Feb 4, 2024
6af0458
Rollup merge of #120323 - estebank:issue-120178, r=fmease
matthiaskrgr Feb 4, 2024
b23945c
Rollup merge of #120473 - estebank:issue-114329, r=TaKO8Ki
matthiaskrgr Feb 4, 2024
592beb1
Rollup merge of #120540 - Fishrock123:test-try-block-in-match-arm, r=…
matthiaskrgr Feb 4, 2024
fa7d3e9
Rollup merge of #120547 - matthewjasper:complete-inline-const-pat, r=…
matthiaskrgr Feb 4, 2024
c2ad283
Rollup merge of #120552 - GuillaumeGomez:never-type-feature-gate, r=c…
matthiaskrgr Feb 4, 2024
1547510
Rollup merge of #120555 - pnkfelix:put-pnkfelix-back-on-review-queue,…
matthiaskrgr Feb 4, 2024
7fa99bf
Rollup merge of #120556 - fmease:improve-unused-generic-param-diags, …
matthiaskrgr Feb 4, 2024
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
13 changes: 13 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}

fn visit_generic_args(&mut self, args: &'a ast::GenericArgs) {
// This check needs to happen here because the never type can be returned from a function,
// but cannot be used in any other context. If this check was in `visit_fn_ret_ty`, it
// include both functions and generics like `impl Fn() -> !`.
if let ast::GenericArgs::Parenthesized(generic_args) = args
&& let ast::FnRetTy::Ty(ref ty) = generic_args.output
&& matches!(ty.kind, ast::TyKind::Never)
{
gate!(&self, never_type, ty.span, "the `!` type is experimental");
}
visit::walk_generic_args(self, args);
}

fn visit_expr(&mut self, e: &'a ast::Expr) {
match e.kind {
ast::ExprKind::TryBlock(_) => {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_error_codes/src/error_codes/E0091.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
An unnecessary type or const parameter was given in a type alias.
An unnecessary type parameter was given in a type alias.

Erroneous code example:

```compile_fail,E0091
type Foo<T> = u32; // error: type parameter `T` is unused
type Foo<T> = u32; // error: type parameter `T` is never used
// or:
type Foo<A,B> = Box<A>; // error: type parameter `B` is unused
type Foo<A, B> = Box<A>; // error: type parameter `B` is never used
```

Please check you didn't write too many parameters. Example:
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ declare_features! (
/// Allow anonymous constants from an inline `const` block
(unstable, inline_const, "1.49.0", Some(76001)),
/// Allow anonymous constants from an inline `const` block in pattern position
(incomplete, inline_const_pat, "1.58.0", Some(76001)),
(unstable, inline_const_pat, "1.58.0", Some(76001)),
/// Allows using `pointer` and `reference` in intra-doc links
(unstable, intra_doc_pointers, "1.51.0", Some(80896)),
// Allows setting the threshold for the `large_assignments` lint.
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,17 @@ hir_analysis_unused_associated_type_bounds =
.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`.
.suggestion = remove this bound

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 =
consider removing `{$param_name}` or referring to it in a field
hir_analysis_unused_generic_parameter_ty_alias_help =
consider removing `{$param_name}` or referring to it in the body of the type alias

hir_analysis_value_of_associated_struct_already_specified =
the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified
.label = re-bound here
Expand Down
14 changes: 11 additions & 3 deletions compiler/rustc_hir_analysis/src/astconv/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
let tcx = self.tcx();
let sized_def_id = tcx.lang_items().sized_trait();
let mut seen_negative_sized_bound = false;
let mut seen_positive_sized_bound = false;

// Try to find an unbound in bounds.
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
Expand All @@ -45,6 +46,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
seen_negative_sized_bound = true;
}
}
hir::TraitBoundModifier::None => {
if let Some(sized_def_id) = sized_def_id
&& ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
{
seen_positive_sized_bound = true;
}
}
_ => {}
}
}
Expand Down Expand Up @@ -82,11 +90,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
);
}

if seen_sized_unbound || seen_negative_sized_bound {
// There was in fact a `?Sized` or `!Sized` bound;
if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound {
// There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound;
// we don't need to do anything.
} else if sized_def_id.is_some() {
// There was no `?Sized` or `!Sized` bound;
// There was no `?Sized`, `!Sized` or explicit `Sized` bound;
// add `Sized` if it's available.
bounds.push_sized(tcx, self_ty, span);
}
Expand Down
77 changes: 54 additions & 23 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _};
use rustc_type_ir::fold::TypeFoldable;

use std::cell::LazyCell;
use std::ops::ControlFlow;

pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
Expand Down Expand Up @@ -520,9 +521,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
}
}
DefKind::TyAlias => {
let pty_ty = tcx.type_of(def_id).instantiate_identity();
let generics = tcx.generics_of(def_id);
check_type_params_are_used(tcx, generics, pty_ty);
check_type_alias_type_params_are_used(tcx, def_id);
}
DefKind::ForeignMod => {
let it = tcx.hir().expect_item(def_id);
Expand Down Expand Up @@ -1269,28 +1268,51 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
}
}

pub(super) fn check_type_params_are_used<'tcx>(
tcx: TyCtxt<'tcx>,
generics: &ty::Generics,
ty: Ty<'tcx>,
) {
debug!("check_type_params_are_used(generics={:?}, ty={:?})", generics, ty);

assert_eq!(generics.parent, None);
fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
if tcx.type_alias_is_lazy(def_id) {
// Since we compute the variances for lazy type aliases and already reject bivariant
// parameters as unused, we can and should skip this check for lazy type aliases.
return;
}

let generics = tcx.generics_of(def_id);
if generics.own_counts().types == 0 {
return;
}

let mut params_used = BitSet::new_empty(generics.params.len());

let ty = tcx.type_of(def_id).instantiate_identity();
if ty.references_error() {
// If there is already another error, do not emit
// an error for not using a type parameter.
// If there is already another error, do not emit an error for not using a type parameter.
assert!(tcx.dcx().has_errors().is_some());
return;
}

// Lazily calculated because it is only needed in case of an error.
let bounded_params = LazyCell::new(|| {
tcx.explicit_predicates_of(def_id)
.predicates
.iter()
.filter_map(|(predicate, span)| {
let bounded_ty = match predicate.kind().skip_binder() {
ty::ClauseKind::Trait(pred) => pred.trait_ref.self_ty(),
ty::ClauseKind::TypeOutlives(pred) => pred.0,
_ => return None,
};
if let ty::Param(param) = bounded_ty.kind() {
Some((param.index, span))
} else {
None
}
})
// FIXME: This assumes that elaborated `Sized` bounds come first (which does hold at the
// time of writing). This is a bit fragile since we later use the span to detect elaborated
// `Sized` bounds. If they came last for example, this would break `Trait + /*elab*/Sized`
// since it would overwrite the span of the user-written bound. This could be fixed by
// folding the spans with `Span::to` which requires a bit of effort I think.
.collect::<FxHashMap<_, _>>()
});

let mut params_used = BitSet::new_empty(generics.params.len());
for leaf in ty.walk() {
if let GenericArgKind::Type(leaf_ty) = leaf.unpack()
&& let ty::Param(param) = leaf_ty.kind()
Expand All @@ -1305,15 +1327,24 @@ pub(super) fn check_type_params_are_used<'tcx>(
&& let ty::GenericParamDefKind::Type { .. } = param.kind
{
let span = tcx.def_span(param.def_id);
struct_span_code_err!(
tcx.dcx(),
let param_name = Ident::new(param.name, span);

// The corresponding predicates are post-`Sized`-elaboration. Therefore we
// * check for emptiness to detect lone user-written `?Sized` bounds
// * compare the param span to the pred span to detect lone user-written `Sized` bounds
let has_explicit_bounds = bounded_params.is_empty()
|| (*bounded_params).get(&param.index).is_some_and(|&&pred_sp| pred_sp != span);
let const_param_help = (!has_explicit_bounds).then_some(());

let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter {
span,
E0091,
"type parameter `{}` is unused",
param.name,
)
.with_span_label(span, "unused type parameter")
.emit();
param_name,
param_def_kind: tcx.def_descr(param.def_id),
help: errors::UnusedGenericParameterHelp::TyAlias { param_name },
const_param_help,
});
diag.code(E0091);
diag.emit();
}
}
}
Expand Down
64 changes: 33 additions & 31 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
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;
Expand All @@ -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;
Expand Down Expand Up @@ -1869,7 +1868,7 @@ fn check_variances_for_type_defn<'tcx>(
hir::ParamName::Error => {}
_ => {
let has_explicit_bounds = explicitly_bounded_params.contains(&parameter);
report_bivariance(tcx, hir_param, has_explicit_bounds);
report_bivariance(tcx, hir_param, has_explicit_bounds, item.kind);
}
}
}
Expand All @@ -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();

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> {
Expand Down Expand Up @@ -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 };
}
24 changes: 24 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1511,3 +1511,27 @@ pub struct NotSupportedDelegation<'a> {
#[label]
pub callee_span: Span,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_unused_generic_parameter)]
pub(crate) struct UnusedGenericParameter {
#[primary_span]
#[label]
pub span: Span,
pub param_name: Ident,
pub param_def_kind: &'static str,
#[subdiagnostic]
pub help: UnusedGenericParameterHelp,
#[help(hir_analysis_const_param_help)]
pub const_param_help: Option<()>,
}

#[derive(Subdiagnostic)]
pub(crate) enum UnusedGenericParameterHelp {
#[help(hir_analysis_unused_generic_parameter_adt_help)]
Adt { param_name: Ident, phantom_data: String },
#[help(hir_analysis_unused_generic_parameter_adt_no_phantom_data_help)]
AdtNoPhantomData { param_name: Ident },
#[help(hir_analysis_unused_generic_parameter_ty_alias_help)]
TyAlias { param_name: Ident },
}
2 changes: 2 additions & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr.kind
&& let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr)
&& self.can_coerce(recv_ty, expected)
&& let name = method.name.as_str()
&& (name.starts_with("to_") || name.starts_with("as_") || name == "into")
{
let span = if let Some(recv_span) = recv_expr.span.find_ancestor_inside(expr.span) {
expr.span.with_lo(recv_span.hi())
Expand Down
Loading
Loading