Skip to content

Commit d8775a4

Browse files
committed
coerce_to_ref: no structural identity reliance
1 parent f07b5e6 commit d8775a4

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
251251
ty::RawPtr(_, b_mutbl) => {
252252
return self.coerce_to_raw_ptr(a, b, b_mutbl);
253253
}
254-
ty::Ref(_, _, mutbl_b) => {
255-
return self.coerce_to_ref(a, b, mutbl_b);
254+
ty::Ref(r_b, _, mutbl_b) => {
255+
return self.coerce_to_ref(a, b, mutbl_b, r_b);
256256
}
257257
ty::Adt(pin, _)
258258
if self.tcx.features().pin_ergonomics()
@@ -343,15 +343,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
343343
a: Ty<'tcx>,
344344
b: Ty<'tcx>,
345345
mutbl_b: hir::Mutability,
346+
r_b: ty::Region<'tcx>,
346347
) -> CoerceResult<'tcx> {
347348
debug!("coerce_to_ref(a={:?}, b={:?})", a, b);
348349
debug_assert!(self.shallow_resolve(a) == a);
349350
debug_assert!(self.shallow_resolve(b) == b);
350351

351-
let mt_a = match *a.kind() {
352-
ty::Ref(_, ty, mutbl) => {
352+
let (r_a, mt_a) = match *a.kind() {
353+
ty::Ref(r_a, ty, mutbl) => {
353354
coerce_mutbls(mutbl, mutbl_b)?;
354-
ty::TypeAndMut { ty, mutbl }
355+
(r_a, ty::TypeAndMut { ty, mutbl })
355356
}
356357
_ => return self.unify(a, b),
357358
};
@@ -368,6 +369,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
368369
// 3. `[T]`, autoref'd ty: `&M [T]`
369370
// - `&M [T]` does unify with `&M [T]`
370371
let mut first_error = None;
372+
let mut r_borrow_var = None;
371373
let mut autoderef = self.autoderef(self.cause.span, a);
372374
let found = autoderef.by_ref().find_map(|(deref_ty, autoderefs)| {
373375
if autoderefs == 0 {
@@ -376,9 +378,29 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
376378
return None;
377379
}
378380

379-
let coercion = RegionVariableOrigin::Coercion(self.cause.span);
380-
let r_borrow = self.next_region_var(coercion);
381-
let autorefd_deref_ty = Ty::new_ref(self.tcx, r_borrow, deref_ty, mutbl_b);
381+
let r = if !self.use_lub {
382+
r_b // [2] above
383+
} else if autoderefs == 1 {
384+
r_a // [3] above
385+
} else {
386+
if r_borrow_var.is_none() {
387+
// create var lazily, at most once
388+
let coercion = RegionVariableOrigin::Coercion(self.cause.span);
389+
let r = self.next_region_var(coercion);
390+
r_borrow_var = Some(r); // [4] above
391+
}
392+
r_borrow_var.unwrap()
393+
};
394+
let autorefd_deref_ty = Ty::new_ref(
395+
self.tcx,
396+
r,
397+
deref_ty,
398+
mutbl_b, // [1] above
399+
);
400+
401+
// let coercion = RegionVariableOrigin::Coercion(self.cause.span);
402+
// let r_borrow = self.next_region_var(coercion);
403+
// let autorefd_deref_ty = Ty::new_ref(self.tcx, r_borrow, deref_ty, mutbl_b);
382404

383405
// Note that we unify the autoref'd `Target` type with `b` rather than
384406
// the `Target` type with the pointee of `b`. This is necessary

0 commit comments

Comments
 (0)