Skip to content

Commit fbaae6f

Browse files
committed
Auto merge of rust-lang#115755 - Dylan-DPC:rollup-4sz8hpu, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - rust-lang#115308 (suggest iter_mut() where trying to modify elements from .iter()) - rust-lang#115595 (Fix incorrect mutable suggestion information for binding in ref pattern like: `let &b = a;` ) - rust-lang#115702 (Update mailmap) - rust-lang#115708 (fix homogeneous_aggregate not ignoring some ZST) - rust-lang#115739 (Call `LateLintPass::check_attribute` from `with_lint_attrs`) - rust-lang#115743 (Point out if a local trait has no implementations) - rust-lang#115744 (Improve diagnostic for generic params from outer items (E0401)) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 68c2f5b + 0fe3b15 commit fbaae6f

File tree

116 files changed

+1184
-227
lines changed

Some content is hidden

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

116 files changed

+1184
-227
lines changed

.mailmap

+4
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ Gareth Daniel Smith <garethdanielsmith@gmail.com> gareth <gareth@gareth-N56VM.(n
205205
Gareth Daniel Smith <garethdanielsmith@gmail.com> Gareth Smith <garethdanielsmith@gmail.com>
206206
Gauri Kholkar <f2013002@goa.bits-pilani.ac.in>
207207
Georges Dubus <georges.dubus@gmail.com> <georges.dubus@compiletoi.net>
208+
Ghost <ghost> <jonasschievink@gmail.com>
209+
Ghost <ghost> <jonas.schievink@ferrous-systems.com>
210+
Ghost <ghost> <jonas@schievink.net>
211+
Ghost <ghost> <Jonas.Schievink@sony.com>
208212
Giles Cope <gilescope@gmail.com>
209213
Glen De Cauwsemaecker <decauwsemaecker.glen@gmail.com>
210214
Graham Fawcett <graham.fawcett@gmail.com> Graham Fawcett <fawcett@uwindsor.ca>

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

+78-6
Original file line numberDiff line numberDiff line change
@@ -371,12 +371,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
371371
err.span_label(span, format!("cannot {act}"));
372372
}
373373
if suggest {
374-
err.span_suggestion_verbose(
375-
local_decl.source_info.span.shrink_to_lo(),
376-
"consider changing this to be mutable",
377-
"mut ",
378-
Applicability::MachineApplicable,
379-
);
374+
self.construct_mut_suggestion_for_local_binding_patterns(&mut err, local);
380375
let tcx = self.infcx.tcx;
381376
if let ty::Closure(id, _) = *the_place_err.ty(self.body, tcx).ty.kind() {
382377
self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err);
@@ -712,6 +707,83 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
712707
)
713708
}
714709

710+
fn construct_mut_suggestion_for_local_binding_patterns(
711+
&self,
712+
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
713+
local: Local,
714+
) {
715+
let local_decl = &self.body.local_decls[local];
716+
debug!("local_decl: {:?}", local_decl);
717+
let pat_span = match *local_decl.local_info() {
718+
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
719+
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
720+
opt_ty_info: _,
721+
opt_match_place: _,
722+
pat_span,
723+
})) => pat_span,
724+
_ => local_decl.source_info.span,
725+
};
726+
727+
struct BindingFinder {
728+
span: Span,
729+
hir_id: Option<hir::HirId>,
730+
}
731+
732+
impl<'tcx> Visitor<'tcx> for BindingFinder {
733+
fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
734+
if let hir::StmtKind::Local(local) = s.kind {
735+
if local.pat.span == self.span {
736+
self.hir_id = Some(local.hir_id);
737+
}
738+
}
739+
hir::intravisit::walk_stmt(self, s);
740+
}
741+
}
742+
743+
let hir_map = self.infcx.tcx.hir();
744+
let def_id = self.body.source.def_id();
745+
let hir_id = if let Some(local_def_id) = def_id.as_local()
746+
&& let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id)
747+
{
748+
let body = hir_map.body(body_id);
749+
let mut v = BindingFinder {
750+
span: pat_span,
751+
hir_id: None,
752+
};
753+
v.visit_body(body);
754+
v.hir_id
755+
} else {
756+
None
757+
};
758+
759+
// With ref-binding patterns, the mutability suggestion has to apply to
760+
// the binding, not the reference (which would be a type error):
761+
//
762+
// `let &b = a;` -> `let &(mut b) = a;`
763+
if let Some(hir_id) = hir_id
764+
&& let Some(hir::Node::Local(hir::Local {
765+
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
766+
..
767+
})) = hir_map.find(hir_id)
768+
&& let Ok(name) = self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
769+
{
770+
err.span_suggestion(
771+
pat_span,
772+
"consider changing this to be mutable",
773+
format!("&(mut {name})"),
774+
Applicability::MachineApplicable,
775+
);
776+
return;
777+
}
778+
779+
err.span_suggestion_verbose(
780+
local_decl.source_info.span.shrink_to_lo(),
781+
"consider changing this to be mutable",
782+
"mut ",
783+
Applicability::MachineApplicable,
784+
);
785+
}
786+
715787
// point to span of upvar making closure call require mutable borrow
716788
fn show_mutating_upvar(
717789
&self,

compiler/rustc_error_codes/src/error_codes/E0401.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Inner items do not inherit type or const parameters from the functions
1+
Inner items do not inherit the generic parameters from the items
22
they are embedded in.
33

44
Erroneous code example:
@@ -32,8 +32,8 @@ fn foo<T>(x: T) {
3232
}
3333
```
3434

35-
Items inside functions are basically just like top-level items, except
36-
that they can only be used from the function they are in.
35+
Items nested inside other items are basically just like top-level items, except
36+
that they can only be used from the item they are in.
3737

3838
There are a couple of solutions for this.
3939

compiler/rustc_lint/src/late.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use rustc_data_structures::sync::join;
2121
use rustc_hir as hir;
2222
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
2323
use rustc_hir::intravisit as hir_visit;
24-
use rustc_hir::intravisit::Visitor;
2524
use rustc_middle::hir::nested_filter;
2625
use rustc_middle::ty::{self, TyCtxt};
2726
use rustc_session::lint::LintPass;
@@ -61,6 +60,9 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
6160
self.context.last_node_with_lint_attrs = id;
6261
debug!("late context: enter_attrs({:?})", attrs);
6362
lint_callback!(self, enter_lint_attrs, attrs);
63+
for attr in attrs {
64+
lint_callback!(self, check_attribute, attr);
65+
}
6466
f(self);
6567
debug!("late context: exit_attrs({:?})", attrs);
6668
lint_callback!(self, exit_lint_attrs, attrs);
@@ -377,20 +379,18 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(
377379

378380
let (module, _span, hir_id) = tcx.hir().get_module(module_def_id);
379381

380-
// There is no module lint that will have the crate itself as an item, so check it here.
381-
if hir_id == hir::CRATE_HIR_ID {
382-
lint_callback!(cx, check_crate,);
383-
}
382+
cx.with_lint_attrs(hir_id, |cx| {
383+
// There is no module lint that will have the crate itself as an item, so check it here.
384+
if hir_id == hir::CRATE_HIR_ID {
385+
lint_callback!(cx, check_crate,);
386+
}
384387

385-
cx.process_mod(module, hir_id);
388+
cx.process_mod(module, hir_id);
386389

387-
// Visit the crate attributes
388-
if hir_id == hir::CRATE_HIR_ID {
389-
for attr in tcx.hir().attrs(hir::CRATE_HIR_ID).iter() {
390-
cx.visit_attribute(attr)
390+
if hir_id == hir::CRATE_HIR_ID {
391+
lint_callback!(cx, check_crate_post,);
391392
}
392-
lint_callback!(cx, check_crate_post,);
393-
}
393+
});
394394
}
395395

396396
fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) {
@@ -431,7 +431,6 @@ fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
431431
// item), warn for it here.
432432
lint_callback!(cx, check_crate,);
433433
tcx.hir().walk_toplevel_module(cx);
434-
tcx.hir().walk_attributes(cx);
435434
lint_callback!(cx, check_crate_post,);
436435
})
437436
}

compiler/rustc_middle/src/ty/trait_def.rs

+4
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ pub struct TraitImpls {
9090
}
9191

9292
impl TraitImpls {
93+
pub fn is_empty(&self) -> bool {
94+
self.blanket_impls.is_empty() && self.non_blanket_impls.is_empty()
95+
}
96+
9397
pub fn blanket_impls(&self) -> &[DefId] {
9498
self.blanket_impls.as_slice()
9599
}

compiler/rustc_resolve/messages.ftl

+13-16
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,6 @@ resolve_cannot_find_ident_in_this_scope =
6868
resolve_cannot_glob_import_possible_crates =
6969
cannot glob-import all possible crates
7070
71-
resolve_cannot_use_self_type_here =
72-
can't use `Self` here
73-
7471
resolve_change_import_binding =
7572
you can use `as` to change the binding name of the import
7673
@@ -90,9 +87,6 @@ resolve_const_not_member_of_trait =
9087
const `{$const_}` is not a member of trait `{$trait_}`
9188
.label = not a member of trait `{$trait_}`
9289
93-
resolve_const_param_from_outer_fn =
94-
const parameter from outer function
95-
9690
resolve_const_param_in_enum_discriminant =
9791
const parameters may not be used in enum discriminant values
9892
@@ -119,10 +113,19 @@ resolve_forward_declared_generic_param =
119113
generic parameters with a default cannot use forward declared identifiers
120114
.label = defaulted generic parameters cannot be forward declared
121115
122-
resolve_generic_params_from_outer_function =
123-
can't use generic parameters from outer function
124-
.label = use of generic parameter from outer function
125-
.suggestion = try using a local generic parameter instead
116+
resolve_generic_params_from_outer_item =
117+
can't use generic parameters from outer item
118+
.label = use of generic parameter from outer item
119+
.refer_to_type_directly = refer to the type directly here instead
120+
.suggestion = try introducing a local generic parameter here
121+
122+
resolve_generic_params_from_outer_item_const_param = const parameter from outer item
123+
124+
resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl`
125+
126+
resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here
127+
128+
resolve_generic_params_from_outer_item_ty_param = type parameter from outer item
126129
127130
resolve_glob_import_doesnt_reexport =
128131
glob import doesn't reexport anything because no candidate is public enough
@@ -277,9 +280,6 @@ resolve_type_not_member_of_trait =
277280
type `{$type_}` is not a member of trait `{$trait_}`
278281
.label = not a member of trait `{$trait_}`
279282
280-
resolve_type_param_from_outer_fn =
281-
type parameter from outer function
282-
283283
resolve_type_param_in_enum_discriminant =
284284
type parameters may not be used in enum discriminant values
285285
@@ -315,9 +315,6 @@ resolve_unreachable_label_suggestion_use_similarly_named =
315315
resolve_unreachable_label_with_similar_name_exists =
316316
a label with a similar name exists but is unreachable
317317
318-
resolve_use_a_type_here_instead =
319-
use a type here instead
320-
321318
resolve_variable_bound_with_different_mode =
322319
variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
323320
.label = bound in different ways

compiler/rustc_resolve/src/diagnostics.rs

+20-27
Original file line numberDiff line numberDiff line change
@@ -553,53 +553,47 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
553553
resolution_error: ResolutionError<'a>,
554554
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
555555
match resolution_error {
556-
ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => {
557-
let mut err = struct_span_err!(
558-
self.tcx.sess,
556+
ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params) => {
557+
use errs::GenericParamsFromOuterItemLabel as Label;
558+
let mut err = errs::GenericParamsFromOuterItem {
559559
span,
560-
E0401,
561-
"can't use generic parameters from outer function",
562-
);
563-
err.span_label(span, "use of generic parameter from outer function");
560+
label: None,
561+
refer_to_type_directly: None,
562+
sugg: None,
563+
};
564564

565565
let sm = self.tcx.sess.source_map();
566566
let def_id = match outer_res {
567567
Res::SelfTyParam { .. } => {
568-
err.span_label(span, "can't use `Self` here");
569-
return err;
568+
err.label = Some(Label::SelfTyParam(span));
569+
return self.tcx.sess.create_err(err);
570570
}
571571
Res::SelfTyAlias { alias_to: def_id, .. } => {
572-
err.span_label(
573-
reduce_impl_span_to_impl_keyword(sm, self.def_span(def_id)),
574-
"`Self` type implicitly declared here, by this `impl`",
575-
);
576-
err.span_label(span, "use a type here instead");
577-
return err;
572+
err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword(
573+
sm,
574+
self.def_span(def_id),
575+
)));
576+
err.refer_to_type_directly = Some(span);
577+
return self.tcx.sess.create_err(err);
578578
}
579579
Res::Def(DefKind::TyParam, def_id) => {
580-
err.span_label(self.def_span(def_id), "type parameter from outer function");
580+
err.label = Some(Label::TyParam(self.def_span(def_id)));
581581
def_id
582582
}
583583
Res::Def(DefKind::ConstParam, def_id) => {
584-
err.span_label(
585-
self.def_span(def_id),
586-
"const parameter from outer function",
587-
);
584+
err.label = Some(Label::ConstParam(self.def_span(def_id)));
588585
def_id
589586
}
590587
_ => {
591588
bug!(
592-
"GenericParamsFromOuterFunction should only be used with \
589+
"GenericParamsFromOuterItem should only be used with \
593590
Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
594591
DefKind::ConstParam"
595592
);
596593
}
597594
};
598595

599596
if let HasGenericParams::Yes(span) = has_generic_params {
600-
// Try to retrieve the span of the function signature and generate a new
601-
// message with a local type or const parameter.
602-
let sugg_msg = "try using a local generic parameter instead";
603597
let name = self.tcx.item_name(def_id);
604598
let (span, snippet) = if span.is_empty() {
605599
let snippet = format!("<{name}>");
@@ -609,11 +603,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
609603
let snippet = format!("{name}, ");
610604
(span, snippet)
611605
};
612-
// Suggest the modification to the user
613-
err.span_suggestion(span, sugg_msg, snippet, Applicability::MaybeIncorrect);
606+
err.sugg = Some(errs::GenericParamsFromOuterItemSugg { span, snippet });
614607
}
615608

616-
err
609+
self.tcx.sess.create_err(err)
617610
}
618611
ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self
619612
.tcx

compiler/rustc_resolve/src/errors.rs

+34
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,40 @@ pub(crate) struct CrateRootNamesMustBeNamedExplicitly(#[primary_span] pub(crate)
3232
#[diag(resolve_crate_root_imports_must_be_named_explicitly)]
3333
pub(crate) struct ResolutionError(#[primary_span] pub(crate) Span);
3434

35+
#[derive(Diagnostic)]
36+
#[diag(resolve_generic_params_from_outer_item, code = "E0401")]
37+
pub(crate) struct GenericParamsFromOuterItem {
38+
#[primary_span]
39+
#[label]
40+
pub(crate) span: Span,
41+
#[subdiagnostic]
42+
pub(crate) label: Option<GenericParamsFromOuterItemLabel>,
43+
#[label(resolve_refer_to_type_directly)]
44+
pub(crate) refer_to_type_directly: Option<Span>,
45+
#[subdiagnostic]
46+
pub(crate) sugg: Option<GenericParamsFromOuterItemSugg>,
47+
}
48+
49+
#[derive(Subdiagnostic)]
50+
pub(crate) enum GenericParamsFromOuterItemLabel {
51+
#[label(resolve_generic_params_from_outer_item_self_ty_param)]
52+
SelfTyParam(#[primary_span] Span),
53+
#[label(resolve_generic_params_from_outer_item_self_ty_alias)]
54+
SelfTyAlias(#[primary_span] Span),
55+
#[label(resolve_generic_params_from_outer_item_ty_param)]
56+
TyParam(#[primary_span] Span),
57+
#[label(resolve_generic_params_from_outer_item_const_param)]
58+
ConstParam(#[primary_span] Span),
59+
}
60+
61+
#[derive(Subdiagnostic)]
62+
#[suggestion(resolve_suggestion, code = "{snippet}", applicability = "maybe-incorrect")]
63+
pub(crate) struct GenericParamsFromOuterItemSugg {
64+
#[primary_span]
65+
pub(crate) span: Span,
66+
pub(crate) snippet: String,
67+
}
68+
3569
#[derive(Diagnostic)]
3670
#[diag(resolve_name_is_already_used_as_generic_parameter, code = "E0403")]
3771
pub(crate) struct NameAlreadyUsedInParameterList {

0 commit comments

Comments
 (0)