Skip to content

Commit

Permalink
Auto merge of rust-lang#104809 - matthiaskrgr:rollup-8abjdwh, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 9 pull requests

Successful merges:

 - rust-lang#103908 (Suggest `.clone()` or `ref binding` on E0382)
 - rust-lang#104517 (Throw error on failure in loading llvm-plugin)
 - rust-lang#104594 (Properly handle `Pin<&mut dyn* Trait>` receiver in codegen)
 - rust-lang#104742 (Make `deref_into_dyn_supertrait` lint the impl and not the usage)
 - rust-lang#104753 (Pass `InferCtxt` to `DropRangeVisitor` so we can resolve vars)
 - rust-lang#104771 (Add regression test for issue rust-lang#99938)
 - rust-lang#104772 (Small accessibility improvements)
 - rust-lang#104775 (Use ObligationCtxt::normalize)
 - rust-lang#104778 (:arrow_up: rust-analyzer)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Nov 24, 2022
2 parents 341d8b8 + 1afbd6e commit 1dda298
Show file tree
Hide file tree
Showing 253 changed files with 4,084 additions and 1,171 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1376,7 +1376,7 @@ pub enum ExprKind {
/// Conditionless loop (can be exited with `break`, `continue`, or `return`).
///
/// `'label: loop { block }`
Loop(P<Block>, Option<Label>),
Loop(P<Block>, Option<Label>, Span),
/// A `match` block.
Match(P<Expr>, Vec<Arm>),
/// A closure (e.g., `move |a, b, c| a + b + c`).
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1355,9 +1355,10 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_block(body);
visit_opt(label, |label| vis.visit_label(label));
}
ExprKind::Loop(body, label) => {
ExprKind::Loop(body, label, span) => {
vis.visit_block(body);
visit_opt(label, |label| vis.visit_label(label));
vis.visit_span(span);
}
ExprKind::Match(expr, arms) => {
vis.visit_expr(expr);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(subexpression);
visitor.visit_block(block);
}
ExprKind::Loop(block, opt_label) => {
ExprKind::Loop(block, opt_label, _) => {
walk_list!(visitor, visit_label, opt_label);
visitor.visit_block(block);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
let span = this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None);
this.lower_expr_while_in_loop_scope(span, cond, body, *opt_label)
}),
ExprKind::Loop(body, opt_label) => self.with_loop_scope(e.id, |this| {
ExprKind::Loop(body, opt_label, span) => self.with_loop_scope(e.id, |this| {
hir::ExprKind::Loop(
this.lower_block(body, false),
this.lower_label(*opt_label),
hir::LoopSource::Loop,
DUMMY_SP,
this.lower_span(*span),
)
}),
ExprKind::TryBlock(body) => self.lower_expr_try_block(body),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ impl<'a> State<'a> {
self.space();
self.print_block_with_attrs(blk, attrs);
}
ast::ExprKind::Loop(ref blk, opt_label) => {
ast::ExprKind::Loop(ref blk, opt_label, _) => {
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.word_space(":");
Expand Down
224 changes: 194 additions & 30 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}

self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
let closure = self.add_moved_or_invoked_closure_note(location, used_place, &mut err);

let mut is_loop_move = false;
let mut in_pattern = false;
let mut seen_spans = FxHashSet::default();

for move_site in &move_site_vec {
let move_out = self.move_data.moves[(*move_site).moi];
Expand All @@ -191,37 +192,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
is_loop_move = true;
}

self.explain_captures(
&mut err,
span,
move_span,
move_spans,
*moved_place,
partially_str,
loop_message,
move_msg,
is_loop_move,
maybe_reinitialized_locations.is_empty(),
);

if let (UseSpans::PatUse(span), []) =
(move_spans, &maybe_reinitialized_locations[..])
{
if maybe_reinitialized_locations.is_empty() {
err.span_suggestion_verbose(
span.shrink_to_lo(),
&format!(
"borrow this field in the pattern to avoid moving {}",
self.describe_place(moved_place.as_ref())
.map(|n| format!("`{}`", n))
.unwrap_or_else(|| "the value".to_string())
),
"ref ",
Applicability::MachineApplicable,
);
in_pattern = true;
if !seen_spans.contains(&move_span) {
if !closure {
self.suggest_ref_or_clone(mpi, move_span, &mut err, &mut in_pattern);
}

self.explain_captures(
&mut err,
span,
move_span,
move_spans,
*moved_place,
partially_str,
loop_message,
move_msg,
is_loop_move,
maybe_reinitialized_locations.is_empty(),
);
}
seen_spans.insert(move_span);
}

use_spans.var_path_only_subdiag(&mut err, desired_action);
Expand Down Expand Up @@ -317,6 +306,160 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}

fn suggest_ref_or_clone(
&mut self,
mpi: MovePathIndex,
move_span: Span,
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
in_pattern: &mut bool,
) {
struct ExpressionFinder<'hir> {
expr_span: Span,
expr: Option<&'hir hir::Expr<'hir>>,
pat: Option<&'hir hir::Pat<'hir>>,
parent_pat: Option<&'hir hir::Pat<'hir>>,
}
impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
if e.span == self.expr_span {
self.expr = Some(e);
}
hir::intravisit::walk_expr(self, e);
}
fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) {
if p.span == self.expr_span {
self.pat = Some(p);
}
if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, i, sub) = p.kind {
if i.span == self.expr_span || p.span == self.expr_span {
self.pat = Some(p);
}
// Check if we are in a situation of `ident @ ident` where we want to suggest
// `ref ident @ ref ident` or `ref ident @ Struct { ref ident }`.
if let Some(subpat) = sub && self.pat.is_none() {
self.visit_pat(subpat);
if self.pat.is_some() {
self.parent_pat = Some(p);
}
return;
}
}
hir::intravisit::walk_pat(self, p);
}
}
let hir = self.infcx.tcx.hir();
if let Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn(_, _, body_id),
..
})) = hir.find(hir.local_def_id_to_hir_id(self.mir_def_id()))
&& let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id)
{
let place = &self.move_data.move_paths[mpi].place;
let span = place.as_local()
.map(|local| self.body.local_decls[local].source_info.span);
let mut finder = ExpressionFinder {
expr_span: move_span,
expr: None,
pat: None,
parent_pat: None,
};
finder.visit_expr(expr);
if let Some(span) = span && let Some(expr) = finder.expr {
for (_, expr) in hir.parent_iter(expr.hir_id) {
if let hir::Node::Expr(expr) = expr {
if expr.span.contains(span) {
// If the let binding occurs within the same loop, then that
// loop isn't relevant, like in the following, the outermost `loop`
// doesn't play into `x` being moved.
// ```
// loop {
// let x = String::new();
// loop {
// foo(x);
// }
// }
// ```
break;
}
if let hir::ExprKind::Loop(.., loop_span) = expr.kind {
err.span_label(loop_span, "inside of this loop");
}
}
}
let typeck = self.infcx.tcx.typeck(self.mir_def_id());
let hir_id = hir.get_parent_node(expr.hir_id);
if let Some(parent) = hir.find(hir_id) {
let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
&& let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id)
{
(def_id.as_local(), args, 1)
} else if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::Call(call, args) = parent_expr.kind
&& let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
{
(def_id.as_local(), args, 0)
} else {
(None, &[][..], 0)
};
if let Some(def_id) = def_id
&& let Some(node) = hir.find(hir.local_def_id_to_hir_id(def_id))
&& let Some(fn_sig) = node.fn_sig()
&& let Some(ident) = node.ident()
&& let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
&& let Some(arg) = fn_sig.decl.inputs.get(pos + offset)
{
let mut span: MultiSpan = arg.span.into();
span.push_span_label(
arg.span,
"this parameter takes ownership of the value".to_string(),
);
let descr = match node.fn_kind() {
Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function",
Some(hir::intravisit::FnKind::Method(..)) => "method",
Some(hir::intravisit::FnKind::Closure) => "closure",
};
span.push_span_label(
ident.span,
format!("in this {descr}"),
);
err.span_note(
span,
format!(
"consider changing this parameter type in {descr} `{ident}` to \
borrow instead if owning the value isn't necessary",
),
);
}
let place = &self.move_data.move_paths[mpi].place;
let ty = place.ty(self.body, self.infcx.tcx).ty;
if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::Call(call_expr, _) = parent_expr.kind
&& let hir::ExprKind::Path(
hir::QPath::LangItem(LangItem::IntoIterIntoIter, _, _)
) = call_expr.kind
{
// Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
} else {
self.suggest_cloning(err, ty, move_span);
}
}
}
if let Some(pat) = finder.pat {
*in_pattern = true;
let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())];
if let Some(pat) = finder.parent_pat {
sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string()));
}
err.multipart_suggestion_verbose(
"borrow this binding in the pattern to avoid moving the value",
sugg,
Applicability::MachineApplicable,
);
}
}
}

fn report_use_of_uninitialized(
&self,
mpi: MovePathIndex,
Expand Down Expand Up @@ -590,6 +733,27 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
true
}

fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
let tcx = self.infcx.tcx;
// Try to find predicates on *generic params* that would allow copying `ty`
let infcx = tcx.infer_ctxt().build();
if infcx
.type_implements_trait(
tcx.lang_items().clone_trait().unwrap(),
[tcx.erase_regions(ty)],
self.param_env,
)
.must_apply_modulo_regions()
{
err.span_suggestion_verbose(
span.shrink_to_hi(),
"consider cloning the value if the performance cost is acceptable",
".clone()".to_string(),
Applicability::MachineApplicable,
);
}
}

fn suggest_adding_copy_bounds(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
let tcx = self.infcx.tcx;
let generics = tcx.generics_of(self.mir_def_id());
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
location: Location,
place: PlaceRef<'tcx>,
diag: &mut Diagnostic,
) {
) -> bool {
debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
let mut target = place.local_or_deref_local();
for stmt in &self.body[location.block].statements[location.statement_index..] {
Expand Down Expand Up @@ -106,7 +106,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
{
place.local_or_deref_local().unwrap()
}
_ => return,
_ => return false,
};

debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
Expand All @@ -125,7 +125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
),
);
return;
return true;
}
}
}
Expand All @@ -149,9 +149,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
),
);
return true;
}
}
}
false
}

/// End-user visible description of `place` if one can be found.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/assert/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::InlineAsm(_)
| ExprKind::Let(_, _, _)
| ExprKind::Lit(_)
| ExprKind::Loop(_, _)
| ExprKind::Loop(_, _, _)
| ExprKind::MacCall(_)
| ExprKind::Match(_, _)
| ExprKind::Path(_, _)
Expand Down
Loading

0 comments on commit 1dda298

Please sign in to comment.