Perform OpaqueCast field projection on HIR, too.
This is necessary for closure captures in 2021 edition, as they capture individual fields, not the full mentioned variables. So it may try to capture a field of an opaque (because the hidden type is known to be something with a field).
This commit is contained in:
parent
d14569bd64
commit
e390dc9c36
8 changed files with 30 additions and 0 deletions
|
@ -457,7 +457,16 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
|||
ty: Ty<'tcx>,
|
||||
kind: ProjectionKind,
|
||||
) -> PlaceWithHirId<'tcx> {
|
||||
let place_ty = base_place.place.ty();
|
||||
let mut projections = base_place.place.projections;
|
||||
|
||||
let node_ty = self.typeck_results.node_type(node.hir_id());
|
||||
// Opaque types can't have field projections, but we can instead convert
|
||||
// the current place in-place (heh) to the hidden type, and then apply all
|
||||
// follow up projections on that.
|
||||
if node_ty != place_ty && place_ty.has_opaque_types() {
|
||||
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
|
||||
}
|
||||
projections.push(Projection { kind, ty });
|
||||
PlaceWithHirId::new(
|
||||
node.hir_id(),
|
||||
|
|
|
@ -673,6 +673,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
match (p1.kind, p2.kind) {
|
||||
// Paths are the same, continue to next loop.
|
||||
(ProjectionKind::Deref, ProjectionKind::Deref) => {}
|
||||
(ProjectionKind::OpaqueCast, ProjectionKind::OpaqueCast) => {}
|
||||
(ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _))
|
||||
if i1 == i2 => {}
|
||||
|
||||
|
@ -695,10 +696,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
l @ (ProjectionKind::Index
|
||||
| ProjectionKind::Subslice
|
||||
| ProjectionKind::Deref
|
||||
| ProjectionKind::OpaqueCast
|
||||
| ProjectionKind::Field(..)),
|
||||
r @ (ProjectionKind::Index
|
||||
| ProjectionKind::Subslice
|
||||
| ProjectionKind::Deref
|
||||
| ProjectionKind::OpaqueCast
|
||||
| ProjectionKind::Field(..)),
|
||||
) => bug!(
|
||||
"ProjectionKinds Index or Subslice were unexpected: ({:?}, {:?})",
|
||||
|
@ -1885,6 +1888,7 @@ fn restrict_capture_precision(
|
|||
return (place, curr_mode);
|
||||
}
|
||||
ProjectionKind::Deref => {}
|
||||
ProjectionKind::OpaqueCast => {}
|
||||
ProjectionKind::Field(..) => {} // ignore
|
||||
}
|
||||
}
|
||||
|
@ -1941,6 +1945,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String
|
|||
ProjectionKind::Deref => String::from("Deref"),
|
||||
ProjectionKind::Index => String::from("Index"),
|
||||
ProjectionKind::Subslice => String::from("Subslice"),
|
||||
ProjectionKind::OpaqueCast => String::from("OpaqueCast"),
|
||||
};
|
||||
if i != 0 {
|
||||
projections_str.push(',');
|
||||
|
|
|
@ -36,6 +36,10 @@ pub enum ProjectionKind {
|
|||
|
||||
/// A subslice covering a range of values like `B[x..y]`.
|
||||
Subslice,
|
||||
|
||||
/// A conversion from an opaque type to its hidden type so we can
|
||||
/// do further projections on it.
|
||||
OpaqueCast,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
|
||||
|
|
|
@ -174,6 +174,8 @@ impl<'tcx> CapturedPlace<'tcx> {
|
|||
// Ignore derefs for now, as they are likely caused by
|
||||
// autoderefs that don't appear in the original code.
|
||||
HirProjectionKind::Deref => {}
|
||||
// Just change the type to the hidden type, so we can actually project.
|
||||
HirProjectionKind::OpaqueCast => {}
|
||||
proj => bug!("Unexpected projection {:?} in captured place", proj),
|
||||
}
|
||||
ty = proj.ty;
|
||||
|
|
|
@ -236,6 +236,9 @@ fn strip_prefix<'a, 'tcx>(
|
|||
}
|
||||
assert_matches!(iter.next(), Some(ProjectionElem::Field(..)));
|
||||
}
|
||||
HirProjectionKind::OpaqueCast => {
|
||||
assert_matches!(iter.next(), Some(ProjectionElem::OpaqueCast(..)));
|
||||
}
|
||||
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
||||
bug!("unexpected projection kind: {:?}", projection);
|
||||
}
|
||||
|
|
|
@ -1074,6 +1074,9 @@ impl<'tcx> Cx<'tcx> {
|
|||
variant_index,
|
||||
name: field,
|
||||
},
|
||||
HirProjectionKind::OpaqueCast => {
|
||||
ExprKind::Use { source: self.thir.exprs.push(captured_place_expr) }
|
||||
}
|
||||
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
||||
// We don't capture these projections, so we can ignore them here
|
||||
continue;
|
||||
|
|
|
@ -1011,6 +1011,8 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||
},
|
||||
// note: unable to trigger `Subslice` kind in tests
|
||||
ProjectionKind::Subslice => (),
|
||||
// Doesn't have surface syntax. Only occurs in patterns.
|
||||
ProjectionKind::OpaqueCast => (),
|
||||
ProjectionKind::Deref => {
|
||||
// Explicit derefs are typically handled later on, but
|
||||
// some items do not need explicit deref, such as array accesses,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
// check-pass
|
||||
// revisions: default edition2021
|
||||
//[edition2021] compile-flags: --edition 2021
|
||||
|
||||
fn main() {
|
||||
type T = impl Copy;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue