Skip to content

Commit 576bf82

Browse files
authored
Rollup merge of #114022 - oli-obk:tait_ice_alias_field_projection, r=cjgillot
Perform OpaqueCast field projection on HIR, too. fixes #105819 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). See #99806 for when and why we added OpaqueCast to MIR.
2 parents 098c1db + e390dc9 commit 576bf82

File tree

9 files changed

+71
-62
lines changed

9 files changed

+71
-62
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -498,14 +498,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
498498

499499
/// Checks that the types internal to the `place` match up with
500500
/// what would be expected.
501+
#[instrument(level = "debug", skip(self, location), ret)]
501502
fn sanitize_place(
502503
&mut self,
503504
place: &Place<'tcx>,
504505
location: Location,
505506
context: PlaceContext,
506507
) -> PlaceTy<'tcx> {
507-
debug!("sanitize_place: {:?}", place);
508-
509508
let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty);
510509

511510
for elem in place.projection.iter() {
@@ -608,7 +607,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
608607
}
609608
}
610609

611-
#[instrument(skip(self), level = "debug")]
610+
#[instrument(skip(self, location), ret, level = "debug")]
612611
fn sanitize_projection(
613612
&mut self,
614613
base: PlaceTy<'tcx>,
@@ -617,7 +616,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
617616
location: Location,
618617
context: PlaceContext,
619618
) -> PlaceTy<'tcx> {
620-
debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
621619
let tcx = self.tcx();
622620
let base_ty = base.ty;
623621
match pi {

compiler/rustc_hir_typeck/src/mem_categorization.rs

+40-44
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,14 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
198198
}
199199

200200
/// Like `pat_ty`, but ignores implicit `&` patterns.
201+
#[instrument(level = "debug", skip(self), ret)]
201202
fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
202203
let base_ty = self.node_ty(pat.hir_id)?;
203-
debug!("pat_ty(pat={:?}) base_ty={:?}", pat, base_ty);
204+
trace!(?base_ty);
204205

205206
// This code detects whether we are looking at a `ref x`,
206207
// and if so, figures out what the type *being borrowed* is.
207-
let ret_ty = match pat.kind {
208+
match pat.kind {
208209
PatKind::Binding(..) => {
209210
let bm = *self
210211
.typeck_results
@@ -217,21 +218,18 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
217218
// but what we want here is the type of the underlying value being borrowed.
218219
// So peel off one-level, turning the &T into T.
219220
match base_ty.builtin_deref(false) {
220-
Some(t) => t.ty,
221+
Some(t) => Ok(t.ty),
221222
None => {
222-
debug!("By-ref binding of non-derefable type {:?}", base_ty);
223-
return Err(());
223+
debug!("By-ref binding of non-derefable type");
224+
Err(())
224225
}
225226
}
226227
} else {
227-
base_ty
228+
Ok(base_ty)
228229
}
229230
}
230-
_ => base_ty,
231-
};
232-
debug!("pat_ty(pat={:?}) ret_ty={:?}", pat, ret_ty);
233-
234-
Ok(ret_ty)
231+
_ => Ok(base_ty),
232+
}
235233
}
236234

237235
pub(crate) fn cat_expr(&self, expr: &hir::Expr<'_>) -> McResult<PlaceWithHirId<'tcx>> {
@@ -299,13 +297,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
299297
}
300298
}
301299

302-
#[instrument(level = "debug", skip(self))]
300+
#[instrument(level = "debug", skip(self), ret)]
303301
pub(crate) fn cat_expr_unadjusted(
304302
&self,
305303
expr: &hir::Expr<'_>,
306304
) -> McResult<PlaceWithHirId<'tcx>> {
307-
debug!("cat_expr: id={} expr={:?}", expr.hir_id, expr);
308-
309305
let expr_ty = self.expr_ty(expr)?;
310306
match expr.kind {
311307
hir::ExprKind::Unary(hir::UnOp::Deref, ref e_base) => {
@@ -319,7 +315,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
319315

320316
hir::ExprKind::Field(ref base, _) => {
321317
let base = self.cat_expr(base)?;
322-
debug!("cat_expr(cat_field): id={} expr={:?} base={:?}", expr.hir_id, expr, base);
318+
debug!(?base);
323319

324320
let field_idx = self
325321
.typeck_results
@@ -389,7 +385,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
389385
}
390386
}
391387

392-
#[instrument(level = "debug", skip(self, span))]
388+
#[instrument(level = "debug", skip(self, span), ret)]
393389
pub(crate) fn cat_res(
394390
&self,
395391
hir_id: hir::HirId,
@@ -430,6 +426,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
430426
/// Note: the actual upvar access contains invisible derefs of closure
431427
/// environment and upvar reference as appropriate. Only regionck cares
432428
/// about these dereferences, so we let it compute them as needed.
429+
#[instrument(level = "debug", skip(self), ret)]
433430
fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult<PlaceWithHirId<'tcx>> {
434431
let closure_expr_def_id = self.body_owner;
435432

@@ -439,41 +436,44 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
439436
};
440437
let var_ty = self.node_ty(var_id)?;
441438

442-
let ret = PlaceWithHirId::new(hir_id, var_ty, PlaceBase::Upvar(upvar_id), Vec::new());
443-
444-
debug!("cat_upvar ret={:?}", ret);
445-
Ok(ret)
439+
Ok(PlaceWithHirId::new(hir_id, var_ty, PlaceBase::Upvar(upvar_id), Vec::new()))
446440
}
447441

442+
#[instrument(level = "debug", skip(self), ret)]
448443
pub(crate) fn cat_rvalue(
449444
&self,
450445
hir_id: hir::HirId,
451446
span: Span,
452447
expr_ty: Ty<'tcx>,
453448
) -> PlaceWithHirId<'tcx> {
454-
debug!("cat_rvalue hir_id={:?}, expr_ty={:?}, span={:?}", hir_id, expr_ty, span);
455-
let ret = PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new());
456-
debug!("cat_rvalue ret={:?}", ret);
457-
ret
449+
PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new())
458450
}
459451

452+
#[instrument(level = "debug", skip(self, node), ret)]
460453
pub(crate) fn cat_projection<N: HirNode>(
461454
&self,
462455
node: &N,
463456
base_place: PlaceWithHirId<'tcx>,
464457
ty: Ty<'tcx>,
465458
kind: ProjectionKind,
466459
) -> PlaceWithHirId<'tcx> {
460+
let place_ty = base_place.place.ty();
467461
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+
}
468470
projections.push(Projection { kind, ty });
469-
let ret = PlaceWithHirId::new(
471+
PlaceWithHirId::new(
470472
node.hir_id(),
471473
base_place.place.base_ty,
472474
base_place.place.base,
473475
projections,
474-
);
475-
debug!("cat_field ret {:?}", ret);
476-
ret
476+
)
477477
}
478478

479479
#[instrument(level = "debug", skip(self))]
@@ -497,7 +497,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
497497
self.cat_deref(expr, base)
498498
}
499499

500-
#[instrument(level = "debug", skip(self, node))]
500+
#[instrument(level = "debug", skip(self, node), ret)]
501501
fn cat_deref(
502502
&self,
503503
node: &impl HirNode,
@@ -514,14 +514,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
514514
let mut projections = base_place.place.projections;
515515
projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });
516516

517-
let ret = PlaceWithHirId::new(
517+
Ok(PlaceWithHirId::new(
518518
node.hir_id(),
519519
base_place.place.base_ty,
520520
base_place.place.base,
521521
projections,
522-
);
523-
debug!("cat_deref ret {:?}", ret);
524-
Ok(ret)
522+
))
525523
}
526524

527525
pub(crate) fn cat_pattern<F>(
@@ -603,6 +601,13 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
603601
}
604602
}
605603

604+
/// Here, `place` is the `PlaceWithHirId` being matched and pat is the pattern it
605+
/// is being matched against.
606+
///
607+
/// In general, the way that this works is that we walk down the pattern,
608+
/// constructing a `PlaceWithHirId` that represents the path that will be taken
609+
/// to reach the value being matched.
610+
#[instrument(skip(self, op), ret, level = "debug")]
606611
fn cat_pattern_<F>(
607612
&self,
608613
mut place_with_id: PlaceWithHirId<'tcx>,
@@ -612,15 +617,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
612617
where
613618
F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>),
614619
{
615-
// Here, `place` is the `PlaceWithHirId` being matched and pat is the pattern it
616-
// is being matched against.
617-
//
618-
// In general, the way that this works is that we walk down the pattern,
619-
// constructing a `PlaceWithHirId` that represents the path that will be taken
620-
// to reach the value being matched.
621-
622-
debug!("cat_pattern(pat={:?}, place_with_id={:?})", pat, place_with_id);
623-
624620
// If (pattern) adjustments are active for this pattern, adjust the `PlaceWithHirId` correspondingly.
625621
// `PlaceWithHirId`s are constructed differently from patterns. For example, in
626622
//
@@ -654,11 +650,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
654650
// `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)`
655651
// and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`.
656652
for _ in 0..self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len()) {
657-
debug!("cat_pattern: applying adjustment to place_with_id={:?}", place_with_id);
653+
debug!("applying adjustment to place_with_id={:?}", place_with_id);
658654
place_with_id = self.cat_deref(pat, place_with_id)?;
659655
}
660656
let place_with_id = place_with_id; // lose mutability
661-
debug!("cat_pattern: applied adjustment derefs to get place_with_id={:?}", place_with_id);
657+
debug!("applied adjustment derefs to get place_with_id={:?}", place_with_id);
662658

663659
// Invoke the callback, but only now, after the `place_with_id` has adjusted.
664660
//

compiler/rustc_hir_typeck/src/upvar.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
264264
self.demand_eqtype(span, closure_kind.to_ty(self.tcx), closure_kind_ty);
265265

266266
// If we have an origin, store it.
267-
if let Some(origin) = origin {
268-
let origin = if enable_precise_capture(span) {
269-
(origin.0, origin.1)
270-
} else {
271-
(origin.0, Place { projections: vec![], ..origin.1 })
272-
};
267+
if let Some(mut origin) = origin {
268+
if !enable_precise_capture(span) {
269+
// Without precise captures, we just capture the base and ignore
270+
// the projections.
271+
origin.1.projections.clear()
272+
}
273273

274274
self.typeck_results
275275
.borrow_mut()
@@ -294,10 +294,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
294294

295295
// Equate the type variables for the upvars with the actual types.
296296
let final_upvar_tys = self.final_upvar_tys(closure_def_id);
297-
debug!(
298-
"analyze_closure: id={:?} args={:?} final_upvar_tys={:?}",
299-
closure_hir_id, args, final_upvar_tys
300-
);
297+
debug!(?closure_hir_id, ?args, ?final_upvar_tys);
301298

302299
// Build a tuple (U0..Un) of the final upvar types U0..Un
303300
// and unify the upvar tuple type in the closure with it:
@@ -338,10 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
338335
let upvar_ty = captured_place.place.ty();
339336
let capture = captured_place.info.capture_kind;
340337

341-
debug!(
342-
"final_upvar_tys: place={:?} upvar_ty={:?} capture={:?}, mutability={:?}",
343-
captured_place.place, upvar_ty, capture, captured_place.mutability,
344-
);
338+
debug!(?captured_place.place, ?upvar_ty, ?capture, ?captured_place.mutability);
345339

346340
apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture, captured_place.region)
347341
})
@@ -679,6 +673,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
679673
match (p1.kind, p2.kind) {
680674
// Paths are the same, continue to next loop.
681675
(ProjectionKind::Deref, ProjectionKind::Deref) => {}
676+
(ProjectionKind::OpaqueCast, ProjectionKind::OpaqueCast) => {}
682677
(ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _))
683678
if i1 == i2 => {}
684679

@@ -701,10 +696,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
701696
l @ (ProjectionKind::Index
702697
| ProjectionKind::Subslice
703698
| ProjectionKind::Deref
699+
| ProjectionKind::OpaqueCast
704700
| ProjectionKind::Field(..)),
705701
r @ (ProjectionKind::Index
706702
| ProjectionKind::Subslice
707703
| ProjectionKind::Deref
704+
| ProjectionKind::OpaqueCast
708705
| ProjectionKind::Field(..)),
709706
) => bug!(
710707
"ProjectionKinds Index or Subslice were unexpected: ({:?}, {:?})",
@@ -1890,6 +1887,7 @@ fn restrict_capture_precision(
18901887
return (place, curr_mode);
18911888
}
18921889
ProjectionKind::Deref => {}
1890+
ProjectionKind::OpaqueCast => {}
18931891
ProjectionKind::Field(..) => {} // ignore
18941892
}
18951893
}
@@ -1946,6 +1944,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String
19461944
ProjectionKind::Deref => String::from("Deref"),
19471945
ProjectionKind::Index => String::from("Index"),
19481946
ProjectionKind::Subslice => String::from("Subslice"),
1947+
ProjectionKind::OpaqueCast => String::from("OpaqueCast"),
19491948
};
19501949
if i != 0 {
19511950
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
@@ -1072,6 +1072,9 @@ impl<'tcx> Cx<'tcx> {
10721072
variant_index,
10731073
name: field,
10741074
},
1075+
HirProjectionKind::OpaqueCast => {
1076+
ExprKind::Use { source: self.thir.exprs.push(captured_place_expr) }
1077+
}
10751078
HirProjectionKind::Index | HirProjectionKind::Subslice => {
10761079
// We don't capture these projections, so we can ignore them here
10771080
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)