Skip to content

Commit 40e2de8

Browse files
committed
Revert "Revert "Rollup merge of rust-lang#98582 - oli-obk:unconstrained_opaque_type, r=estebank""
This reverts commit 4a742a6.
1 parent 5d664f7 commit 40e2de8

File tree

30 files changed

+250
-37
lines changed

30 files changed

+250
-37
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2146,7 +2146,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
21462146
}
21472147
StorageDeadOrDrop::Destructor(_) => kind,
21482148
},
2149-
ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
2149+
ProjectionElem::OpaqueCast { .. }
2150+
| ProjectionElem::Field(..)
2151+
| ProjectionElem::Downcast(..) => {
21502152
match place_ty.ty.kind() {
21512153
ty::Adt(def, _) if def.has_dtor(tcx) => {
21522154
// Report the outermost adt with a destructor

compiler/rustc_borrowck/src/diagnostics/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
237237
}
238238
ProjectionElem::Downcast(..) if opt.including_downcast => return None,
239239
ProjectionElem::Downcast(..) => (),
240+
ProjectionElem::OpaqueCast(..) => (),
240241
ProjectionElem::Field(field, _ty) => {
241242
// FIXME(project-rfc_2229#36): print capture precisely here.
242243
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
@@ -317,6 +318,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
317318
PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
318319
}
319320
ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
321+
ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(*ty),
320322
ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
321323
},
322324
};

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
169169
..,
170170
ProjectionElem::Index(_)
171171
| ProjectionElem::ConstantIndex { .. }
172+
| ProjectionElem::OpaqueCast { .. }
172173
| ProjectionElem::Subslice { .. }
173174
| ProjectionElem::Downcast(..),
174175
],

compiler/rustc_borrowck/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
17811781
for (place_base, elem) in place.iter_projections().rev() {
17821782
match elem {
17831783
ProjectionElem::Index(_/*operand*/) |
1784+
ProjectionElem::OpaqueCast(_) |
17841785
ProjectionElem::ConstantIndex { .. } |
17851786
// assigning to P[i] requires P to be valid.
17861787
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
@@ -2172,6 +2173,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
21722173
| ProjectionElem::Index(..)
21732174
| ProjectionElem::ConstantIndex { .. }
21742175
| ProjectionElem::Subslice { .. }
2176+
| ProjectionElem::OpaqueCast { .. }
21752177
| ProjectionElem::Downcast(..) => {
21762178
let upvar_field_projection = self.is_upvar_field_projection(place);
21772179
if let Some(field) = upvar_field_projection {

compiler/rustc_borrowck/src/places_conflict.rs

+13
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ fn place_components_conflict<'tcx>(
250250
| (ProjectionElem::Index { .. }, _, _)
251251
| (ProjectionElem::ConstantIndex { .. }, _, _)
252252
| (ProjectionElem::Subslice { .. }, _, _)
253+
| (ProjectionElem::OpaqueCast { .. }, _, _)
253254
| (ProjectionElem::Downcast { .. }, _, _) => {
254255
// Recursive case. This can still be disjoint on a
255256
// further iteration if this a shallow access and
@@ -317,6 +318,17 @@ fn place_projection_conflict<'tcx>(
317318
debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
318319
Overlap::EqualOrDisjoint
319320
}
321+
(ProjectionElem::OpaqueCast(v1), ProjectionElem::OpaqueCast(v2)) => {
322+
if v1 == v2 {
323+
// same type - recur.
324+
debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
325+
Overlap::EqualOrDisjoint
326+
} else {
327+
// Different types. Disjoint!
328+
debug!("place_element_conflict: DISJOINT-OPAQUE");
329+
Overlap::Disjoint
330+
}
331+
}
320332
(ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
321333
if f1 == f2 {
322334
// same field (e.g., `a.y` vs. `a.y`) - recur.
@@ -520,6 +532,7 @@ fn place_projection_conflict<'tcx>(
520532
| ProjectionElem::Field(..)
521533
| ProjectionElem::Index(..)
522534
| ProjectionElem::ConstantIndex { .. }
535+
| ProjectionElem::OpaqueCast { .. }
523536
| ProjectionElem::Subslice { .. }
524537
| ProjectionElem::Downcast(..),
525538
_,

compiler/rustc_borrowck/src/prefixes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
8181
}
8282
ProjectionElem::Downcast(..)
8383
| ProjectionElem::Subslice { .. }
84+
| ProjectionElem::OpaqueCast { .. }
8485
| ProjectionElem::ConstantIndex { .. }
8586
| ProjectionElem::Index(_) => {
8687
cursor = cursor_base;

compiler/rustc_borrowck/src/type_check/mod.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,19 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
760760
}
761761
PlaceTy::from_ty(fty)
762762
}
763+
ProjectionElem::OpaqueCast(ty) => {
764+
let ty = self.sanitize_type(place, ty);
765+
let ty = self.cx.normalize(ty, location);
766+
self.cx
767+
.eq_types(
768+
base.ty,
769+
ty,
770+
location.to_locations(),
771+
ConstraintCategory::TypeAnnotation,
772+
)
773+
.unwrap();
774+
PlaceTy::from_ty(ty)
775+
}
763776
}
764777
}
765778

@@ -1166,10 +1179,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
11661179
tcx,
11671180
self.param_env,
11681181
proj,
1169-
|this, field, ()| {
1182+
|this, field, _| {
11701183
let ty = this.field_ty(tcx, field);
11711184
self.normalize(ty, locations)
11721185
},
1186+
|_, _| unreachable!(),
11731187
);
11741188
curr_projected_ty = projected_ty;
11751189
}
@@ -2501,6 +2515,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
25012515
}
25022516
ProjectionElem::Field(..)
25032517
| ProjectionElem::Downcast(..)
2518+
| ProjectionElem::OpaqueCast(..)
25042519
| ProjectionElem::Index(..)
25052520
| ProjectionElem::ConstantIndex { .. }
25062521
| ProjectionElem::Subslice { .. } => {

compiler/rustc_codegen_cranelift/src/base.rs

+1
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,7 @@ pub(crate) fn codegen_place<'tcx>(
850850
PlaceElem::Deref => {
851851
cplace = cplace.place_deref(fx);
852852
}
853+
PlaceElem::OpaqueCast(ty) => cplace = cplace.place_opaque_cast(fx, ty),
853854
PlaceElem::Field(field, _ty) => {
854855
cplace = cplace.place_field(fx, field);
855856
}

compiler/rustc_codegen_cranelift/src/value_and_place.rs

+8
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,14 @@ impl<'tcx> CPlace<'tcx> {
621621
}
622622
}
623623

624+
pub(crate) fn place_opaque_cast(
625+
self,
626+
fx: &mut FunctionCx<'_, '_, 'tcx>,
627+
ty: Ty<'tcx>,
628+
) -> CPlace<'tcx> {
629+
CPlace { inner: self.inner, layout: fx.layout_of(ty) }
630+
}
631+
624632
pub(crate) fn place_field(
625633
self,
626634
fx: &mut FunctionCx<'_, '_, 'tcx>,

compiler/rustc_codegen_ssa/src/mir/place.rs

+16
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,21 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
400400
downcast
401401
}
402402

403+
pub fn project_type<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
404+
&self,
405+
bx: &mut Bx,
406+
ty: Ty<'tcx>,
407+
) -> Self {
408+
let mut downcast = *self;
409+
downcast.layout = bx.cx().layout_of(ty);
410+
411+
// Cast to the appropriate type.
412+
let variant_ty = bx.cx().backend_type(downcast.layout);
413+
downcast.llval = bx.pointercast(downcast.llval, bx.cx().type_ptr_to(variant_ty));
414+
415+
downcast
416+
}
417+
403418
pub fn storage_live<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) {
404419
bx.lifetime_start(self.llval, self.layout.size);
405420
}
@@ -442,6 +457,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
442457
mir::ProjectionElem::Field(ref field, _) => {
443458
cg_base.project_field(bx, field.index())
444459
}
460+
mir::ProjectionElem::OpaqueCast(ty) => cg_base.project_type(bx, ty),
445461
mir::ProjectionElem::Index(index) => {
446462
let index = &mir::Operand::Copy(mir::Place::from(index));
447463
let index = self.codegen_operand(bx, index);

compiler/rustc_const_eval/src/interpret/projection.rs

+10
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,11 @@ where
350350
) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> {
351351
use rustc_middle::mir::ProjectionElem::*;
352352
Ok(match proj_elem {
353+
OpaqueCast(ty) => {
354+
let mut place = base.clone();
355+
place.layout = self.layout_of(ty)?;
356+
place
357+
}
353358
Field(field, _) => self.place_field(base, field.index())?,
354359
Downcast(_, variant) => self.place_downcast(base, variant)?,
355360
Deref => self.deref_operand(&self.place_to_op(base)?)?.into(),
@@ -374,6 +379,11 @@ where
374379
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
375380
use rustc_middle::mir::ProjectionElem::*;
376381
Ok(match proj_elem {
382+
OpaqueCast(ty) => {
383+
let mut op = base.clone();
384+
op.layout = self.layout_of(ty)?;
385+
op
386+
}
377387
Field(field, _) => self.operand_field(base, field.index())?,
378388
Downcast(_, variant) => self.operand_downcast(base, variant)?,
379389
Deref => self.deref_operand(base)?.into(),

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+1
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
656656

657657
ProjectionElem::ConstantIndex { .. }
658658
| ProjectionElem::Downcast(..)
659+
| ProjectionElem::OpaqueCast(..)
659660
| ProjectionElem::Subslice { .. }
660661
| ProjectionElem::Field(..)
661662
| ProjectionElem::Index(_) => {}

compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ where
308308

309309
ProjectionElem::Deref
310310
| ProjectionElem::Field(_, _)
311+
| ProjectionElem::OpaqueCast(_)
311312
| ProjectionElem::ConstantIndex { .. }
312313
| ProjectionElem::Subslice { .. }
313314
| ProjectionElem::Downcast(_, _)

compiler/rustc_const_eval/src/transform/promote_consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ impl<'tcx> Validator<'_, 'tcx> {
361361
return Err(Unpromotable);
362362
}
363363
}
364-
ProjectionElem::Downcast(..) => {
364+
ProjectionElem::OpaqueCast(..) | ProjectionElem::Downcast(..) => {
365365
return Err(Unpromotable);
366366
}
367367

compiler/rustc_middle/src/mir/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,7 @@ impl<V, T> ProjectionElem<V, T> {
13801380

13811381
Self::Field(_, _)
13821382
| Self::Index(_)
1383+
| Self::OpaqueCast(_)
13831384
| Self::ConstantIndex { .. }
13841385
| Self::Subslice { .. }
13851386
| Self::Downcast(_, _) => false,
@@ -1574,7 +1575,9 @@ impl Debug for Place<'_> {
15741575
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
15751576
for elem in self.projection.iter().rev() {
15761577
match elem {
1577-
ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => {
1578+
ProjectionElem::OpaqueCast(_)
1579+
| ProjectionElem::Downcast(_, _)
1580+
| ProjectionElem::Field(_, _) => {
15781581
write!(fmt, "(").unwrap();
15791582
}
15801583
ProjectionElem::Deref => {
@@ -1590,6 +1593,9 @@ impl Debug for Place<'_> {
15901593

15911594
for elem in self.projection.iter() {
15921595
match elem {
1596+
ProjectionElem::OpaqueCast(ty) => {
1597+
write!(fmt, " as {})", ty)?;
1598+
}
15931599
ProjectionElem::Downcast(Some(name), _index) => {
15941600
write!(fmt, " as {})", name)?;
15951601
}

compiler/rustc_middle/src/mir/syntax.rs

+7
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,9 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
829829
/// generator has more than one variant, the parent place's variant index must be set, indicating
830830
/// which variant is being used. If it has just one variant, the variant index may or may not be
831831
/// included - the single possible variant is inferred if it is not included.
832+
/// - [`OpaqueCast`](ProjectionElem::OpaqueCast): This projection changes the place's type to the
833+
/// given one, and makes no other changes. A `OpaqueCast` projection on any type other than an
834+
/// opaque type from the current crate is not well-formed.
832835
/// - [`ConstantIndex`](ProjectionElem::ConstantIndex): Computes an offset in units of `T` into the
833836
/// place as described in the documentation for the `ProjectionElem`. The resulting address is
834837
/// 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> {
928931
///
929932
/// The included Symbol is the name of the variant, used for printing MIR.
930933
Downcast(Option<Symbol>, VariantIdx),
934+
935+
/// Like an explicit cast from an opaque type to a concrete type, but without
936+
/// requiring an intermediate variable.
937+
OpaqueCast(T),
931938
}
932939

933940
/// Alias for projections as they appear in places, where the base is a place

compiler/rustc_middle/src/mir/tcx.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl<'tcx> PlaceTy<'tcx> {
5757
/// `PlaceElem`, where we can just use the `Ty` that is already
5858
/// stored inline on field projection elems.
5959
pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
60-
self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty)
60+
self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty, |_, ty| ty)
6161
}
6262

6363
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@@ -71,6 +71,7 @@ impl<'tcx> PlaceTy<'tcx> {
7171
param_env: ty::ParamEnv<'tcx>,
7272
elem: &ProjectionElem<V, T>,
7373
mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
74+
mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
7475
) -> PlaceTy<'tcx>
7576
where
7677
V: ::std::fmt::Debug,
@@ -109,6 +110,7 @@ impl<'tcx> PlaceTy<'tcx> {
109110
PlaceTy { ty: self.ty, variant_index: Some(index) }
110111
}
111112
ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
113+
ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast(&self, ty)),
112114
};
113115
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
114116
answer

compiler/rustc_middle/src/mir/visit.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,11 @@ macro_rules! visit_place_fns {
10941094
self.visit_ty(&mut new_ty, TyContext::Location(location));
10951095
if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
10961096
}
1097+
PlaceElem::OpaqueCast(ty) => {
1098+
let mut new_ty = ty;
1099+
self.visit_ty(&mut new_ty, TyContext::Location(location));
1100+
if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
1101+
}
10971102
PlaceElem::Deref
10981103
| PlaceElem::ConstantIndex { .. }
10991104
| PlaceElem::Subslice { .. }
@@ -1163,7 +1168,7 @@ macro_rules! visit_place_fns {
11631168
location: Location,
11641169
) {
11651170
match elem {
1166-
ProjectionElem::Field(_field, ty) => {
1171+
ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) => {
11671172
self.visit_ty(ty, TyContext::Location(location));
11681173
}
11691174
ProjectionElem::Index(local) => {

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

+12-5
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
102102
variant = Some(*idx);
103103
continue;
104104
}
105+
// These do not affect anything, they just make sure we know the right type.
106+
ProjectionElem::OpaqueCast(_) => continue,
105107
ProjectionElem::Index(..)
106108
| ProjectionElem::ConstantIndex { .. }
107109
| ProjectionElem::Subslice { .. } => {
@@ -168,7 +170,7 @@ fn find_capture_matching_projections<'a, 'tcx>(
168170
/// `PlaceBuilder` now starts from `PlaceBase::Local`.
169171
///
170172
/// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found.
171-
#[instrument(level = "trace", skip(cx))]
173+
#[instrument(level = "trace", skip(cx), ret)]
172174
fn to_upvars_resolved_place_builder<'tcx>(
173175
from_builder: PlaceBuilder<'tcx>,
174176
cx: &Builder<'_, 'tcx>,
@@ -213,7 +215,6 @@ fn to_upvars_resolved_place_builder<'tcx>(
213215
&capture.captured_place.place.projections,
214216
);
215217
upvar_resolved_place_builder.projection.extend(remaining_projections);
216-
trace!(?upvar_resolved_place_builder);
217218

218219
Ok(upvar_resolved_place_builder)
219220
}
@@ -232,16 +233,21 @@ fn strip_prefix<'tcx>(
232233
prefix_projections: &[HirProjection<'tcx>],
233234
) -> impl Iterator<Item = PlaceElem<'tcx>> {
234235
let mut iter = projections.into_iter();
236+
let mut next = || match iter.next()? {
237+
// Filter out opaque casts, they are unnecessary in the prefix.
238+
ProjectionElem::OpaqueCast(..) => iter.next(),
239+
other => Some(other),
240+
};
235241
for projection in prefix_projections {
236242
match projection.kind {
237243
HirProjectionKind::Deref => {
238-
assert!(matches!(iter.next(), Some(ProjectionElem::Deref)));
244+
assert!(matches!(next(), Some(ProjectionElem::Deref)));
239245
}
240246
HirProjectionKind::Field(..) => {
241247
if base_ty.is_enum() {
242-
assert!(matches!(iter.next(), Some(ProjectionElem::Downcast(..))));
248+
assert!(matches!(next(), Some(ProjectionElem::Downcast(..))));
243249
}
244-
assert!(matches!(iter.next(), Some(ProjectionElem::Field(..))));
250+
assert!(matches!(next(), Some(ProjectionElem::Field(..))));
245251
}
246252
HirProjectionKind::Index | HirProjectionKind::Subslice => {
247253
bug!("unexpected projection kind: {:?}", projection);
@@ -711,6 +717,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
711717
}
712718
ProjectionElem::Field(..)
713719
| ProjectionElem::Downcast(..)
720+
| ProjectionElem::OpaqueCast(..)
714721
| ProjectionElem::ConstantIndex { .. }
715722
| ProjectionElem::Subslice { .. } => (),
716723
}

0 commit comments

Comments
 (0)