Revert "Revert "Rollup merge of #98582 - oli-obk:unconstrained_opaque_type, r=estebank""
This reverts commit 4a742a691e7dd2522bad68b86fe2fd5a199d5561.
This commit is contained in:
parent
5d664f7a8f
commit
40e2de8c41
@ -2146,7 +2146,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
StorageDeadOrDrop::Destructor(_) => kind,
|
StorageDeadOrDrop::Destructor(_) => kind,
|
||||||
},
|
},
|
||||||
ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
|
ProjectionElem::OpaqueCast { .. }
|
||||||
|
| 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
|
||||||
|
@ -237,6 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
ProjectionElem::Downcast(..) if opt.including_downcast => return None,
|
ProjectionElem::Downcast(..) if opt.including_downcast => 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 {
|
||||||
@ -317,6 +318,7 @@ 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,6 +169,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
..,
|
..,
|
||||||
ProjectionElem::Index(_)
|
ProjectionElem::Index(_)
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
|
| ProjectionElem::OpaqueCast { .. }
|
||||||
| ProjectionElem::Subslice { .. }
|
| ProjectionElem::Subslice { .. }
|
||||||
| ProjectionElem::Downcast(..),
|
| ProjectionElem::Downcast(..),
|
||||||
],
|
],
|
||||||
|
@ -1781,6 +1781,7 @@ 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*/) =>
|
||||||
@ -2172,6 +2173,7 @@ 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 {
|
||||||
|
@ -250,6 +250,7 @@ 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
|
||||||
@ -317,6 +318,17 @@ 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.
|
||||||
@ -520,6 +532,7 @@ 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,6 +81,7 @@ 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;
|
||||||
|
@ -760,6 +760,19 @@ 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1166,10 +1179,11 @@ 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;
|
||||||
}
|
}
|
||||||
@ -2501,6 +2515,7 @@ 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 { .. } => {
|
||||||
|
@ -850,6 +850,7 @@ pub(crate) fn codegen_place<'tcx>(
|
|||||||
PlaceElem::Deref => {
|
PlaceElem::Deref => {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -621,6 +621,14 @@ 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>,
|
||||||
|
@ -400,6 +400,21 @@ 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);
|
||||||
}
|
}
|
||||||
@ -442,6 +457,7 @@ 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);
|
||||||
|
@ -350,6 +350,11 @@ where
|
|||||||
) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> {
|
) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> {
|
||||||
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(),
|
||||||
@ -374,6 +379,11 @@ where
|
|||||||
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
||||||
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(),
|
||||||
|
@ -656,6 +656,7 @@ 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(_) => {}
|
||||||
|
@ -308,6 +308,7 @@ 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::Downcast(..) => {
|
ProjectionElem::OpaqueCast(..) | ProjectionElem::Downcast(..) => {
|
||||||
return Err(Unpromotable);
|
return Err(Unpromotable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1380,6 +1380,7 @@ 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,
|
||||||
@ -1574,7 +1575,9 @@ 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::Downcast(_, _) | ProjectionElem::Field(_, _) => {
|
ProjectionElem::OpaqueCast(_)
|
||||||
|
| ProjectionElem::Downcast(_, _)
|
||||||
|
| ProjectionElem::Field(_, _) => {
|
||||||
write!(fmt, "(").unwrap();
|
write!(fmt, "(").unwrap();
|
||||||
}
|
}
|
||||||
ProjectionElem::Deref => {
|
ProjectionElem::Deref => {
|
||||||
@ -1590,6 +1593,9 @@ 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)?;
|
||||||
}
|
}
|
||||||
|
@ -829,6 +829,9 @@ 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
|
||||||
@ -928,6 +931,10 @@ 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)
|
self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty, |_, ty| ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
|
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
|
||||||
@ -71,6 +71,7 @@ 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,
|
||||||
@ -109,6 +110,7 @@ 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
|
||||||
|
@ -1094,6 +1094,11 @@ 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 { .. }
|
||||||
@ -1163,7 +1168,7 @@ macro_rules! visit_place_fns {
|
|||||||
location: Location,
|
location: Location,
|
||||||
) {
|
) {
|
||||||
match elem {
|
match elem {
|
||||||
ProjectionElem::Field(_field, ty) => {
|
ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) => {
|
||||||
self.visit_ty(ty, TyContext::Location(location));
|
self.visit_ty(ty, TyContext::Location(location));
|
||||||
}
|
}
|
||||||
ProjectionElem::Index(local) => {
|
ProjectionElem::Index(local) => {
|
||||||
|
@ -102,6 +102,8 @@ 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 { .. } => {
|
||||||
@ -168,7 +170,7 @@ 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))]
|
#[instrument(level = "trace", skip(cx), ret)]
|
||||||
fn to_upvars_resolved_place_builder<'tcx>(
|
fn to_upvars_resolved_place_builder<'tcx>(
|
||||||
from_builder: PlaceBuilder<'tcx>,
|
from_builder: PlaceBuilder<'tcx>,
|
||||||
cx: &Builder<'_, 'tcx>,
|
cx: &Builder<'_, 'tcx>,
|
||||||
@ -213,7 +215,6 @@ fn to_upvars_resolved_place_builder<'tcx>(
|
|||||||
&capture.captured_place.place.projections,
|
&capture.captured_place.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)
|
||||||
}
|
}
|
||||||
@ -232,16 +233,21 @@ 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!(iter.next(), Some(ProjectionElem::Deref)));
|
assert!(matches!(next(), Some(ProjectionElem::Deref)));
|
||||||
}
|
}
|
||||||
HirProjectionKind::Field(..) => {
|
HirProjectionKind::Field(..) => {
|
||||||
if base_ty.is_enum() {
|
if base_ty.is_enum() {
|
||||||
assert!(matches!(iter.next(), Some(ProjectionElem::Downcast(..))));
|
assert!(matches!(next(), Some(ProjectionElem::Downcast(..))));
|
||||||
}
|
}
|
||||||
assert!(matches!(iter.next(), Some(ProjectionElem::Field(..))));
|
assert!(matches!(next(), Some(ProjectionElem::Field(..))));
|
||||||
}
|
}
|
||||||
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
||||||
bug!("unexpected projection kind: {:?}", projection);
|
bug!("unexpected projection kind: {:?}", projection);
|
||||||
@ -711,6 +717,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
ProjectionElem::Field(..)
|
ProjectionElem::Field(..)
|
||||||
| ProjectionElem::Downcast(..)
|
| ProjectionElem::Downcast(..)
|
||||||
|
| ProjectionElem::OpaqueCast(..)
|
||||||
| ProjectionElem::ConstantIndex { .. }
|
| ProjectionElem::ConstantIndex { .. }
|
||||||
| ProjectionElem::Subslice { .. } => (),
|
| ProjectionElem::Subslice { .. } => (),
|
||||||
}
|
}
|
||||||
|
@ -95,9 +95,14 @@ 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(in crate::build) fn new(
|
||||||
place: PlaceBuilder<'tcx>,
|
mut 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): can we use this to simplify slice/array pattern hacks?
|
||||||
|
// FIXME(oli-obk): only add this projection if `place` actually had an opaque
|
||||||
|
// type before the projection.
|
||||||
|
place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
|
||||||
MatchPair { place, pattern }
|
MatchPair { place, pattern }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -842,7 +842,15 @@ fn is_useful<'p, 'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let ty = v.head().ty();
|
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(..) = ty.kind() {
|
||||||
|
if let Some(row) = rows.first() {
|
||||||
|
ty = row.head().ty();
|
||||||
|
}
|
||||||
|
}
|
||||||
let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
|
let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
|
||||||
debug!("v.head: {:?}, v.span: {:?}", v.head(), v.head().span());
|
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 pcx = &PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive };
|
||||||
|
@ -48,6 +48,7 @@ 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 }
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// 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; //~ ERROR unconstrained opaque type
|
type T = impl Copy;
|
||||||
let foo: T = (1u32, 2u32);
|
let foo: T = (1u32, 2u32);
|
||||||
let (a, b): (u32, u32) = foo;
|
let (a, b): (u32, u32) = foo;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
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; // error: unconstrained opaque type
|
type T = impl Copy;
|
||||||
let foo: T = (1u32, 2u32);
|
let foo: T = (1u32, 2u32);
|
||||||
let (a, b) = foo; // removing this line makes the code compile
|
let (a, b) = foo; // this line used to make the code fail
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
|||||||
|
#![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
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
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`.
|
@ -0,0 +1,92 @@
|
|||||||
|
#![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)) => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn upvar() {
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct Foo((u32, u32));
|
||||||
|
|
||||||
|
type T = impl Copy;
|
||||||
|
let foo: T = Foo((1u32, 2u32));
|
||||||
|
let x = move || {
|
||||||
|
let Foo((a, b)) = foo;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enum_upvar() {
|
||||||
|
type T = impl Copy;
|
||||||
|
let foo: T = Some((1u32, 2u32));
|
||||||
|
let x = move || {
|
||||||
|
match foo {
|
||||||
|
None => (),
|
||||||
|
Some((a, b)) => (),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn r#struct() {
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct Foo((u32, u32));
|
||||||
|
|
||||||
|
type U = impl Copy;
|
||||||
|
let foo: U = Foo((1u32, 2u32));
|
||||||
|
let Foo((a, b)) = foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod only_pattern {
|
||||||
|
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 => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod only_pattern_rpit {
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
}
|
@ -260,6 +260,7 @@ 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…
x
Reference in New Issue
Block a user