Skip to content

Commit 1096159

Browse files
committed
Auto merge of #142973 - compiler-errors:quick-coerce-2, r=<try>
[perf] Fast path for coercions of TY == TY
2 parents ad3b725 + 34842e5 commit 1096159

File tree

3 files changed

+41
-11
lines changed

3 files changed

+41
-11
lines changed

compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -780,8 +780,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
780780
} else {
781781
LaterUseKind::FakeLetRead
782782
}
783-
} else if self.was_captured_by_trait_object(borrow) {
784-
LaterUseKind::TraitCapture
783+
} else if let Some(unsize_span) = self.was_captured_by_trait_object(borrow) {
784+
// We drilled down the span to the actual location of the unsize, rather
785+
// than the location of the borrow.
786+
return (LaterUseKind::TraitCapture, unsize_span, None);
785787
} else if location.statement_index == block.statements.len() {
786788
if let TerminatorKind::Call { func, call_source: CallSource::Normal, .. } =
787789
&block.terminator().kind
@@ -818,7 +820,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
818820
/// Checks if a borrowed value was captured by a trait object. We do this by
819821
/// looking forward in the MIR from the reserve location and checking if we see
820822
/// an unsized cast to a trait object on our data.
821-
fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
823+
fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> Option<Span> {
822824
// Start at the reserve location, find the place that we want to see cast to a trait object.
823825
let location = borrow.reserve_location;
824826
let block = &self.body[location.block];
@@ -834,10 +836,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
834836
if let Some(local) = place.as_local() {
835837
local
836838
} else {
837-
return false;
839+
return None;
838840
}
839841
} else {
840-
return false;
842+
return None;
841843
};
842844

843845
debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
@@ -884,7 +886,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
884886
if from == target {
885887
debug!("was_captured_by_trait_object: ty={:?}", ty);
886888
// Check the type for a trait object.
887-
return match ty.kind() {
889+
let matches = match ty.kind() {
888890
// `&dyn Trait`
889891
ty::Ref(_, ty, _) if ty.is_trait() => true,
890892
// `Box<dyn Trait>`
@@ -897,11 +899,16 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
897899
// Anything else.
898900
_ => false,
899901
};
902+
if matches {
903+
return Some(stmt.source_info.span);
904+
} else {
905+
return None;
906+
}
900907
}
901908
}
902-
return false;
909+
return None;
903910
}
904-
_ => return false,
911+
_ => return None,
905912
}
906913
}
907914
_ => {}
@@ -925,7 +932,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
925932
);
926933
// Check if one of the arguments to this function is the target place.
927934
let found_target = args.iter().any(|arg| {
928-
if let Operand::Move(place) = arg.node {
935+
if let Operand::Move(place) | Operand::Copy(place) = arg.node {
929936
if let Some(potential) = place.as_local() {
930937
potential == target
931938
} else {
@@ -949,6 +956,6 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
949956
}
950957

951958
// We didn't find anything and ran out of locations to check.
952-
false
959+
None
953960
}
954961
}

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,30 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
205205
return self.coerce_from_inference_variable(a, b);
206206
}
207207

208+
// No coercion needed; types are identical. The only exception is when we have
209+
// a mutable reference, which needs a pair of reborrow adjustments inserted.
210+
if a == b {
211+
if let ty::Ref(_, pointee, ty::Mutability::Mut) = *a.kind() {
212+
return Ok(InferOk {
213+
value: (
214+
vec![
215+
Adjustment { kind: Adjust::Deref(None), target: pointee },
216+
Adjustment {
217+
kind: Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Mut {
218+
allow_two_phase_borrow: AllowTwoPhase::No,
219+
})),
220+
target: a,
221+
},
222+
],
223+
a,
224+
),
225+
obligations: Default::default(),
226+
});
227+
} else {
228+
return Ok(InferOk { value: (vec![], a), obligations: Default::default() });
229+
}
230+
}
231+
208232
// Consider coercing the subtype to a DST
209233
//
210234
// NOTE: this is wrapped in a `commit_if_ok` because it creates

tests/ui/span/regions-close-over-type-parameter-2.stderr

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ LL | let tmp0 = 3;
66
LL | let tmp1 = &tmp0;
77
| ^^^^^ borrowed value does not live long enough
88
LL | repeater3(tmp1)
9-
| --------------- borrow later captured here by trait object
109
LL | };
1110
| - `tmp0` dropped here while still borrowed
1211

0 commit comments

Comments
 (0)