mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-24 15:54:15 +00:00
Don't leak inference variables in array unsizing
This commit is contained in:
parent
012910dab2
commit
9bf9fe07dc
@ -149,7 +149,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
// time writing the results into the various typeck results.
|
||||
let mut autoderef =
|
||||
self.autoderef_overloaded_span(self.span, unadjusted_self_ty, self.call_expr.span);
|
||||
let (_, n) = match autoderef.nth(pick.autoderefs) {
|
||||
let (ty, n) = match autoderef.nth(pick.autoderefs) {
|
||||
Some(n) => n,
|
||||
None => {
|
||||
return self.tcx.ty_error_with_message(
|
||||
@ -161,14 +161,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
assert_eq!(n, pick.autoderefs);
|
||||
|
||||
let mut adjustments = self.adjust_steps(&autoderef);
|
||||
let mut target = self.structurally_resolved_type(autoderef.span(), ty);
|
||||
|
||||
let mut target =
|
||||
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
||||
|
||||
match &pick.autoref_or_ptr_adjustment {
|
||||
match pick.autoref_or_ptr_adjustment {
|
||||
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, unsize }) => {
|
||||
let region = self.next_region_var(infer::Autoref(self.span));
|
||||
target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl: *mutbl, ty: target });
|
||||
// Type we're wrapping in a reference, used later for unsizing
|
||||
let base_ty = target;
|
||||
|
||||
target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target });
|
||||
let mutbl = match mutbl {
|
||||
hir::Mutability::Not => AutoBorrowMutability::Not,
|
||||
hir::Mutability::Mut => AutoBorrowMutability::Mut {
|
||||
@ -182,10 +183,18 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
target,
|
||||
});
|
||||
|
||||
if let Some(unsize_target) = unsize {
|
||||
if unsize {
|
||||
let unsized_ty = if let ty::Array(elem_ty, _) = base_ty.kind() {
|
||||
self.tcx.mk_slice(elem_ty)
|
||||
} else {
|
||||
bug!(
|
||||
"AutorefOrPtrAdjustment's unsize flag should only be set for array ty, found {}",
|
||||
base_ty
|
||||
)
|
||||
};
|
||||
target = self
|
||||
.tcx
|
||||
.mk_ref(region, ty::TypeAndMut { mutbl: mutbl.into(), ty: unsize_target });
|
||||
.mk_ref(region, ty::TypeAndMut { mutbl: mutbl.into(), ty: unsized_ty });
|
||||
adjustments
|
||||
.push(Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), target });
|
||||
}
|
||||
|
@ -167,26 +167,26 @@ enum ProbeResult {
|
||||
/// T`, we could convert it to `*const T`, then autoref to `&*const T`. However, currently we do
|
||||
/// (at most) one of these. Either the receiver has type `T` and we convert it to `&T` (or with
|
||||
/// `mut`), or it has type `*mut T` and we convert it to `*const T`.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum AutorefOrPtrAdjustment<'tcx> {
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub enum AutorefOrPtrAdjustment {
|
||||
/// Receiver has type `T`, add `&` or `&mut` (it `T` is `mut`), and maybe also "unsize" it.
|
||||
/// Unsizing is used to convert a `[T; N]` to `[T]`, which only makes sense when autorefing.
|
||||
Autoref {
|
||||
mutbl: hir::Mutability,
|
||||
|
||||
/// Indicates that the source expression should be "unsized" to a target type. This should
|
||||
/// probably eventually go away in favor of just coercing method receivers.
|
||||
unsize: Option<Ty<'tcx>>,
|
||||
/// Indicates that the source expression should be "unsized" to a target type.
|
||||
/// This is special-cased for just arrays unsizing to slices.
|
||||
unsize: bool,
|
||||
},
|
||||
/// Receiver has type `*mut T`, convert to `*const T`
|
||||
ToConstPtr,
|
||||
}
|
||||
|
||||
impl<'tcx> AutorefOrPtrAdjustment<'tcx> {
|
||||
fn get_unsize(&self) -> Option<Ty<'tcx>> {
|
||||
impl AutorefOrPtrAdjustment {
|
||||
fn get_unsize(&self) -> bool {
|
||||
match self {
|
||||
AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize,
|
||||
AutorefOrPtrAdjustment::ToConstPtr => None,
|
||||
AutorefOrPtrAdjustment::ToConstPtr => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -204,7 +204,7 @@ pub struct Pick<'tcx> {
|
||||
|
||||
/// Indicates that we want to add an autoref (and maybe also unsize it), or if the receiver is
|
||||
/// `*mut T`, convert it to `*const T`.
|
||||
pub autoref_or_ptr_adjustment: Option<AutorefOrPtrAdjustment<'tcx>>,
|
||||
pub autoref_or_ptr_adjustment: Option<AutorefOrPtrAdjustment>,
|
||||
pub self_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
@ -1202,7 +1202,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
pick.autoderefs += 1;
|
||||
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
|
||||
mutbl,
|
||||
unsize: pick.autoref_or_ptr_adjustment.and_then(|a| a.get_unsize()),
|
||||
unsize: pick.autoref_or_ptr_adjustment.map_or(false, |a| a.get_unsize()),
|
||||
})
|
||||
}
|
||||
|
||||
@ -1227,10 +1227,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||
self.pick_method(autoref_ty, unstable_candidates).map(|r| {
|
||||
r.map(|mut pick| {
|
||||
pick.autoderefs = step.autoderefs;
|
||||
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::Autoref {
|
||||
mutbl,
|
||||
unsize: step.unsize.then_some(self_ty),
|
||||
});
|
||||
pick.autoref_or_ptr_adjustment =
|
||||
Some(AutorefOrPtrAdjustment::Autoref { mutbl, unsize: step.unsize });
|
||||
pick
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user