Skip to content

Rollup of 7 pull requests #115755

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

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ Gareth Daniel Smith <garethdanielsmith@gmail.com> gareth <gareth@gareth-N56VM.(n
Gareth Daniel Smith <garethdanielsmith@gmail.com> Gareth Smith <garethdanielsmith@gmail.com>
Gauri Kholkar <f2013002@goa.bits-pilani.ac.in>
Georges Dubus <georges.dubus@gmail.com> <georges.dubus@compiletoi.net>
Ghost <ghost> <jonasschievink@gmail.com>
Ghost <ghost> <jonas.schievink@ferrous-systems.com>
Ghost <ghost> <jonas@schievink.net>
Ghost <ghost> <Jonas.Schievink@sony.com>
Giles Cope <gilescope@gmail.com>
Glen De Cauwsemaecker <decauwsemaecker.glen@gmail.com>
Graham Fawcett <graham.fawcett@gmail.com> Graham Fawcett <fawcett@uwindsor.ca>
Expand Down
126 changes: 119 additions & 7 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use hir::ExprKind;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::intravisit::Visitor;
use rustc_hir::Node;
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt};
use rustc_middle::{
hir::place::PlaceBase,
mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location},
Expand Down Expand Up @@ -370,12 +371,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
err.span_label(span, format!("cannot {act}"));
}
if suggest {
err.span_suggestion_verbose(
local_decl.source_info.span.shrink_to_lo(),
"consider changing this to be mutable",
"mut ",
Applicability::MachineApplicable,
);
self.construct_mut_suggestion_for_local_binding_patterns(&mut err, local);
let tcx = self.infcx.tcx;
if let ty::Closure(id, _) = *the_place_err.ty(self.body, tcx).ty.kind() {
self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err);
Expand Down Expand Up @@ -491,6 +487,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
),
);

self.suggest_using_iter_mut(&mut err);
self.suggest_make_local_mut(&mut err, local, name);
}
_ => {
Expand Down Expand Up @@ -710,6 +707,83 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
)
}

fn construct_mut_suggestion_for_local_binding_patterns(
&self,
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
local: Local,
) {
let local_decl = &self.body.local_decls[local];
debug!("local_decl: {:?}", local_decl);
let pat_span = match *local_decl.local_info() {
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
opt_ty_info: _,
opt_match_place: _,
pat_span,
})) => pat_span,
_ => local_decl.source_info.span,
};

struct BindingFinder {
span: Span,
hir_id: Option<hir::HirId>,
}

impl<'tcx> Visitor<'tcx> for BindingFinder {
fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
if let hir::StmtKind::Local(local) = s.kind {
if local.pat.span == self.span {
self.hir_id = Some(local.hir_id);
}
}
hir::intravisit::walk_stmt(self, s);
}
}

let hir_map = self.infcx.tcx.hir();
let def_id = self.body.source.def_id();
let hir_id = if let Some(local_def_id) = def_id.as_local()
&& let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id)
{
let body = hir_map.body(body_id);
let mut v = BindingFinder {
span: pat_span,
hir_id: None,
};
v.visit_body(body);
v.hir_id
} else {
None
};

// With ref-binding patterns, the mutability suggestion has to apply to
// the binding, not the reference (which would be a type error):
//
// `let &b = a;` -> `let &(mut b) = a;`
if let Some(hir_id) = hir_id
&& let Some(hir::Node::Local(hir::Local {
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
..
})) = hir_map.find(hir_id)
&& let Ok(name) = self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
{
err.span_suggestion(
pat_span,
"consider changing this to be mutable",
format!("&(mut {name})"),
Applicability::MachineApplicable,
);
return;
}

err.span_suggestion_verbose(
local_decl.source_info.span.shrink_to_lo(),
"consider changing this to be mutable",
"mut ",
Applicability::MachineApplicable,
);
}

// point to span of upvar making closure call require mutable borrow
fn show_mutating_upvar(
&self,
Expand Down Expand Up @@ -953,6 +1027,44 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}

fn suggest_using_iter_mut(&self, err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>) {
let source = self.body.source;
let hir = self.infcx.tcx.hir();
if let InstanceDef::Item(def_id) = source.instance
&& let Some(Node::Expr(hir::Expr { hir_id, kind, ..})) = hir.get_if_local(def_id)
&& let ExprKind::Closure(closure) = kind && closure.movability == None
&& let Some(Node::Expr(expr)) = hir.find_parent(*hir_id) {
let mut cur_expr = expr;
while let ExprKind::MethodCall(path_segment, recv, _, _) = cur_expr.kind {
if path_segment.ident.name == sym::iter {
// check `_ty` has `iter_mut` method
let res = self
.infcx
.tcx
.typeck(path_segment.hir_id.owner.def_id)
.type_dependent_def_id(cur_expr.hir_id)
.and_then(|def_id| self.infcx.tcx.impl_of_method(def_id))
.map(|def_id| self.infcx.tcx.associated_items(def_id))
.map(|assoc_items| {
assoc_items.filter_by_name_unhygienic(sym::iter_mut).peekable()
});

if let Some(mut res) = res && res.peek().is_some() {
err.span_suggestion_verbose(
path_segment.ident.span,
"you may want to use `iter_mut` here",
"iter_mut",
Applicability::MaybeIncorrect,
);
}
break;
} else {
cur_expr = recv;
}
}
}
}

fn suggest_make_local_mut(
&self,
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_error_codes/src/error_codes/E0401.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Inner items do not inherit type or const parameters from the functions
Inner items do not inherit the generic parameters from the items
they are embedded in.

Erroneous code example:
Expand Down Expand Up @@ -32,8 +32,8 @@ fn foo<T>(x: T) {
}
```

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

There are a couple of solutions for this.

Expand Down
25 changes: 12 additions & 13 deletions compiler/rustc_lint/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use rustc_data_structures::sync::join;
use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
use rustc_hir::intravisit as hir_visit;
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::LintPass;
Expand Down Expand Up @@ -61,6 +60,9 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
self.context.last_node_with_lint_attrs = id;
debug!("late context: enter_attrs({:?})", attrs);
lint_callback!(self, enter_lint_attrs, attrs);
for attr in attrs {
lint_callback!(self, check_attribute, attr);
}
f(self);
debug!("late context: exit_attrs({:?})", attrs);
lint_callback!(self, exit_lint_attrs, attrs);
Expand Down Expand Up @@ -377,20 +379,18 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(

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

// There is no module lint that will have the crate itself as an item, so check it here.
if hir_id == hir::CRATE_HIR_ID {
lint_callback!(cx, check_crate,);
}
cx.with_lint_attrs(hir_id, |cx| {
// There is no module lint that will have the crate itself as an item, so check it here.
if hir_id == hir::CRATE_HIR_ID {
lint_callback!(cx, check_crate,);
}

cx.process_mod(module, hir_id);
cx.process_mod(module, hir_id);

// Visit the crate attributes
if hir_id == hir::CRATE_HIR_ID {
for attr in tcx.hir().attrs(hir::CRATE_HIR_ID).iter() {
cx.visit_attribute(attr)
if hir_id == hir::CRATE_HIR_ID {
lint_callback!(cx, check_crate_post,);
}
lint_callback!(cx, check_crate_post,);
}
});
}

fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) {
Expand Down Expand Up @@ -431,7 +431,6 @@ fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
// item), warn for it here.
lint_callback!(cx, check_crate,);
tcx.hir().walk_toplevel_module(cx);
tcx.hir().walk_attributes(cx);
lint_callback!(cx, check_crate_post,);
})
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/trait_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ pub struct TraitImpls {
}

impl TraitImpls {
pub fn is_empty(&self) -> bool {
self.blanket_impls.is_empty() && self.non_blanket_impls.is_empty()
}

pub fn blanket_impls(&self) -> &[DefId] {
self.blanket_impls.as_slice()
}
Expand Down
29 changes: 13 additions & 16 deletions compiler/rustc_resolve/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ resolve_cannot_find_ident_in_this_scope =
resolve_cannot_glob_import_possible_crates =
cannot glob-import all possible crates

resolve_cannot_use_self_type_here =
can't use `Self` here

resolve_change_import_binding =
you can use `as` to change the binding name of the import

Expand All @@ -90,9 +87,6 @@ resolve_const_not_member_of_trait =
const `{$const_}` is not a member of trait `{$trait_}`
.label = not a member of trait `{$trait_}`

resolve_const_param_from_outer_fn =
const parameter from outer function

resolve_const_param_in_enum_discriminant =
const parameters may not be used in enum discriminant values

Expand All @@ -119,10 +113,19 @@ resolve_forward_declared_generic_param =
generic parameters with a default cannot use forward declared identifiers
.label = defaulted generic parameters cannot be forward declared

resolve_generic_params_from_outer_function =
can't use generic parameters from outer function
.label = use of generic parameter from outer function
.suggestion = try using a local generic parameter instead
resolve_generic_params_from_outer_item =
can't use generic parameters from outer item
.label = use of generic parameter from outer item
.refer_to_type_directly = refer to the type directly here instead
.suggestion = try introducing a local generic parameter here

resolve_generic_params_from_outer_item_const_param = const parameter from outer item

resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl`

resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here

resolve_generic_params_from_outer_item_ty_param = type parameter from outer item

resolve_glob_import_doesnt_reexport =
glob import doesn't reexport anything because no candidate is public enough
Expand Down Expand Up @@ -277,9 +280,6 @@ resolve_type_not_member_of_trait =
type `{$type_}` is not a member of trait `{$trait_}`
.label = not a member of trait `{$trait_}`

resolve_type_param_from_outer_fn =
type parameter from outer function

resolve_type_param_in_enum_discriminant =
type parameters may not be used in enum discriminant values

Expand Down Expand Up @@ -315,9 +315,6 @@ resolve_unreachable_label_suggestion_use_similarly_named =
resolve_unreachable_label_with_similar_name_exists =
a label with a similar name exists but is unreachable

resolve_use_a_type_here_instead =
use a type here instead

resolve_variable_bound_with_different_mode =
variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
.label = bound in different ways
Expand Down
Loading