mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Revert "Rollup merge of #98582 - oli-obk:unconstrained_opaque_type, r=estebank"
This reverts commit6f8fb911ad
, reversing changes made to7210e46dc6
.
This commit is contained in:
parent
03d488b48a
commit
4a742a691e
@ -2155,9 +2155,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
StorageDeadOrDrop::Destructor(_) => kind,
|
StorageDeadOrDrop::Destructor(_) => kind,
|
||||||
},
|
},
|
||||||
ProjectionElem::OpaqueCast { .. }
|
ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
|
||||||
| ProjectionElem::Field(..)
|
|
||||||
| ProjectionElem::Downcast(..) => {
|
|
||||||
match place_ty.ty.kind() {
|
match place_ty.ty.kind() {
|
||||||
ty::Adt(def, _) if def.has_dtor(tcx) => {
|
ty::Adt(def, _) if def.has_dtor(tcx) => {
|
||||||
// Report the outermost adt with a destructor
|
// Report the outermost adt with a destructor
|
||||||
|
@ -226,7 +226,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
ProjectionElem::Downcast(..) if including_downcast.0 => return None,
|
ProjectionElem::Downcast(..) if including_downcast.0 => return None,
|
||||||
ProjectionElem::Downcast(..) => (),
|
ProjectionElem::Downcast(..) => (),
|
||||||
ProjectionElem::OpaqueCast(..) => (),
|
|
||||||
ProjectionElem::Field(field, _ty) => {
|
ProjectionElem::Field(field, _ty) => {
|
||||||
// FIXME(project-rfc_2229#36): print capture precisely here.
|
// FIXME(project-rfc_2229#36): print capture precisely here.
|
||||||
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
|
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
|
||||||
@ -287,7 +286,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
|
PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
|
||||||
}
|
}
|
||||||
ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
|
ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
|
||||||
ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(*ty),
|
|
||||||
ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
|
ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -169,7 +169,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
..,
|
..,
|
||||||
ProjectionElem::Index(_)
|
ProjectionElem::Index(_)
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::OpaqueCast { .. }
|
|
||||||
| ProjectionElem::Subslice { .. }
|
| ProjectionElem::Subslice { .. }
|
||||||
| ProjectionElem::Downcast(..),
|
| ProjectionElem::Downcast(..),
|
||||||
],
|
],
|
||||||
|
@ -1788,7 +1788,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
for (place_base, elem) in place.iter_projections().rev() {
|
for (place_base, elem) in place.iter_projections().rev() {
|
||||||
match elem {
|
match elem {
|
||||||
ProjectionElem::Index(_/*operand*/) |
|
ProjectionElem::Index(_/*operand*/) |
|
||||||
ProjectionElem::OpaqueCast(_) |
|
|
||||||
ProjectionElem::ConstantIndex { .. } |
|
ProjectionElem::ConstantIndex { .. } |
|
||||||
// assigning to P[i] requires P to be valid.
|
// assigning to P[i] requires P to be valid.
|
||||||
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
|
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
|
||||||
@ -2180,7 +2179,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
| ProjectionElem::Index(..)
|
| ProjectionElem::Index(..)
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::Subslice { .. }
|
| ProjectionElem::Subslice { .. }
|
||||||
| ProjectionElem::OpaqueCast { .. }
|
|
||||||
| ProjectionElem::Downcast(..) => {
|
| ProjectionElem::Downcast(..) => {
|
||||||
let upvar_field_projection = self.is_upvar_field_projection(place);
|
let upvar_field_projection = self.is_upvar_field_projection(place);
|
||||||
if let Some(field) = upvar_field_projection {
|
if let Some(field) = upvar_field_projection {
|
||||||
|
@ -255,7 +255,6 @@ fn place_components_conflict<'tcx>(
|
|||||||
| (ProjectionElem::Index { .. }, _, _)
|
| (ProjectionElem::Index { .. }, _, _)
|
||||||
| (ProjectionElem::ConstantIndex { .. }, _, _)
|
| (ProjectionElem::ConstantIndex { .. }, _, _)
|
||||||
| (ProjectionElem::Subslice { .. }, _, _)
|
| (ProjectionElem::Subslice { .. }, _, _)
|
||||||
| (ProjectionElem::OpaqueCast { .. }, _, _)
|
|
||||||
| (ProjectionElem::Downcast { .. }, _, _) => {
|
| (ProjectionElem::Downcast { .. }, _, _) => {
|
||||||
// Recursive case. This can still be disjoint on a
|
// Recursive case. This can still be disjoint on a
|
||||||
// further iteration if this a shallow access and
|
// further iteration if this a shallow access and
|
||||||
@ -323,17 +322,6 @@ fn place_projection_conflict<'tcx>(
|
|||||||
debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
|
debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
|
||||||
Overlap::EqualOrDisjoint
|
Overlap::EqualOrDisjoint
|
||||||
}
|
}
|
||||||
(ProjectionElem::OpaqueCast(v1), ProjectionElem::OpaqueCast(v2)) => {
|
|
||||||
if v1 == v2 {
|
|
||||||
// same type - recur.
|
|
||||||
debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
|
|
||||||
Overlap::EqualOrDisjoint
|
|
||||||
} else {
|
|
||||||
// Different types. Disjoint!
|
|
||||||
debug!("place_element_conflict: DISJOINT-OPAQUE");
|
|
||||||
Overlap::Disjoint
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
|
(ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
|
||||||
if f1 == f2 {
|
if f1 == f2 {
|
||||||
// same field (e.g., `a.y` vs. `a.y`) - recur.
|
// same field (e.g., `a.y` vs. `a.y`) - recur.
|
||||||
@ -537,7 +525,6 @@ fn place_projection_conflict<'tcx>(
|
|||||||
| ProjectionElem::Field(..)
|
| ProjectionElem::Field(..)
|
||||||
| ProjectionElem::Index(..)
|
| ProjectionElem::Index(..)
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::OpaqueCast { .. }
|
|
||||||
| ProjectionElem::Subslice { .. }
|
| ProjectionElem::Subslice { .. }
|
||||||
| ProjectionElem::Downcast(..),
|
| ProjectionElem::Downcast(..),
|
||||||
_,
|
_,
|
||||||
|
@ -81,7 +81,6 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
ProjectionElem::Downcast(..)
|
ProjectionElem::Downcast(..)
|
||||||
| ProjectionElem::Subslice { .. }
|
| ProjectionElem::Subslice { .. }
|
||||||
| ProjectionElem::OpaqueCast { .. }
|
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::Index(_) => {
|
| ProjectionElem::Index(_) => {
|
||||||
cursor = cursor_base;
|
cursor = cursor_base;
|
||||||
|
@ -790,19 +790,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||||||
}
|
}
|
||||||
PlaceTy::from_ty(fty)
|
PlaceTy::from_ty(fty)
|
||||||
}
|
}
|
||||||
ProjectionElem::OpaqueCast(ty) => {
|
|
||||||
let ty = self.sanitize_type(place, ty);
|
|
||||||
let ty = self.cx.normalize(ty, location);
|
|
||||||
self.cx
|
|
||||||
.eq_types(
|
|
||||||
base.ty,
|
|
||||||
ty,
|
|
||||||
location.to_locations(),
|
|
||||||
ConstraintCategory::TypeAnnotation,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
PlaceTy::from_ty(ty)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1208,11 +1195,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
tcx,
|
tcx,
|
||||||
self.param_env,
|
self.param_env,
|
||||||
proj,
|
proj,
|
||||||
|this, field, _| {
|
|this, field, ()| {
|
||||||
let ty = this.field_ty(tcx, field);
|
let ty = this.field_ty(tcx, field);
|
||||||
self.normalize(ty, locations)
|
self.normalize(ty, locations)
|
||||||
},
|
},
|
||||||
|_, _| unreachable!(),
|
|
||||||
);
|
);
|
||||||
curr_projected_ty = projected_ty;
|
curr_projected_ty = projected_ty;
|
||||||
}
|
}
|
||||||
@ -2507,7 +2493,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
ProjectionElem::Field(..)
|
ProjectionElem::Field(..)
|
||||||
| ProjectionElem::Downcast(..)
|
| ProjectionElem::Downcast(..)
|
||||||
| ProjectionElem::OpaqueCast(..)
|
|
||||||
| ProjectionElem::Index(..)
|
| ProjectionElem::Index(..)
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::Subslice { .. } => {
|
| ProjectionElem::Subslice { .. } => {
|
||||||
|
@ -825,7 +825,6 @@ pub(crate) fn codegen_place<'tcx>(
|
|||||||
cplace = cplace.place_deref(fx);
|
cplace = cplace.place_deref(fx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PlaceElem::OpaqueCast(ty) => cplace = cplace.place_opaque_cast(fx, ty),
|
|
||||||
PlaceElem::Field(field, _ty) => {
|
PlaceElem::Field(field, _ty) => {
|
||||||
cplace = cplace.place_field(fx, field);
|
cplace = cplace.place_field(fx, field);
|
||||||
}
|
}
|
||||||
|
@ -615,14 +615,6 @@ impl<'tcx> CPlace<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn place_opaque_cast(
|
|
||||||
self,
|
|
||||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> CPlace<'tcx> {
|
|
||||||
CPlace { inner: self.inner, layout: fx.layout_of(ty) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn place_field(
|
pub(crate) fn place_field(
|
||||||
self,
|
self,
|
||||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||||
|
@ -411,21 +411,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||||||
downcast
|
downcast
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn project_type<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
|
|
||||||
&self,
|
|
||||||
bx: &mut Bx,
|
|
||||||
ty: Ty<'tcx>,
|
|
||||||
) -> Self {
|
|
||||||
let mut downcast = *self;
|
|
||||||
downcast.layout = bx.cx().layout_of(ty);
|
|
||||||
|
|
||||||
// Cast to the appropriate type.
|
|
||||||
let variant_ty = bx.cx().backend_type(downcast.layout);
|
|
||||||
downcast.llval = bx.pointercast(downcast.llval, bx.cx().type_ptr_to(variant_ty));
|
|
||||||
|
|
||||||
downcast
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn storage_live<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) {
|
pub fn storage_live<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) {
|
||||||
bx.lifetime_start(self.llval, self.layout.size);
|
bx.lifetime_start(self.llval, self.layout.size);
|
||||||
}
|
}
|
||||||
@ -474,7 +459,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
mir::ProjectionElem::Field(ref field, _) => {
|
mir::ProjectionElem::Field(ref field, _) => {
|
||||||
cg_base.project_field(bx, field.index())
|
cg_base.project_field(bx, field.index())
|
||||||
}
|
}
|
||||||
mir::ProjectionElem::OpaqueCast(ty) => cg_base.project_type(bx, ty),
|
|
||||||
mir::ProjectionElem::Index(index) => {
|
mir::ProjectionElem::Index(index) => {
|
||||||
let index = &mir::Operand::Copy(mir::Place::from(index));
|
let index = &mir::Operand::Copy(mir::Place::from(index));
|
||||||
let index = self.codegen_operand(bx, index);
|
let index = self.codegen_operand(bx, index);
|
||||||
|
@ -349,11 +349,6 @@ where
|
|||||||
) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
|
) -> InterpResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
|
||||||
use rustc_middle::mir::ProjectionElem::*;
|
use rustc_middle::mir::ProjectionElem::*;
|
||||||
Ok(match proj_elem {
|
Ok(match proj_elem {
|
||||||
OpaqueCast(ty) => {
|
|
||||||
let mut place = base.clone();
|
|
||||||
place.layout = self.layout_of(ty)?;
|
|
||||||
place
|
|
||||||
}
|
|
||||||
Field(field, _) => self.place_field(base, field.index())?,
|
Field(field, _) => self.place_field(base, field.index())?,
|
||||||
Downcast(_, variant) => self.place_downcast(base, variant)?,
|
Downcast(_, variant) => self.place_downcast(base, variant)?,
|
||||||
Deref => self.deref_operand(&self.place_to_op(base)?)?.into(),
|
Deref => self.deref_operand(&self.place_to_op(base)?)?.into(),
|
||||||
@ -378,11 +373,6 @@ where
|
|||||||
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||||
use rustc_middle::mir::ProjectionElem::*;
|
use rustc_middle::mir::ProjectionElem::*;
|
||||||
Ok(match proj_elem {
|
Ok(match proj_elem {
|
||||||
OpaqueCast(ty) => {
|
|
||||||
let mut op = base.clone();
|
|
||||||
op.layout = self.layout_of(ty)?;
|
|
||||||
op
|
|
||||||
}
|
|
||||||
Field(field, _) => self.operand_field(base, field.index())?,
|
Field(field, _) => self.operand_field(base, field.index())?,
|
||||||
Downcast(_, variant) => self.operand_downcast(base, variant)?,
|
Downcast(_, variant) => self.operand_downcast(base, variant)?,
|
||||||
Deref => self.deref_operand(base)?.into(),
|
Deref => self.deref_operand(base)?.into(),
|
||||||
|
@ -652,7 +652,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
|
|
||||||
ProjectionElem::ConstantIndex { .. }
|
ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::Downcast(..)
|
| ProjectionElem::Downcast(..)
|
||||||
| ProjectionElem::OpaqueCast(..)
|
|
||||||
| ProjectionElem::Subslice { .. }
|
| ProjectionElem::Subslice { .. }
|
||||||
| ProjectionElem::Field(..)
|
| ProjectionElem::Field(..)
|
||||||
| ProjectionElem::Index(_) => {}
|
| ProjectionElem::Index(_) => {}
|
||||||
|
@ -316,7 +316,6 @@ where
|
|||||||
|
|
||||||
ProjectionElem::Deref
|
ProjectionElem::Deref
|
||||||
| ProjectionElem::Field(_, _)
|
| ProjectionElem::Field(_, _)
|
||||||
| ProjectionElem::OpaqueCast(_)
|
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::Subslice { .. }
|
| ProjectionElem::Subslice { .. }
|
||||||
| ProjectionElem::Downcast(_, _)
|
| ProjectionElem::Downcast(_, _)
|
||||||
|
@ -361,7 +361,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||||||
return Err(Unpromotable);
|
return Err(Unpromotable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProjectionElem::OpaqueCast(..) | ProjectionElem::Downcast(..) => {
|
ProjectionElem::Downcast(..) => {
|
||||||
return Err(Unpromotable);
|
return Err(Unpromotable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1397,7 +1397,6 @@ impl<V, T> ProjectionElem<V, T> {
|
|||||||
|
|
||||||
Self::Field(_, _)
|
Self::Field(_, _)
|
||||||
| Self::Index(_)
|
| Self::Index(_)
|
||||||
| Self::OpaqueCast(_)
|
|
||||||
| Self::ConstantIndex { .. }
|
| Self::ConstantIndex { .. }
|
||||||
| Self::Subslice { .. }
|
| Self::Subslice { .. }
|
||||||
| Self::Downcast(_, _) => false,
|
| Self::Downcast(_, _) => false,
|
||||||
@ -1575,9 +1574,7 @@ impl Debug for Place<'_> {
|
|||||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||||
for elem in self.projection.iter().rev() {
|
for elem in self.projection.iter().rev() {
|
||||||
match elem {
|
match elem {
|
||||||
ProjectionElem::OpaqueCast(_)
|
ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => {
|
||||||
| ProjectionElem::Downcast(_, _)
|
|
||||||
| ProjectionElem::Field(_, _) => {
|
|
||||||
write!(fmt, "(").unwrap();
|
write!(fmt, "(").unwrap();
|
||||||
}
|
}
|
||||||
ProjectionElem::Deref => {
|
ProjectionElem::Deref => {
|
||||||
@ -1593,9 +1590,6 @@ impl Debug for Place<'_> {
|
|||||||
|
|
||||||
for elem in self.projection.iter() {
|
for elem in self.projection.iter() {
|
||||||
match elem {
|
match elem {
|
||||||
ProjectionElem::OpaqueCast(ty) => {
|
|
||||||
write!(fmt, " as {})", ty)?;
|
|
||||||
}
|
|
||||||
ProjectionElem::Downcast(Some(name), _index) => {
|
ProjectionElem::Downcast(Some(name), _index) => {
|
||||||
write!(fmt, " as {})", name)?;
|
write!(fmt, " as {})", name)?;
|
||||||
}
|
}
|
||||||
|
@ -754,9 +754,6 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
|
|||||||
/// generator has more than one variant, the parent place's variant index must be set, indicating
|
/// generator has more than one variant, the parent place's variant index must be set, indicating
|
||||||
/// which variant is being used. If it has just one variant, the variant index may or may not be
|
/// which variant is being used. If it has just one variant, the variant index may or may not be
|
||||||
/// included - the single possible variant is inferred if it is not included.
|
/// included - the single possible variant is inferred if it is not included.
|
||||||
/// - [`OpaqueCast`](ProjectionElem::OpaqueCast): This projection changes the place's type to the
|
|
||||||
/// given one, and makes no other changes. A `OpaqueCast` projection on any type other than an
|
|
||||||
/// opaque type from the current crate is not well-formed.
|
|
||||||
/// - [`ConstantIndex`](ProjectionElem::ConstantIndex): Computes an offset in units of `T` into the
|
/// - [`ConstantIndex`](ProjectionElem::ConstantIndex): Computes an offset in units of `T` into the
|
||||||
/// place as described in the documentation for the `ProjectionElem`. The resulting address is
|
/// place as described in the documentation for the `ProjectionElem`. The resulting address is
|
||||||
/// the parent's address plus that offset, and the type is `T`. This is only legal if the parent
|
/// the parent's address plus that offset, and the type is `T`. This is only legal if the parent
|
||||||
@ -859,10 +856,6 @@ pub enum ProjectionElem<V, T> {
|
|||||||
///
|
///
|
||||||
/// The included Symbol is the name of the variant, used for printing MIR.
|
/// The included Symbol is the name of the variant, used for printing MIR.
|
||||||
Downcast(Option<Symbol>, VariantIdx),
|
Downcast(Option<Symbol>, VariantIdx),
|
||||||
|
|
||||||
/// Like an explicit cast from an opaque type to a concrete type, but without
|
|
||||||
/// requiring an intermediate variable.
|
|
||||||
OpaqueCast(T),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alias for projections as they appear in places, where the base is a place
|
/// Alias for projections as they appear in places, where the base is a place
|
||||||
|
@ -57,7 +57,7 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||||||
/// `PlaceElem`, where we can just use the `Ty` that is already
|
/// `PlaceElem`, where we can just use the `Ty` that is already
|
||||||
/// stored inline on field projection elems.
|
/// stored inline on field projection elems.
|
||||||
pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
|
pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
|
||||||
self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty, |_, ty| ty)
|
self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
|
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
|
||||||
@ -71,7 +71,6 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
elem: &ProjectionElem<V, T>,
|
elem: &ProjectionElem<V, T>,
|
||||||
mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
|
mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
|
||||||
mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
|
|
||||||
) -> PlaceTy<'tcx>
|
) -> PlaceTy<'tcx>
|
||||||
where
|
where
|
||||||
V: ::std::fmt::Debug,
|
V: ::std::fmt::Debug,
|
||||||
@ -110,7 +109,6 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||||||
PlaceTy { ty: self.ty, variant_index: Some(index) }
|
PlaceTy { ty: self.ty, variant_index: Some(index) }
|
||||||
}
|
}
|
||||||
ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
|
ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
|
||||||
ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast(&self, ty)),
|
|
||||||
};
|
};
|
||||||
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
|
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
|
||||||
answer
|
answer
|
||||||
|
@ -182,7 +182,6 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
|
|||||||
Ok(match self {
|
Ok(match self {
|
||||||
Deref => Deref,
|
Deref => Deref,
|
||||||
Field(f, ty) => Field(f, ty.try_fold_with(folder)?),
|
Field(f, ty) => Field(f, ty.try_fold_with(folder)?),
|
||||||
OpaqueCast(ty) => OpaqueCast(ty.try_fold_with(folder)?),
|
|
||||||
Index(v) => Index(v.try_fold_with(folder)?),
|
Index(v) => Index(v.try_fold_with(folder)?),
|
||||||
Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
|
Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
|
||||||
ConstantIndex { offset, min_length, from_end } => {
|
ConstantIndex { offset, min_length, from_end } => {
|
||||||
|
@ -1064,11 +1064,6 @@ macro_rules! visit_place_fns {
|
|||||||
self.visit_ty(&mut new_ty, TyContext::Location(location));
|
self.visit_ty(&mut new_ty, TyContext::Location(location));
|
||||||
if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
|
if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
|
||||||
}
|
}
|
||||||
PlaceElem::OpaqueCast(ty) => {
|
|
||||||
let mut new_ty = ty;
|
|
||||||
self.visit_ty(&mut new_ty, TyContext::Location(location));
|
|
||||||
if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
|
|
||||||
}
|
|
||||||
PlaceElem::Deref
|
PlaceElem::Deref
|
||||||
| PlaceElem::ConstantIndex { .. }
|
| PlaceElem::ConstantIndex { .. }
|
||||||
| PlaceElem::Subslice { .. }
|
| PlaceElem::Subslice { .. }
|
||||||
@ -1138,7 +1133,7 @@ macro_rules! visit_place_fns {
|
|||||||
location: Location,
|
location: Location,
|
||||||
) {
|
) {
|
||||||
match elem {
|
match elem {
|
||||||
ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) => {
|
ProjectionElem::Field(_field, ty) => {
|
||||||
self.visit_ty(ty, TyContext::Location(location));
|
self.visit_ty(ty, TyContext::Location(location));
|
||||||
}
|
}
|
||||||
ProjectionElem::Index(local) => {
|
ProjectionElem::Index(local) => {
|
||||||
|
@ -7,7 +7,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
|||||||
use rustc_middle::hir::place::Projection as HirProjection;
|
use rustc_middle::hir::place::Projection as HirProjection;
|
||||||
use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
|
use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
|
||||||
use rustc_middle::middle::region;
|
use rustc_middle::middle::region;
|
||||||
use rustc_middle::mir::tcx::PlaceTy;
|
|
||||||
use rustc_middle::mir::AssertKind::BoundsCheck;
|
use rustc_middle::mir::AssertKind::BoundsCheck;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
@ -72,7 +71,7 @@ pub(crate) enum PlaceBase {
|
|||||||
/// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
|
/// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
|
||||||
/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
|
/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub(in crate::build) struct PlaceBuilder<'tcx> {
|
pub(crate) struct PlaceBuilder<'tcx> {
|
||||||
base: PlaceBase,
|
base: PlaceBase,
|
||||||
projection: Vec<PlaceElem<'tcx>>,
|
projection: Vec<PlaceElem<'tcx>>,
|
||||||
}
|
}
|
||||||
@ -105,8 +104,6 @@ fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
|
|||||||
variant = Some(*idx);
|
variant = Some(*idx);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// These do not affect anything, they just make sure we know the right type.
|
|
||||||
ProjectionElem::OpaqueCast(_) => continue,
|
|
||||||
ProjectionElem::Index(..)
|
ProjectionElem::Index(..)
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::Subslice { .. } => {
|
| ProjectionElem::Subslice { .. } => {
|
||||||
@ -204,10 +201,10 @@ fn find_capture_matching_projections<'a, 'tcx>(
|
|||||||
/// `PlaceBuilder` now starts from `PlaceBase::Local`.
|
/// `PlaceBuilder` now starts from `PlaceBase::Local`.
|
||||||
///
|
///
|
||||||
/// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found.
|
/// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found.
|
||||||
#[instrument(level = "trace", skip(cx))]
|
fn to_upvars_resolved_place_builder<'a, 'tcx>(
|
||||||
fn to_upvars_resolved_place_builder<'tcx>(
|
|
||||||
from_builder: PlaceBuilder<'tcx>,
|
from_builder: PlaceBuilder<'tcx>,
|
||||||
cx: &Builder<'_, 'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
typeck_results: &'a ty::TypeckResults<'tcx>,
|
||||||
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
|
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
|
||||||
match from_builder.base {
|
match from_builder.base {
|
||||||
PlaceBase::Local(_) => Ok(from_builder),
|
PlaceBase::Local(_) => Ok(from_builder),
|
||||||
@ -222,13 +219,13 @@ fn to_upvars_resolved_place_builder<'tcx>(
|
|||||||
|
|
||||||
let Some((capture_index, capture)) =
|
let Some((capture_index, capture)) =
|
||||||
find_capture_matching_projections(
|
find_capture_matching_projections(
|
||||||
cx.typeck_results,
|
typeck_results,
|
||||||
var_hir_id,
|
var_hir_id,
|
||||||
closure_def_id,
|
closure_def_id,
|
||||||
&from_builder.projection,
|
&from_builder.projection,
|
||||||
) else {
|
) else {
|
||||||
let closure_span = cx.tcx.def_span(closure_def_id);
|
let closure_span = tcx.def_span(closure_def_id);
|
||||||
if !enable_precise_capture(cx.tcx, closure_span) {
|
if !enable_precise_capture(tcx, closure_span) {
|
||||||
bug!(
|
bug!(
|
||||||
"No associated capture found for {:?}[{:#?}] even though \
|
"No associated capture found for {:?}[{:#?}] even though \
|
||||||
capture_disjoint_fields isn't enabled",
|
capture_disjoint_fields isn't enabled",
|
||||||
@ -245,8 +242,8 @@ fn to_upvars_resolved_place_builder<'tcx>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// We won't be building MIR if the closure wasn't local
|
// We won't be building MIR if the closure wasn't local
|
||||||
let closure_hir_id = cx.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
|
let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
|
||||||
let closure_ty = cx.typeck_results.node_type(closure_hir_id);
|
let closure_ty = typeck_results.node_type(closure_hir_id);
|
||||||
|
|
||||||
let substs = match closure_ty.kind() {
|
let substs = match closure_ty.kind() {
|
||||||
ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
|
ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
|
||||||
@ -273,14 +270,12 @@ fn to_upvars_resolved_place_builder<'tcx>(
|
|||||||
|
|
||||||
// We used some of the projections to build the capture itself,
|
// We used some of the projections to build the capture itself,
|
||||||
// now we apply the remaining to the upvar resolved place.
|
// now we apply the remaining to the upvar resolved place.
|
||||||
trace!(?capture.place, ?from_builder.projection);
|
|
||||||
let remaining_projections = strip_prefix(
|
let remaining_projections = strip_prefix(
|
||||||
capture.place.base_ty,
|
capture.place.base_ty,
|
||||||
from_builder.projection,
|
from_builder.projection,
|
||||||
&capture.place.projections,
|
&capture.place.projections,
|
||||||
);
|
);
|
||||||
upvar_resolved_place_builder.projection.extend(remaining_projections);
|
upvar_resolved_place_builder.projection.extend(remaining_projections);
|
||||||
trace!(?upvar_resolved_place_builder);
|
|
||||||
|
|
||||||
Ok(upvar_resolved_place_builder)
|
Ok(upvar_resolved_place_builder)
|
||||||
}
|
}
|
||||||
@ -299,21 +294,16 @@ fn strip_prefix<'tcx>(
|
|||||||
prefix_projections: &[HirProjection<'tcx>],
|
prefix_projections: &[HirProjection<'tcx>],
|
||||||
) -> impl Iterator<Item = PlaceElem<'tcx>> {
|
) -> impl Iterator<Item = PlaceElem<'tcx>> {
|
||||||
let mut iter = projections.into_iter();
|
let mut iter = projections.into_iter();
|
||||||
let mut next = || match iter.next()? {
|
|
||||||
// Filter out opaque casts, they are unnecessary in the prefix.
|
|
||||||
ProjectionElem::OpaqueCast(..) => iter.next(),
|
|
||||||
other => Some(other),
|
|
||||||
};
|
|
||||||
for projection in prefix_projections {
|
for projection in prefix_projections {
|
||||||
match projection.kind {
|
match projection.kind {
|
||||||
HirProjectionKind::Deref => {
|
HirProjectionKind::Deref => {
|
||||||
assert!(matches!(next(), Some(ProjectionElem::Deref)));
|
assert!(matches!(iter.next(), Some(ProjectionElem::Deref)));
|
||||||
}
|
}
|
||||||
HirProjectionKind::Field(..) => {
|
HirProjectionKind::Field(..) => {
|
||||||
if base_ty.is_enum() {
|
if base_ty.is_enum() {
|
||||||
assert!(matches!(next(), Some(ProjectionElem::Downcast(..))));
|
assert!(matches!(iter.next(), Some(ProjectionElem::Downcast(..))));
|
||||||
}
|
}
|
||||||
assert!(matches!(next(), Some(ProjectionElem::Field(..))));
|
assert!(matches!(iter.next(), Some(ProjectionElem::Field(..))));
|
||||||
}
|
}
|
||||||
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
||||||
bug!("unexpected projection kind: {:?}", projection);
|
bug!("unexpected projection kind: {:?}", projection);
|
||||||
@ -325,32 +315,24 @@ fn strip_prefix<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> PlaceBuilder<'tcx> {
|
impl<'tcx> PlaceBuilder<'tcx> {
|
||||||
pub(crate) fn into_place(self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> {
|
pub(crate) fn into_place<'a>(
|
||||||
|
self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
typeck_results: &'a ty::TypeckResults<'tcx>,
|
||||||
|
) -> Place<'tcx> {
|
||||||
if let PlaceBase::Local(local) = self.base {
|
if let PlaceBase::Local(local) = self.base {
|
||||||
let mut projections = vec![];
|
Place { local, projection: tcx.intern_place_elems(&self.projection) }
|
||||||
let mut ty = PlaceTy::from_ty(cx.local_decls[local].ty);
|
|
||||||
for projection in self.projection {
|
|
||||||
// Only preserve those opaque casts that actually go from an opaque type
|
|
||||||
// to another type.
|
|
||||||
if let ProjectionElem::OpaqueCast(t) = projection {
|
|
||||||
if let ty::Opaque(..) = ty.ty.kind() {
|
|
||||||
if t != ty.ty {
|
|
||||||
projections.push(ProjectionElem::OpaqueCast(t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
projections.push(projection);
|
self.expect_upvars_resolved(tcx, typeck_results).into_place(tcx, typeck_results)
|
||||||
}
|
|
||||||
ty = ty.projection_ty(cx.tcx, projection);
|
|
||||||
}
|
|
||||||
Place { local, projection: cx.tcx.intern_place_elems(&projections) }
|
|
||||||
} else {
|
|
||||||
self.expect_upvars_resolved(cx).into_place(cx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_upvars_resolved(self, cx: &Builder<'_, 'tcx>) -> PlaceBuilder<'tcx> {
|
fn expect_upvars_resolved<'a>(
|
||||||
to_upvars_resolved_place_builder(self, cx).unwrap()
|
self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
typeck_results: &'a ty::TypeckResults<'tcx>,
|
||||||
|
) -> PlaceBuilder<'tcx> {
|
||||||
|
to_upvars_resolved_place_builder(self, tcx, typeck_results).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to resolve the `PlaceBuilder`.
|
/// Attempts to resolve the `PlaceBuilder`.
|
||||||
@ -364,11 +346,12 @@ impl<'tcx> PlaceBuilder<'tcx> {
|
|||||||
/// not captured. This can happen because the final mir that will be
|
/// not captured. This can happen because the final mir that will be
|
||||||
/// generated doesn't require a read for this place. Failures will only
|
/// generated doesn't require a read for this place. Failures will only
|
||||||
/// happen inside closures.
|
/// happen inside closures.
|
||||||
pub(crate) fn try_upvars_resolved(
|
pub(crate) fn try_upvars_resolved<'a>(
|
||||||
self,
|
self,
|
||||||
cx: &Builder<'_, 'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
typeck_results: &'a ty::TypeckResults<'tcx>,
|
||||||
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
|
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
|
||||||
to_upvars_resolved_place_builder(self, cx)
|
to_upvars_resolved_place_builder(self, tcx, typeck_results)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn base(&self) -> PlaceBase {
|
pub(crate) fn base(&self) -> PlaceBase {
|
||||||
@ -428,7 +411,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
expr: &Expr<'tcx>,
|
expr: &Expr<'tcx>,
|
||||||
) -> BlockAnd<Place<'tcx>> {
|
) -> BlockAnd<Place<'tcx>> {
|
||||||
let place_builder = unpack!(block = self.as_place_builder(block, expr));
|
let place_builder = unpack!(block = self.as_place_builder(block, expr));
|
||||||
block.and(place_builder.into_place(self))
|
block.and(place_builder.into_place(self.tcx, self.typeck_results))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is used when constructing a compound `Place`, so that we can avoid creating
|
/// This is used when constructing a compound `Place`, so that we can avoid creating
|
||||||
@ -452,7 +435,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
expr: &Expr<'tcx>,
|
expr: &Expr<'tcx>,
|
||||||
) -> BlockAnd<Place<'tcx>> {
|
) -> BlockAnd<Place<'tcx>> {
|
||||||
let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
|
let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
|
||||||
block.and(place_builder.into_place(self))
|
block.and(place_builder.into_place(self.tcx, self.typeck_results))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is used when constructing a compound `Place`, so that we can avoid creating
|
/// This is used when constructing a compound `Place`, so that we can avoid creating
|
||||||
@ -547,7 +530,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
inferred_ty: expr.ty,
|
inferred_ty: expr.ty,
|
||||||
});
|
});
|
||||||
|
|
||||||
let place = place_builder.clone().into_place(this);
|
let place = place_builder.clone().into_place(this.tcx, this.typeck_results);
|
||||||
this.cfg.push(
|
this.cfg.push(
|
||||||
block,
|
block,
|
||||||
Statement {
|
Statement {
|
||||||
@ -699,7 +682,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
if is_outermost_index {
|
if is_outermost_index {
|
||||||
self.read_fake_borrows(block, fake_borrow_temps, source_info)
|
self.read_fake_borrows(block, fake_borrow_temps, source_info)
|
||||||
} else {
|
} else {
|
||||||
base_place = base_place.expect_upvars_resolved(self);
|
base_place = base_place.expect_upvars_resolved(self.tcx, self.typeck_results);
|
||||||
self.add_fake_borrows_of_base(
|
self.add_fake_borrows_of_base(
|
||||||
&base_place,
|
&base_place,
|
||||||
block,
|
block,
|
||||||
@ -727,7 +710,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let lt = self.temp(bool_ty, expr_span);
|
let lt = self.temp(bool_ty, expr_span);
|
||||||
|
|
||||||
// len = len(slice)
|
// len = len(slice)
|
||||||
self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.into_place(self)));
|
self.cfg.push_assign(
|
||||||
|
block,
|
||||||
|
source_info,
|
||||||
|
len,
|
||||||
|
Rvalue::Len(slice.into_place(self.tcx, self.typeck_results)),
|
||||||
|
);
|
||||||
// lt = idx < len
|
// lt = idx < len
|
||||||
self.cfg.push_assign(
|
self.cfg.push_assign(
|
||||||
block,
|
block,
|
||||||
@ -807,7 +795,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
ProjectionElem::Field(..)
|
ProjectionElem::Field(..)
|
||||||
| ProjectionElem::Downcast(..)
|
| ProjectionElem::Downcast(..)
|
||||||
| ProjectionElem::OpaqueCast(..)
|
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::Subslice { .. } => (),
|
| ProjectionElem::Subslice { .. } => (),
|
||||||
}
|
}
|
||||||
|
@ -321,8 +321,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let place_builder =
|
let place_builder =
|
||||||
unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
|
unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
|
||||||
|
|
||||||
if let Ok(place_builder_resolved) = place_builder.try_upvars_resolved(this) {
|
if let Ok(place_builder_resolved) =
|
||||||
let mir_place = place_builder_resolved.into_place(this);
|
place_builder.try_upvars_resolved(this.tcx, this.typeck_results)
|
||||||
|
{
|
||||||
|
let mir_place =
|
||||||
|
place_builder_resolved.into_place(this.tcx, this.typeck_results);
|
||||||
this.cfg.push_fake_read(
|
this.cfg.push_fake_read(
|
||||||
block,
|
block,
|
||||||
this.source_info(this.tcx.hir().span(*hir_id)),
|
this.source_info(this.tcx.hir().span(*hir_id)),
|
||||||
@ -613,7 +616,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// by the parent itself. The mutability of the current capture
|
// by the parent itself. The mutability of the current capture
|
||||||
// is same as that of the capture in the parent closure.
|
// is same as that of the capture in the parent closure.
|
||||||
PlaceBase::Upvar { .. } => {
|
PlaceBase::Upvar { .. } => {
|
||||||
let enclosing_upvars_resolved = arg_place_builder.clone().into_place(this);
|
let enclosing_upvars_resolved =
|
||||||
|
arg_place_builder.clone().into_place(this.tcx, this.typeck_results);
|
||||||
|
|
||||||
match enclosing_upvars_resolved.as_ref() {
|
match enclosing_upvars_resolved.as_ref() {
|
||||||
PlaceRef {
|
PlaceRef {
|
||||||
@ -650,7 +654,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
|
Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||||
};
|
};
|
||||||
|
|
||||||
let arg_place = arg_place_builder.into_place(this);
|
let arg_place = arg_place_builder.into_place(this.tcx, this.typeck_results);
|
||||||
|
|
||||||
this.cfg.push_assign(
|
this.cfg.push_assign(
|
||||||
block,
|
block,
|
||||||
|
@ -23,7 +23,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability))
|
ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
|
||||||
fn as_temp_inner(
|
fn as_temp_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut block: BasicBlock,
|
mut block: BasicBlock,
|
||||||
@ -31,6 +30,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
expr: &Expr<'tcx>,
|
expr: &Expr<'tcx>,
|
||||||
mutability: Mutability,
|
mutability: Mutability,
|
||||||
) -> BlockAnd<Local> {
|
) -> BlockAnd<Local> {
|
||||||
|
debug!(
|
||||||
|
"as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})",
|
||||||
|
block, temp_lifetime, expr, mutability
|
||||||
|
);
|
||||||
let this = self;
|
let this = self;
|
||||||
|
|
||||||
let expr_span = expr.span;
|
let expr_span = expr.span;
|
||||||
|
@ -15,13 +15,14 @@ use std::iter;
|
|||||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// Compile `expr`, storing the result into `destination`, which
|
/// Compile `expr`, storing the result into `destination`, which
|
||||||
/// is assumed to be uninitialized.
|
/// is assumed to be uninitialized.
|
||||||
#[instrument(level = "debug", skip(self))]
|
|
||||||
pub(crate) fn expr_into_dest(
|
pub(crate) fn expr_into_dest(
|
||||||
&mut self,
|
&mut self,
|
||||||
destination: Place<'tcx>,
|
destination: Place<'tcx>,
|
||||||
mut block: BasicBlock,
|
mut block: BasicBlock,
|
||||||
expr: &Expr<'tcx>,
|
expr: &Expr<'tcx>,
|
||||||
) -> BlockAnd<()> {
|
) -> BlockAnd<()> {
|
||||||
|
debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr);
|
||||||
|
|
||||||
// since we frequently have to reference `self` from within a
|
// since we frequently have to reference `self` from within a
|
||||||
// closure, where `self` would be shadowed, it's easier to
|
// closure, where `self` would be shadowed, it's easier to
|
||||||
// just use the name `this` uniformly
|
// just use the name `this` uniformly
|
||||||
@ -365,7 +366,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
None => {
|
None => {
|
||||||
let place_builder = place_builder.clone();
|
let place_builder = place_builder.clone();
|
||||||
this.consume_by_copy_or_move(
|
this.consume_by_copy_or_move(
|
||||||
place_builder.field(n, *ty).into_place(this),
|
place_builder
|
||||||
|
.field(n, *ty)
|
||||||
|
.into_place(this.tcx, this.typeck_results),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -220,8 +220,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let cause_matched_place = FakeReadCause::ForMatchedPlace(None);
|
let cause_matched_place = FakeReadCause::ForMatchedPlace(None);
|
||||||
let source_info = self.source_info(scrutinee_span);
|
let source_info = self.source_info(scrutinee_span);
|
||||||
|
|
||||||
if let Ok(scrutinee_builder) = scrutinee_place_builder.clone().try_upvars_resolved(self) {
|
if let Ok(scrutinee_builder) =
|
||||||
let scrutinee_place = scrutinee_builder.into_place(self);
|
scrutinee_place_builder.clone().try_upvars_resolved(self.tcx, self.typeck_results)
|
||||||
|
{
|
||||||
|
let scrutinee_place = scrutinee_builder.into_place(self.tcx, self.typeck_results);
|
||||||
self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
|
self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,10 +348,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// ```
|
// ```
|
||||||
let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None;
|
let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None;
|
||||||
let scrutinee_place: Place<'tcx>;
|
let scrutinee_place: Place<'tcx>;
|
||||||
if let Ok(scrutinee_builder) =
|
if let Ok(scrutinee_builder) = scrutinee_place_builder
|
||||||
scrutinee_place_builder.clone().try_upvars_resolved(this)
|
.clone()
|
||||||
|
.try_upvars_resolved(this.tcx, this.typeck_results)
|
||||||
{
|
{
|
||||||
scrutinee_place = scrutinee_builder.into_place(this);
|
scrutinee_place =
|
||||||
|
scrutinee_builder.into_place(this.tcx, this.typeck_results);
|
||||||
opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span));
|
opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span));
|
||||||
}
|
}
|
||||||
let scope = this.declare_bindings(
|
let scope = this.declare_bindings(
|
||||||
@ -598,6 +602,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
while let Some(next) = {
|
while let Some(next) = {
|
||||||
for binding in &candidate_ref.bindings {
|
for binding in &candidate_ref.bindings {
|
||||||
let local = self.var_local_id(binding.var_id, OutsideGuard);
|
let local = self.var_local_id(binding.var_id, OutsideGuard);
|
||||||
|
|
||||||
|
let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||||
|
VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
|
||||||
|
)))) = self.local_decls[local].local_info else {
|
||||||
|
bug!("Let binding to non-user variable.")
|
||||||
|
};
|
||||||
// `try_upvars_resolved` may fail if it is unable to resolve the given
|
// `try_upvars_resolved` may fail if it is unable to resolve the given
|
||||||
// `PlaceBuilder` inside a closure. In this case, we don't want to include
|
// `PlaceBuilder` inside a closure. In this case, we don't want to include
|
||||||
// a scrutinee place. `scrutinee_place_builder` will fail for destructured
|
// a scrutinee place. `scrutinee_place_builder` will fail for destructured
|
||||||
@ -612,15 +622,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// let (v1, v2) = foo;
|
// let (v1, v2) = foo;
|
||||||
// };
|
// };
|
||||||
// ```
|
// ```
|
||||||
if let Ok(match_pair_resolved) = initializer.clone().try_upvars_resolved(self) {
|
if let Ok(match_pair_resolved) =
|
||||||
let place = match_pair_resolved.into_place(self);
|
initializer.clone().try_upvars_resolved(self.tcx, self.typeck_results)
|
||||||
|
{
|
||||||
let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
let place = match_pair_resolved.into_place(self.tcx, self.typeck_results);
|
||||||
VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
|
|
||||||
)))) = self.local_decls[local].local_info else {
|
|
||||||
bug!("Let binding to non-user variable.")
|
|
||||||
};
|
|
||||||
|
|
||||||
*match_place = Some(place);
|
*match_place = Some(place);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -649,7 +654,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
/// scope for the bindings in these patterns, if such a scope had to be
|
/// scope for the bindings in these patterns, if such a scope had to be
|
||||||
/// created. NOTE: Declaring the bindings should always be done in their
|
/// created. NOTE: Declaring the bindings should always be done in their
|
||||||
/// drop scope.
|
/// drop scope.
|
||||||
#[instrument(skip(self), level = "debug")]
|
|
||||||
pub(crate) fn declare_bindings(
|
pub(crate) fn declare_bindings(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut visibility_scope: Option<SourceScope>,
|
mut visibility_scope: Option<SourceScope>,
|
||||||
@ -658,6 +662,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
has_guard: ArmHasGuard,
|
has_guard: ArmHasGuard,
|
||||||
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
|
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
|
||||||
) -> Option<SourceScope> {
|
) -> Option<SourceScope> {
|
||||||
|
debug!("declare_bindings: pattern={:?}", pattern);
|
||||||
self.visit_primary_bindings(
|
self.visit_primary_bindings(
|
||||||
&pattern,
|
&pattern,
|
||||||
UserTypeProjections::none(),
|
UserTypeProjections::none(),
|
||||||
@ -867,7 +872,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
|
|||||||
Candidate {
|
Candidate {
|
||||||
span: pattern.span,
|
span: pattern.span,
|
||||||
has_guard,
|
has_guard,
|
||||||
match_pairs: smallvec![MatchPair::new(place, pattern)],
|
match_pairs: smallvec![MatchPair { place, pattern }],
|
||||||
bindings: Vec::new(),
|
bindings: Vec::new(),
|
||||||
ascriptions: Vec::new(),
|
ascriptions: Vec::new(),
|
||||||
subcandidates: Vec::new(),
|
subcandidates: Vec::new(),
|
||||||
@ -1043,7 +1048,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
/// if `x.0` matches `false` (for the third arm). In the (impossible at
|
/// if `x.0` matches `false` (for the third arm). In the (impossible at
|
||||||
/// runtime) case when `x.0` is now `true`, we branch to
|
/// runtime) case when `x.0` is now `true`, we branch to
|
||||||
/// `otherwise_block`.
|
/// `otherwise_block`.
|
||||||
#[instrument(skip(self, fake_borrows), level = "debug")]
|
|
||||||
fn match_candidates<'pat>(
|
fn match_candidates<'pat>(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -1053,6 +1057,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
candidates: &mut [&mut Candidate<'pat, 'tcx>],
|
candidates: &mut [&mut Candidate<'pat, 'tcx>],
|
||||||
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
|
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
|
||||||
) {
|
) {
|
||||||
|
debug!(
|
||||||
|
"matched_candidate(span={:?}, candidates={:?}, start_block={:?}, otherwise_block={:?})",
|
||||||
|
span, candidates, start_block, otherwise_block,
|
||||||
|
);
|
||||||
|
|
||||||
// Start by simplifying candidates. Once this process is complete, all
|
// Start by simplifying candidates. Once this process is complete, all
|
||||||
// the match pairs which remain require some form of test, whether it
|
// the match pairs which remain require some form of test, whether it
|
||||||
// be a switch or pattern comparison.
|
// be a switch or pattern comparison.
|
||||||
@ -1371,10 +1380,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(
|
|
||||||
skip(self, otherwise, or_span, place, fake_borrows, candidate, pats),
|
|
||||||
level = "debug"
|
|
||||||
)]
|
|
||||||
fn test_or_pattern<'pat>(
|
fn test_or_pattern<'pat>(
|
||||||
&mut self,
|
&mut self,
|
||||||
candidate: &mut Candidate<'pat, 'tcx>,
|
candidate: &mut Candidate<'pat, 'tcx>,
|
||||||
@ -1384,7 +1389,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
place: PlaceBuilder<'tcx>,
|
place: PlaceBuilder<'tcx>,
|
||||||
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
|
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
|
||||||
) {
|
) {
|
||||||
debug!("candidate={:#?}\npats={:#?}", candidate, pats);
|
debug!("test_or_pattern:\ncandidate={:#?}\npats={:#?}", candidate, pats);
|
||||||
let mut or_candidates: Vec<_> = pats
|
let mut or_candidates: Vec<_> = pats
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard))
|
.map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard))
|
||||||
@ -1600,9 +1605,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
|
|
||||||
// Insert a Shallow borrow of any places that is switched on.
|
// Insert a Shallow borrow of any places that is switched on.
|
||||||
if let Some(fb) = fake_borrows && let Ok(match_place_resolved) =
|
if let Some(fb) = fake_borrows && let Ok(match_place_resolved) =
|
||||||
match_place.clone().try_upvars_resolved(self)
|
match_place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
|
||||||
{
|
{
|
||||||
let resolved_place = match_place_resolved.into_place(self);
|
let resolved_place = match_place_resolved.into_place(self.tcx, self.typeck_results);
|
||||||
fb.insert(resolved_place);
|
fb.insert(resolved_place);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1629,14 +1634,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
candidates = rest;
|
candidates = rest;
|
||||||
}
|
}
|
||||||
// at least the first candidate ought to be tested
|
// at least the first candidate ought to be tested
|
||||||
assert!(
|
assert!(total_candidate_count > candidates.len());
|
||||||
total_candidate_count > candidates.len(),
|
debug!("test_candidates: tested_candidates: {}", total_candidate_count - candidates.len());
|
||||||
"{}, {:#?}",
|
debug!("test_candidates: untested_candidates: {}", candidates.len());
|
||||||
total_candidate_count,
|
|
||||||
candidates
|
|
||||||
);
|
|
||||||
debug!("tested_candidates: {}", total_candidate_count - candidates.len());
|
|
||||||
debug!("untested_candidates: {}", candidates.len());
|
|
||||||
|
|
||||||
// HACK(matthewjasper) This is a closure so that we can let the test
|
// HACK(matthewjasper) This is a closure so that we can let the test
|
||||||
// create its blocks before the rest of the match. This currently
|
// create its blocks before the rest of the match. This currently
|
||||||
@ -1794,8 +1794,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
let mut opt_expr_place: Option<(Option<&Place<'tcx>>, Span)> = None;
|
let mut opt_expr_place: Option<(Option<&Place<'tcx>>, Span)> = None;
|
||||||
let expr_place: Place<'tcx>;
|
let expr_place: Place<'tcx>;
|
||||||
if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self) {
|
if let Ok(expr_builder) =
|
||||||
expr_place = expr_builder.into_place(self);
|
expr_place_builder.try_upvars_resolved(self.tcx, self.typeck_results)
|
||||||
|
{
|
||||||
|
expr_place = expr_builder.into_place(self.tcx, self.typeck_results);
|
||||||
opt_expr_place = Some((Some(&expr_place), expr_span));
|
opt_expr_place = Some((Some(&expr_place), expr_span));
|
||||||
}
|
}
|
||||||
let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
|
let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
|
||||||
@ -2193,7 +2195,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
/// first local is a binding for occurrences of `var` in the guard, which
|
/// first local is a binding for occurrences of `var` in the guard, which
|
||||||
/// will have type `&T`. The second local is a binding for occurrences of
|
/// will have type `&T`. The second local is a binding for occurrences of
|
||||||
/// `var` in the arm body, which will have type `T`.
|
/// `var` in the arm body, which will have type `T`.
|
||||||
#[instrument(skip(self), level = "debug")]
|
|
||||||
fn declare_binding(
|
fn declare_binding(
|
||||||
&mut self,
|
&mut self,
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
@ -2208,12 +2209,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
|
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
|
||||||
pat_span: Span,
|
pat_span: Span,
|
||||||
) {
|
) {
|
||||||
|
debug!(
|
||||||
|
"declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
|
||||||
|
visibility_scope={:?}, source_info={:?})",
|
||||||
|
var_id, name, mode, var_ty, visibility_scope, source_info
|
||||||
|
);
|
||||||
|
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope };
|
let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope };
|
||||||
let binding_mode = match mode {
|
let binding_mode = match mode {
|
||||||
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability),
|
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability),
|
||||||
BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability),
|
BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability),
|
||||||
};
|
};
|
||||||
|
debug!("declare_binding: user_ty={:?}", user_ty);
|
||||||
let local = LocalDecl::<'tcx> {
|
let local = LocalDecl::<'tcx> {
|
||||||
mutability,
|
mutability,
|
||||||
ty: var_ty,
|
ty: var_ty,
|
||||||
@ -2263,7 +2271,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
LocalsForNode::One(for_arm_body)
|
LocalsForNode::One(for_arm_body)
|
||||||
};
|
};
|
||||||
debug!(?locals);
|
debug!("declare_binding: vars={:?}", locals);
|
||||||
self.var_indices.insert(var_id, locals);
|
self.var_indices.insert(var_id, locals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,13 +37,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
///
|
///
|
||||||
/// only generates a single switch. If this happens this method returns
|
/// only generates a single switch. If this happens this method returns
|
||||||
/// `true`.
|
/// `true`.
|
||||||
#[instrument(skip(self, candidate), level = "debug")]
|
|
||||||
pub(super) fn simplify_candidate<'pat>(
|
pub(super) fn simplify_candidate<'pat>(
|
||||||
&mut self,
|
&mut self,
|
||||||
candidate: &mut Candidate<'pat, 'tcx>,
|
candidate: &mut Candidate<'pat, 'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// repeatedly simplify match pairs until fixed point is reached
|
// repeatedly simplify match pairs until fixed point is reached
|
||||||
debug!("{:#?}", candidate);
|
debug!(?candidate, "simplify_candidate");
|
||||||
|
|
||||||
// existing_bindings and new_bindings exists to keep the semantics in order.
|
// existing_bindings and new_bindings exists to keep the semantics in order.
|
||||||
// Reversing the binding order for bindings after `@` changes the binding order in places
|
// Reversing the binding order for bindings after `@` changes the binding order in places
|
||||||
@ -156,10 +155,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
ascription: thir::Ascription { ref annotation, variance },
|
ascription: thir::Ascription { ref annotation, variance },
|
||||||
} => {
|
} => {
|
||||||
// Apply the type ascription to the value at `match_pair.place`, which is the
|
// Apply the type ascription to the value at `match_pair.place`, which is the
|
||||||
if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
|
if let Ok(place_resolved) =
|
||||||
|
match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
|
||||||
|
{
|
||||||
candidate.ascriptions.push(Ascription {
|
candidate.ascriptions.push(Ascription {
|
||||||
annotation: annotation.clone(),
|
annotation: annotation.clone(),
|
||||||
source: place_resolved.into_place(self),
|
source: place_resolved.into_place(self.tcx, self.typeck_results),
|
||||||
variance,
|
variance,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -183,10 +184,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
ref subpattern,
|
ref subpattern,
|
||||||
is_primary: _,
|
is_primary: _,
|
||||||
} => {
|
} => {
|
||||||
if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
|
if let Ok(place_resolved) =
|
||||||
|
match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
|
||||||
|
{
|
||||||
candidate.bindings.push(Binding {
|
candidate.bindings.push(Binding {
|
||||||
span: match_pair.pattern.span,
|
span: match_pair.pattern.span,
|
||||||
source: place_resolved.into_place(self),
|
source: place_resolved.into_place(self.tcx, self.typeck_results),
|
||||||
var_id: var,
|
var_id: var,
|
||||||
binding_mode: mode,
|
binding_mode: mode,
|
||||||
});
|
});
|
||||||
|
@ -144,7 +144,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self, make_target_blocks, place_builder), level = "debug")]
|
|
||||||
pub(super) fn perform_test(
|
pub(super) fn perform_test(
|
||||||
&mut self,
|
&mut self,
|
||||||
match_start_span: Span,
|
match_start_span: Span,
|
||||||
@ -154,9 +153,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
test: &Test<'tcx>,
|
test: &Test<'tcx>,
|
||||||
make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
|
make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
|
||||||
) {
|
) {
|
||||||
let place = place_builder.into_place(self);
|
let place: Place<'tcx>;
|
||||||
let place_ty = place.ty(&self.local_decls, self.tcx);
|
if let Ok(test_place_builder) =
|
||||||
debug!(?place, ?place_ty,);
|
place_builder.try_upvars_resolved(self.tcx, self.typeck_results)
|
||||||
|
{
|
||||||
|
place = test_place_builder.into_place(self.tcx, self.typeck_results);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debug!(
|
||||||
|
"perform_test({:?}, {:?}: {:?}, {:?})",
|
||||||
|
block,
|
||||||
|
place,
|
||||||
|
place.ty(&self.local_decls, self.tcx),
|
||||||
|
test
|
||||||
|
);
|
||||||
|
|
||||||
let source_info = self.source_info(test.span);
|
let source_info = self.source_info(test.span);
|
||||||
match test.kind {
|
match test.kind {
|
||||||
@ -724,7 +735,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
|
// So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
|
||||||
// we want to create a set of derived match-patterns like
|
// we want to create a set of derived match-patterns like
|
||||||
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
|
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
|
||||||
let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)`
|
let elem =
|
||||||
|
ProjectionElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index);
|
||||||
|
let downcast_place = match_pair.place.project(elem); // `(x as Variant)`
|
||||||
let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
|
let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
|
||||||
// e.g., `(x as Variant).0`
|
// e.g., `(x as Variant).0`
|
||||||
let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty);
|
let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty);
|
||||||
|
@ -31,9 +31,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
suffix: &'pat [Pat<'tcx>],
|
suffix: &'pat [Pat<'tcx>],
|
||||||
) {
|
) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let (min_length, exact_size) =
|
let (min_length, exact_size) = if let Ok(place_resolved) =
|
||||||
if let Ok(place_resolved) = place.clone().try_upvars_resolved(self) {
|
place.clone().try_upvars_resolved(tcx, self.typeck_results)
|
||||||
match place_resolved.into_place(self).ty(&self.local_decls, tcx).ty.kind() {
|
{
|
||||||
|
match place_resolved
|
||||||
|
.into_place(tcx, self.typeck_results)
|
||||||
|
.ty(&self.local_decls, tcx)
|
||||||
|
.ty
|
||||||
|
.kind()
|
||||||
|
{
|
||||||
ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
|
ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
|
||||||
_ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
|
_ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
|
||||||
}
|
}
|
||||||
@ -94,14 +100,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||||
pub(in crate::build) fn new(
|
pub(crate) fn new(
|
||||||
place: PlaceBuilder<'tcx>,
|
place: PlaceBuilder<'tcx>,
|
||||||
pattern: &'pat Pat<'tcx>,
|
pattern: &'pat Pat<'tcx>,
|
||||||
) -> MatchPair<'pat, 'tcx> {
|
) -> MatchPair<'pat, 'tcx> {
|
||||||
// Force the place type to the pattern's type.
|
|
||||||
// FIXME(oli-obk): only do this when we don't already know the place type.
|
|
||||||
// FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
|
|
||||||
let place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
|
|
||||||
MatchPair { place, pattern }
|
MatchPair { place, pattern }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,7 +553,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
|
|
||||||
/// Convenience wrapper that pushes a scope and then executes `f`
|
/// Convenience wrapper that pushes a scope and then executes `f`
|
||||||
/// to build its contents, popping the scope afterwards.
|
/// to build its contents, popping the scope afterwards.
|
||||||
#[instrument(skip(self, f), level = "debug")]
|
|
||||||
pub(crate) fn in_scope<F, R>(
|
pub(crate) fn in_scope<F, R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
region_scope: (region::Scope, SourceInfo),
|
region_scope: (region::Scope, SourceInfo),
|
||||||
@ -563,6 +562,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
where
|
where
|
||||||
F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>,
|
F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>,
|
||||||
{
|
{
|
||||||
|
debug!("in_scope(region_scope={:?})", region_scope);
|
||||||
let source_scope = self.source_scope;
|
let source_scope = self.source_scope;
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
if let LintLevel::Explicit(current_hir_id) = lint_level {
|
if let LintLevel::Explicit(current_hir_id) = lint_level {
|
||||||
@ -589,7 +589,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let rv = unpack!(block = f(self));
|
let rv = unpack!(block = f(self));
|
||||||
unpack!(block = self.pop_scope(region_scope, block));
|
unpack!(block = self.pop_scope(region_scope, block));
|
||||||
self.source_scope = source_scope;
|
self.source_scope = source_scope;
|
||||||
debug!(?block);
|
debug!("in_scope: exiting region_scope={:?} block={:?}", region_scope, block);
|
||||||
block.and(rv)
|
block.and(rv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,8 +48,6 @@ impl<'tcx> Cx<'tcx> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
trace!(?expr.ty);
|
|
||||||
|
|
||||||
// Now apply adjustments, if any.
|
// Now apply adjustments, if any.
|
||||||
for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
|
for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
|
||||||
trace!(?expr, ?adjustment);
|
trace!(?expr, ?adjustment);
|
||||||
@ -58,8 +56,6 @@ impl<'tcx> Cx<'tcx> {
|
|||||||
self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span));
|
self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span));
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(?expr.ty, "after adjustments");
|
|
||||||
|
|
||||||
// Next, wrap this up in the expr's scope.
|
// Next, wrap this up in the expr's scope.
|
||||||
expr = Expr {
|
expr = Expr {
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
|
@ -1202,32 +1202,35 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
|
|||||||
|
|
||||||
/// Creates a new list of wildcard fields for a given constructor. The result must have a
|
/// Creates a new list of wildcard fields for a given constructor. The result must have a
|
||||||
/// length of `constructor.arity()`.
|
/// length of `constructor.arity()`.
|
||||||
#[instrument(level = "trace")]
|
pub(super) fn wildcards(
|
||||||
pub(super) fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self {
|
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
constructor: &Constructor<'tcx>,
|
||||||
|
) -> Self {
|
||||||
let ret = match constructor {
|
let ret = match constructor {
|
||||||
Single | Variant(_) => match pcx.ty.kind() {
|
Single | Variant(_) => match ty.kind() {
|
||||||
ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter()),
|
ty::Tuple(fs) => Fields::wildcards_from_tys(cx, fs.iter()),
|
||||||
ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty)),
|
ty::Ref(_, rty, _) => Fields::wildcards_from_tys(cx, once(*rty)),
|
||||||
ty::Adt(adt, substs) => {
|
ty::Adt(adt, substs) => {
|
||||||
if adt.is_box() {
|
if adt.is_box() {
|
||||||
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
// The only legal patterns of type `Box` (outside `std`) are `_` and box
|
||||||
// patterns. If we're here we can assume this is a box pattern.
|
// patterns. If we're here we can assume this is a box pattern.
|
||||||
Fields::wildcards_from_tys(pcx.cx, once(substs.type_at(0)))
|
Fields::wildcards_from_tys(cx, once(substs.type_at(0)))
|
||||||
} else {
|
} else {
|
||||||
let variant = &adt.variant(constructor.variant_index_for_adt(*adt));
|
let variant = &adt.variant(constructor.variant_index_for_adt(*adt));
|
||||||
let tys = Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant)
|
let tys = Fields::list_variant_nonhidden_fields(cx, ty, variant)
|
||||||
.map(|(_, ty)| ty);
|
.map(|(_, ty)| ty);
|
||||||
Fields::wildcards_from_tys(pcx.cx, tys)
|
Fields::wildcards_from_tys(cx, tys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => bug!("Unexpected type for `Single` constructor: {:?}", pcx),
|
_ => bug!("Unexpected type for `Single` constructor: {:?}", ty),
|
||||||
},
|
},
|
||||||
Slice(slice) => match *pcx.ty.kind() {
|
Slice(slice) => match *ty.kind() {
|
||||||
ty::Slice(ty) | ty::Array(ty, _) => {
|
ty::Slice(ty) | ty::Array(ty, _) => {
|
||||||
let arity = slice.arity();
|
let arity = slice.arity();
|
||||||
Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty))
|
Fields::wildcards_from_tys(cx, (0..arity).map(|_| ty))
|
||||||
}
|
}
|
||||||
_ => bug!("bad slice pattern {:?} {:?}", constructor, pcx),
|
_ => bug!("bad slice pattern {:?} {:?}", constructor, ty),
|
||||||
},
|
},
|
||||||
Str(..)
|
Str(..)
|
||||||
| FloatRange(..)
|
| FloatRange(..)
|
||||||
@ -1240,7 +1243,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
|
|||||||
bug!("called `Fields::wildcards` on an `Or` ctor")
|
bug!("called `Fields::wildcards` on an `Or` ctor")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
debug!(?ret);
|
debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1283,7 +1286,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
/// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
|
/// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
|
||||||
/// `Some(_)`.
|
/// `Some(_)`.
|
||||||
pub(super) fn wild_from_ctor(pcx: PatCtxt<'_, 'p, 'tcx>, ctor: Constructor<'tcx>) -> Self {
|
pub(super) fn wild_from_ctor(pcx: PatCtxt<'_, 'p, 'tcx>, ctor: Constructor<'tcx>) -> Self {
|
||||||
let fields = Fields::wildcards(pcx, &ctor);
|
let fields = Fields::wildcards(pcx.cx, pcx.ty, &ctor);
|
||||||
DeconstructedPat::new(ctor, fields, pcx.ty, DUMMY_SP)
|
DeconstructedPat::new(ctor, fields, pcx.ty, DUMMY_SP)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1550,13 +1553,13 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
/// `other_ctor` can be different from `self.ctor`, but must be covered by it.
|
/// `other_ctor` can be different from `self.ctor`, but must be covered by it.
|
||||||
pub(super) fn specialize<'a>(
|
pub(super) fn specialize<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
pcx: PatCtxt<'_, 'p, 'tcx>,
|
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||||
other_ctor: &Constructor<'tcx>,
|
other_ctor: &Constructor<'tcx>,
|
||||||
) -> SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]> {
|
) -> SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]> {
|
||||||
match (&self.ctor, other_ctor) {
|
match (&self.ctor, other_ctor) {
|
||||||
(Wildcard, _) => {
|
(Wildcard, _) => {
|
||||||
// We return a wildcard for each field of `other_ctor`.
|
// We return a wildcard for each field of `other_ctor`.
|
||||||
Fields::wildcards(pcx, other_ctor).iter_patterns().collect()
|
Fields::wildcards(cx, self.ty, other_ctor).iter_patterns().collect()
|
||||||
}
|
}
|
||||||
(Slice(self_slice), Slice(other_slice))
|
(Slice(self_slice), Slice(other_slice))
|
||||||
if self_slice.arity() != other_slice.arity() =>
|
if self_slice.arity() != other_slice.arity() =>
|
||||||
@ -1575,7 +1578,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
|||||||
let prefix = &self.fields.fields[..prefix];
|
let prefix = &self.fields.fields[..prefix];
|
||||||
let suffix = &self.fields.fields[self_slice.arity() - suffix..];
|
let suffix = &self.fields.fields[self_slice.arity() - suffix..];
|
||||||
let wildcard: &_ =
|
let wildcard: &_ =
|
||||||
pcx.cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty));
|
cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty));
|
||||||
let extra_wildcards = other_slice.arity() - self_slice.arity();
|
let extra_wildcards = other_slice.arity() - self_slice.arity();
|
||||||
let extra_wildcards = (0..extra_wildcards).map(|_| wildcard);
|
let extra_wildcards = (0..extra_wildcards).map(|_| wildcard);
|
||||||
prefix.iter().chain(extra_wildcards).chain(suffix).collect()
|
prefix.iter().chain(extra_wildcards).chain(suffix).collect()
|
||||||
|
@ -196,7 +196,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
|
||||||
fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
|
fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
|
||||||
let mut ty = self.typeck_results.node_type(pat.hir_id);
|
let mut ty = self.typeck_results.node_type(pat.hir_id);
|
||||||
|
|
||||||
|
@ -411,12 +411,12 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
|
|||||||
/// This is roughly the inverse of `Constructor::apply`.
|
/// This is roughly the inverse of `Constructor::apply`.
|
||||||
fn pop_head_constructor(
|
fn pop_head_constructor(
|
||||||
&self,
|
&self,
|
||||||
pcx: PatCtxt<'_, 'p, 'tcx>,
|
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||||
ctor: &Constructor<'tcx>,
|
ctor: &Constructor<'tcx>,
|
||||||
) -> PatStack<'p, 'tcx> {
|
) -> PatStack<'p, 'tcx> {
|
||||||
// We pop the head pattern and push the new fields extracted from the arguments of
|
// We pop the head pattern and push the new fields extracted from the arguments of
|
||||||
// `self.head()`.
|
// `self.head()`.
|
||||||
let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(pcx, ctor);
|
let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(cx, ctor);
|
||||||
new_fields.extend_from_slice(&self.pats[1..]);
|
new_fields.extend_from_slice(&self.pats[1..]);
|
||||||
PatStack::from_vec(new_fields)
|
PatStack::from_vec(new_fields)
|
||||||
}
|
}
|
||||||
@ -475,7 +475,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
|
|||||||
let mut matrix = Matrix::empty();
|
let mut matrix = Matrix::empty();
|
||||||
for row in &self.patterns {
|
for row in &self.patterns {
|
||||||
if ctor.is_covered_by(pcx, row.head().ctor()) {
|
if ctor.is_covered_by(pcx, row.head().ctor()) {
|
||||||
let new_row = row.pop_head_constructor(pcx, ctor);
|
let new_row = row.pop_head_constructor(pcx.cx, ctor);
|
||||||
matrix.push(new_row);
|
matrix.push(new_row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -786,7 +786,7 @@ fn is_useful<'p, 'tcx>(
|
|||||||
is_under_guard: bool,
|
is_under_guard: bool,
|
||||||
is_top_level: bool,
|
is_top_level: bool,
|
||||||
) -> Usefulness<'p, 'tcx> {
|
) -> Usefulness<'p, 'tcx> {
|
||||||
debug!(?matrix, ?v);
|
debug!("matrix,v={:?}{:?}", matrix, v);
|
||||||
let Matrix { patterns: rows, .. } = matrix;
|
let Matrix { patterns: rows, .. } = matrix;
|
||||||
|
|
||||||
// The base case. We are pattern-matching on () and the return value is
|
// The base case. We are pattern-matching on () and the return value is
|
||||||
@ -806,6 +806,11 @@ fn is_useful<'p, 'tcx>(
|
|||||||
|
|
||||||
debug_assert!(rows.iter().all(|r| r.len() == v.len()));
|
debug_assert!(rows.iter().all(|r| r.len() == v.len()));
|
||||||
|
|
||||||
|
let ty = v.head().ty();
|
||||||
|
let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
|
||||||
|
debug!("v.head: {:?}, v.span: {:?}", v.head(), v.head().span());
|
||||||
|
let pcx = PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive };
|
||||||
|
|
||||||
// If the first pattern is an or-pattern, expand it.
|
// If the first pattern is an or-pattern, expand it.
|
||||||
let mut ret = Usefulness::new_not_useful(witness_preference);
|
let mut ret = Usefulness::new_not_useful(witness_preference);
|
||||||
if v.head().is_or_pat() {
|
if v.head().is_or_pat() {
|
||||||
@ -827,19 +832,6 @@ fn is_useful<'p, 'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut ty = v.head().ty();
|
|
||||||
|
|
||||||
// Opaque types can't get destructured/split, but the patterns can
|
|
||||||
// actually hint at hidden types, so we use the patterns' types instead.
|
|
||||||
if let ty::Opaque(..) = v.head().ty().kind() {
|
|
||||||
if let Some(row) = rows.first() {
|
|
||||||
ty = row.head().ty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
|
|
||||||
debug!("v.head: {:?}, v.span: {:?}", v.head(), v.head().span());
|
|
||||||
let pcx = PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive };
|
|
||||||
|
|
||||||
let v_ctor = v.head().ctor();
|
let v_ctor = v.head().ctor();
|
||||||
debug!(?v_ctor);
|
debug!(?v_ctor);
|
||||||
if let Constructor::IntRange(ctor_range) = &v_ctor {
|
if let Constructor::IntRange(ctor_range) = &v_ctor {
|
||||||
@ -861,7 +853,7 @@ fn is_useful<'p, 'tcx>(
|
|||||||
debug!("specialize({:?})", ctor);
|
debug!("specialize({:?})", ctor);
|
||||||
// We cache the result of `Fields::wildcards` because it is used a lot.
|
// We cache the result of `Fields::wildcards` because it is used a lot.
|
||||||
let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor);
|
let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor);
|
||||||
let v = v.pop_head_constructor(pcx, &ctor);
|
let v = v.pop_head_constructor(cx, &ctor);
|
||||||
let usefulness = ensure_sufficient_stack(|| {
|
let usefulness = ensure_sufficient_stack(|| {
|
||||||
is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false)
|
is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false)
|
||||||
});
|
});
|
||||||
|
@ -48,7 +48,6 @@ impl<'tcx> Lift for PlaceElem<'tcx> {
|
|||||||
match *self {
|
match *self {
|
||||||
ProjectionElem::Deref => ProjectionElem::Deref,
|
ProjectionElem::Deref => ProjectionElem::Deref,
|
||||||
ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, ty.lift()),
|
ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, ty.lift()),
|
||||||
ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty.lift()),
|
|
||||||
ProjectionElem::Index(ref i) => ProjectionElem::Index(i.lift()),
|
ProjectionElem::Index(ref i) => ProjectionElem::Index(i.lift()),
|
||||||
ProjectionElem::Subslice { from, to, from_end } => {
|
ProjectionElem::Subslice { from, to, from_end } => {
|
||||||
ProjectionElem::Subslice { from, to, from_end }
|
ProjectionElem::Subslice { from, to, from_end }
|
||||||
|
@ -28,7 +28,6 @@ fn is_stable(place: PlaceRef<'_>) -> bool {
|
|||||||
ProjectionElem::Field { .. } |
|
ProjectionElem::Field { .. } |
|
||||||
ProjectionElem::ConstantIndex { .. } |
|
ProjectionElem::ConstantIndex { .. } |
|
||||||
ProjectionElem::Subslice { .. } |
|
ProjectionElem::Subslice { .. } |
|
||||||
ProjectionElem::OpaqueCast { .. } |
|
|
||||||
ProjectionElem::Downcast { .. } => true,
|
ProjectionElem::Downcast { .. } => true,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
// compile-flags: --edition=2021
|
// compile-flags: --edition=2021
|
||||||
// check-pass
|
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
type T = impl Copy;
|
type T = impl Copy; //~ ERROR unconstrained opaque type
|
||||||
let foo: T = (1u32, 2u32);
|
let foo: T = (1u32, 2u32);
|
||||||
let (a, b): (u32, u32) = foo;
|
let (a, b): (u32, u32) = foo;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
error: unconstrained opaque type
|
||||||
|
--> $DIR/cross_inference_pattern_bug.rs:5:14
|
||||||
|
|
|
||||||
|
LL | type T = impl Copy;
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `T` must be used in combination with a concrete type within the same module
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
@ -1,13 +1,13 @@
|
|||||||
|
// known-bug: #96572
|
||||||
// compile-flags: --edition=2021 --crate-type=lib
|
// compile-flags: --edition=2021 --crate-type=lib
|
||||||
// rustc-env:RUST_BACKTRACE=0
|
// rustc-env:RUST_BACKTRACE=0
|
||||||
// check-pass
|
|
||||||
|
|
||||||
// tracked in https://github.com/rust-lang/rust/issues/96572
|
// tracked in https://github.com/rust-lang/rust/issues/96572
|
||||||
|
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
type T = impl Copy;
|
type T = impl Copy; // error: unconstrained opaque type
|
||||||
let foo: T = (1u32, 2u32);
|
let foo: T = (1u32, 2u32);
|
||||||
let (a, b) = foo; // this line used to make the code fail
|
let (a, b) = foo; // removing this line makes the code compile
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
error: unconstrained opaque type
|
||||||
|
--> $DIR/cross_inference_pattern_bug_no_type.rs:10:14
|
||||||
|
|
|
||||||
|
LL | type T = impl Copy; // error: unconstrained opaque type
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `T` must be used in combination with a concrete type within the same module
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
@ -1,10 +0,0 @@
|
|||||||
#![feature(type_alias_impl_trait)]
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
type T = impl Copy;
|
|
||||||
let foo: T = Some((1u32, 2u32));
|
|
||||||
match foo {
|
|
||||||
None => (),
|
|
||||||
Some((a, b, c)) => (), //~ ERROR mismatched types
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
error[E0308]: mismatched types
|
|
||||||
--> $DIR/issue-96572-unconstrained-mismatch.rs:8:14
|
|
||||||
|
|
|
||||||
LL | match foo {
|
|
||||||
| --- this expression has type `T`
|
|
||||||
LL | None => (),
|
|
||||||
LL | Some((a, b, c)) => (),
|
|
||||||
| ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
|
|
||||||
|
|
|
||||||
= note: expected tuple `(u32, u32)`
|
|
||||||
found tuple `(_, _, _)`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -1,29 +0,0 @@
|
|||||||
// check-pass
|
|
||||||
|
|
||||||
#[allow(unconditional_recursion)]
|
|
||||||
fn foo(b: bool) -> impl Copy {
|
|
||||||
let (mut x, mut y) = foo(false);
|
|
||||||
x = 42;
|
|
||||||
y = "foo";
|
|
||||||
if b {
|
|
||||||
panic!()
|
|
||||||
} else {
|
|
||||||
foo(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bar(b: bool) -> Option<impl Copy> {
|
|
||||||
if b {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
match bar(!b) {
|
|
||||||
Some((mut x, mut y)) => {
|
|
||||||
x = 42;
|
|
||||||
y = "foo";
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -1,24 +0,0 @@
|
|||||||
#![feature(type_alias_impl_trait)]
|
|
||||||
// check-pass
|
|
||||||
|
|
||||||
type T = impl Copy;
|
|
||||||
|
|
||||||
fn foo(foo: T) {
|
|
||||||
let (mut x, mut y) = foo;
|
|
||||||
x = 42;
|
|
||||||
y = "foo";
|
|
||||||
}
|
|
||||||
|
|
||||||
type U = impl Copy;
|
|
||||||
|
|
||||||
fn bar(bar: Option<U>) {
|
|
||||||
match bar {
|
|
||||||
Some((mut x, mut y)) => {
|
|
||||||
x = 42;
|
|
||||||
y = "foo";
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -1,11 +0,0 @@
|
|||||||
#![feature(type_alias_impl_trait)]
|
|
||||||
// check-pass
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
struct Foo((u32, u32));
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
type U = impl Copy;
|
|
||||||
let foo: U = Foo((1u32, 2u32));
|
|
||||||
let Foo((a, b)) = foo;
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
#![feature(type_alias_impl_trait)]
|
|
||||||
// check-pass
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
type T = impl Copy;
|
|
||||||
let foo: T = Some((1u32, 2u32));
|
|
||||||
let x = move || {
|
|
||||||
match foo {
|
|
||||||
None => (),
|
|
||||||
Some((a, b)) => (),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
#![feature(type_alias_impl_trait)]
|
|
||||||
// check-pass
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
struct Foo((u32, u32));
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
type T = impl Copy;
|
|
||||||
let foo: T = Foo((1u32, 2u32));
|
|
||||||
let x = move || {
|
|
||||||
let Foo((a, b)) = foo;
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
#![feature(type_alias_impl_trait)]
|
|
||||||
// check-pass
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
type T = impl Copy;
|
|
||||||
let foo: T = Some((1u32, 2u32));
|
|
||||||
match foo {
|
|
||||||
None => (),
|
|
||||||
Some((a, b)) => (),
|
|
||||||
}
|
|
||||||
}
|
|
@ -252,7 +252,6 @@ fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &B
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ProjectionElem::ConstantIndex { .. }
|
ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::OpaqueCast(..)
|
|
||||||
| ProjectionElem::Downcast(..)
|
| ProjectionElem::Downcast(..)
|
||||||
| ProjectionElem::Subslice { .. }
|
| ProjectionElem::Subslice { .. }
|
||||||
| ProjectionElem::Deref
|
| ProjectionElem::Deref
|
||||||
|
Loading…
Reference in New Issue
Block a user