Skip to content

Commit e390dc9

Browse files
committed
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).
1 parent d14569b commit e390dc9

File tree

8 files changed

+30
-0
lines changed

8 files changed

+30
-0
lines changed

compiler/rustc_hir_typeck/src/mem_categorization.rs

+9
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,16 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
457457
ty: Ty<'tcx>,
458458
kind: ProjectionKind,
459459
) -> PlaceWithHirId<'tcx> {
460+
let place_ty = base_place.place.ty();
460461
let mut projections = base_place.place.projections;
462+
463+
let node_ty = self.typeck_results.node_type(node.hir_id());
464+
// Opaque types can't have field projections, but we can instead convert
465+
// the current place in-place (heh) to the hidden type, and then apply all
466+
// follow up projections on that.
467+
if node_ty != place_ty && place_ty.has_opaque_types() {
468+
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
469+
}
461470
projections.push(Projection { kind, ty });
462471
PlaceWithHirId::new(
463472
node.hir_id(),

compiler/rustc_hir_typeck/src/upvar.rs

+5
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
673673
match (p1.kind, p2.kind) {
674674
// Paths are the same, continue to next loop.
675675
(ProjectionKind::Deref, ProjectionKind::Deref) => {}
676+
(ProjectionKind::OpaqueCast, ProjectionKind::OpaqueCast) => {}
676677
(ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _))
677678
if i1 == i2 => {}
678679

@@ -695,10 +696,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
695696
l @ (ProjectionKind::Index
696697
| ProjectionKind::Subslice
697698
| ProjectionKind::Deref
699+
| ProjectionKind::OpaqueCast
698700
| ProjectionKind::Field(..)),
699701
r @ (ProjectionKind::Index
700702
| ProjectionKind::Subslice
701703
| ProjectionKind::Deref
704+
| ProjectionKind::OpaqueCast
702705
| ProjectionKind::Field(..)),
703706
) => bug!(
704707
"ProjectionKinds Index or Subslice were unexpected: ({:?}, {:?})",
@@ -1885,6 +1888,7 @@ fn restrict_capture_precision(
18851888
return (place, curr_mode);
18861889
}
18871890
ProjectionKind::Deref => {}
1891+
ProjectionKind::OpaqueCast => {}
18881892
ProjectionKind::Field(..) => {} // ignore
18891893
}
18901894
}
@@ -1941,6 +1945,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String
19411945
ProjectionKind::Deref => String::from("Deref"),
19421946
ProjectionKind::Index => String::from("Index"),
19431947
ProjectionKind::Subslice => String::from("Subslice"),
1948+
ProjectionKind::OpaqueCast => String::from("OpaqueCast"),
19441949
};
19451950
if i != 0 {
19461951
projections_str.push(',');

compiler/rustc_middle/src/hir/place.rs

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ pub enum ProjectionKind {
3636

3737
/// A subslice covering a range of values like `B[x..y]`.
3838
Subslice,
39+
40+
/// A conversion from an opaque type to its hidden type so we can
41+
/// do further projections on it.
42+
OpaqueCast,
3943
}
4044

4145
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]

compiler/rustc_middle/src/ty/closure.rs

+2
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ impl<'tcx> CapturedPlace<'tcx> {
174174
// Ignore derefs for now, as they are likely caused by
175175
// autoderefs that don't appear in the original code.
176176
HirProjectionKind::Deref => {}
177+
// Just change the type to the hidden type, so we can actually project.
178+
HirProjectionKind::OpaqueCast => {}
177179
proj => bug!("Unexpected projection {:?} in captured place", proj),
178180
}
179181
ty = proj.ty;

compiler/rustc_mir_build/src/build/expr/as_place.rs

+3
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ fn strip_prefix<'a, 'tcx>(
236236
}
237237
assert_matches!(iter.next(), Some(ProjectionElem::Field(..)));
238238
}
239+
HirProjectionKind::OpaqueCast => {
240+
assert_matches!(iter.next(), Some(ProjectionElem::OpaqueCast(..)));
241+
}
239242
HirProjectionKind::Index | HirProjectionKind::Subslice => {
240243
bug!("unexpected projection kind: {:?}", projection);
241244
}

compiler/rustc_mir_build/src/thir/cx/expr.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,9 @@ impl<'tcx> Cx<'tcx> {
10741074
variant_index,
10751075
name: field,
10761076
},
1077+
HirProjectionKind::OpaqueCast => {
1078+
ExprKind::Use { source: self.thir.exprs.push(captured_place_expr) }
1079+
}
10771080
HirProjectionKind::Index | HirProjectionKind::Subslice => {
10781081
// We don't capture these projections, so we can ignore them here
10791082
continue;

src/tools/clippy/clippy_utils/src/sugg.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,8 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
10111011
},
10121012
// note: unable to trigger `Subslice` kind in tests
10131013
ProjectionKind::Subslice => (),
1014+
// Doesn't have surface syntax. Only occurs in patterns.
1015+
ProjectionKind::OpaqueCast => (),
10141016
ProjectionKind::Deref => {
10151017
// Explicit derefs are typically handled later on, but
10161018
// some items do not need explicit deref, such as array accesses,

tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![feature(type_alias_impl_trait)]
22
// check-pass
3+
// revisions: default edition2021
4+
//[edition2021] compile-flags: --edition 2021
35

46
fn main() {
57
type T = impl Copy;

0 commit comments

Comments
 (0)