Skip to content

Commit 5bbf4be

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

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
@@ -781,8 +781,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
781781
} else {
782782
LaterUseKind::FakeLetRead
783783
}
784-
} else if self.was_captured_by_trait_object(borrow) {
785-
LaterUseKind::TraitCapture
784+
} else if let Some(unsize_span) = self.was_captured_by_trait_object(borrow) {
785+
// We drilled down the span to the actual location of the unsize, rather
786+
// than the location of the borrow.
787+
return (LaterUseKind::TraitCapture, unsize_span, None);
786788
} else if location.statement_index == block.statements.len() {
787789
if let TerminatorKind::Call { func, call_source: CallSource::Normal, .. } =
788790
&block.terminator().kind
@@ -819,7 +821,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
819821
/// Checks if a borrowed value was captured by a trait object. We do this by
820822
/// looking forward in the MIR from the reserve location and checking if we see
821823
/// an unsized cast to a trait object on our data.
822-
fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
824+
fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> Option<Span> {
823825
// Start at the reserve location, find the place that we want to see cast to a trait object.
824826
let location = borrow.reserve_location;
825827
let block = &self.body[location.block];
@@ -835,10 +837,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
835837
if let Some(local) = place.as_local() {
836838
local
837839
} else {
838-
return false;
840+
return None;
839841
}
840842
} else {
841-
return false;
843+
return None;
842844
};
843845

844846
debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
@@ -885,7 +887,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
885887
if from == target {
886888
debug!("was_captured_by_trait_object: ty={:?}", ty);
887889
// Check the type for a trait object.
888-
return match ty.kind() {
890+
let matches = match ty.kind() {
889891
// `&dyn Trait`
890892
ty::Ref(_, ty, _) if ty.is_trait() => true,
891893
// `Box<dyn Trait>`
@@ -898,11 +900,16 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
898900
// Anything else.
899901
_ => false,
900902
};
903+
if matches {
904+
return Some(stmt.source_info.span);
905+
} else {
906+
return None;
907+
}
901908
}
902909
}
903-
return false;
910+
return None;
904911
}
905-
_ => return false,
912+
_ => return None,
906913
}
907914
}
908915
_ => {}
@@ -926,7 +933,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
926933
);
927934
// Check if one of the arguments to this function is the target place.
928935
let found_target = args.iter().any(|arg| {
929-
if let Operand::Move(place) = arg.node {
936+
if let Operand::Move(place) | Operand::Copy(place) = arg.node {
930937
if let Some(potential) = place.as_local() {
931938
potential == target
932939
} else {
@@ -950,6 +957,6 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
950957
}
951958

952959
// We didn't find anything and ran out of locations to check.
953-
false
960+
None
954961
}
955962
}

compiler/rustc_hir_typeck/src/coercion.rs

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

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