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 https://github.com/rust-lang/rust/pull/99806 for when and why we added OpaqueCast to MIR.
This commit is contained in:
commit
576bf82702
@ -498,14 +498,13 @@ fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
|
|||||||
|
|
||||||
/// Checks that the types internal to the `place` match up with
|
/// Checks that the types internal to the `place` match up with
|
||||||
/// what would be expected.
|
/// what would be expected.
|
||||||
|
#[instrument(level = "debug", skip(self, location), ret)]
|
||||||
fn sanitize_place(
|
fn sanitize_place(
|
||||||
&mut self,
|
&mut self,
|
||||||
place: &Place<'tcx>,
|
place: &Place<'tcx>,
|
||||||
location: Location,
|
location: Location,
|
||||||
context: PlaceContext,
|
context: PlaceContext,
|
||||||
) -> PlaceTy<'tcx> {
|
) -> PlaceTy<'tcx> {
|
||||||
debug!("sanitize_place: {:?}", place);
|
|
||||||
|
|
||||||
let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty);
|
let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty);
|
||||||
|
|
||||||
for elem in place.projection.iter() {
|
for elem in place.projection.iter() {
|
||||||
@ -608,7 +607,7 @@ fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Locatio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self, location), ret, level = "debug")]
|
||||||
fn sanitize_projection(
|
fn sanitize_projection(
|
||||||
&mut self,
|
&mut self,
|
||||||
base: PlaceTy<'tcx>,
|
base: PlaceTy<'tcx>,
|
||||||
@ -617,7 +616,6 @@ fn sanitize_projection(
|
|||||||
location: Location,
|
location: Location,
|
||||||
context: PlaceContext,
|
context: PlaceContext,
|
||||||
) -> PlaceTy<'tcx> {
|
) -> PlaceTy<'tcx> {
|
||||||
debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
|
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let base_ty = base.ty;
|
let base_ty = base.ty;
|
||||||
match pi {
|
match pi {
|
||||||
|
@ -198,13 +198,14 @@ pub(crate) fn pat_ty_adjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Like `pat_ty`, but ignores implicit `&` patterns.
|
/// Like `pat_ty`, but ignores implicit `&` patterns.
|
||||||
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
|
fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
|
||||||
let base_ty = self.node_ty(pat.hir_id)?;
|
let base_ty = self.node_ty(pat.hir_id)?;
|
||||||
debug!("pat_ty(pat={:?}) base_ty={:?}", pat, base_ty);
|
trace!(?base_ty);
|
||||||
|
|
||||||
// This code detects whether we are looking at a `ref x`,
|
// This code detects whether we are looking at a `ref x`,
|
||||||
// and if so, figures out what the type *being borrowed* is.
|
// and if so, figures out what the type *being borrowed* is.
|
||||||
let ret_ty = match pat.kind {
|
match pat.kind {
|
||||||
PatKind::Binding(..) => {
|
PatKind::Binding(..) => {
|
||||||
let bm = *self
|
let bm = *self
|
||||||
.typeck_results
|
.typeck_results
|
||||||
@ -217,21 +218,18 @@ fn pat_ty_unadjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
|
|||||||
// but what we want here is the type of the underlying value being borrowed.
|
// but what we want here is the type of the underlying value being borrowed.
|
||||||
// So peel off one-level, turning the &T into T.
|
// So peel off one-level, turning the &T into T.
|
||||||
match base_ty.builtin_deref(false) {
|
match base_ty.builtin_deref(false) {
|
||||||
Some(t) => t.ty,
|
Some(t) => Ok(t.ty),
|
||||||
None => {
|
None => {
|
||||||
debug!("By-ref binding of non-derefable type {:?}", base_ty);
|
debug!("By-ref binding of non-derefable type");
|
||||||
return Err(());
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
base_ty
|
Ok(base_ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => base_ty,
|
_ => Ok(base_ty),
|
||||||
};
|
}
|
||||||
debug!("pat_ty(pat={:?}) ret_ty={:?}", pat, ret_ty);
|
|
||||||
|
|
||||||
Ok(ret_ty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cat_expr(&self, expr: &hir::Expr<'_>) -> McResult<PlaceWithHirId<'tcx>> {
|
pub(crate) fn cat_expr(&self, expr: &hir::Expr<'_>) -> McResult<PlaceWithHirId<'tcx>> {
|
||||||
@ -299,13 +297,11 @@ fn cat_expr_adjusted_with<F>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
pub(crate) fn cat_expr_unadjusted(
|
pub(crate) fn cat_expr_unadjusted(
|
||||||
&self,
|
&self,
|
||||||
expr: &hir::Expr<'_>,
|
expr: &hir::Expr<'_>,
|
||||||
) -> McResult<PlaceWithHirId<'tcx>> {
|
) -> McResult<PlaceWithHirId<'tcx>> {
|
||||||
debug!("cat_expr: id={} expr={:?}", expr.hir_id, expr);
|
|
||||||
|
|
||||||
let expr_ty = self.expr_ty(expr)?;
|
let expr_ty = self.expr_ty(expr)?;
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
hir::ExprKind::Unary(hir::UnOp::Deref, ref e_base) => {
|
hir::ExprKind::Unary(hir::UnOp::Deref, ref e_base) => {
|
||||||
@ -319,7 +315,7 @@ pub(crate) fn cat_expr_unadjusted(
|
|||||||
|
|
||||||
hir::ExprKind::Field(ref base, _) => {
|
hir::ExprKind::Field(ref base, _) => {
|
||||||
let base = self.cat_expr(base)?;
|
let base = self.cat_expr(base)?;
|
||||||
debug!("cat_expr(cat_field): id={} expr={:?} base={:?}", expr.hir_id, expr, base);
|
debug!(?base);
|
||||||
|
|
||||||
let field_idx = self
|
let field_idx = self
|
||||||
.typeck_results
|
.typeck_results
|
||||||
@ -389,7 +385,7 @@ pub(crate) fn cat_expr_unadjusted(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, span))]
|
#[instrument(level = "debug", skip(self, span), ret)]
|
||||||
pub(crate) fn cat_res(
|
pub(crate) fn cat_res(
|
||||||
&self,
|
&self,
|
||||||
hir_id: hir::HirId,
|
hir_id: hir::HirId,
|
||||||
@ -430,6 +426,7 @@ pub(crate) fn cat_res(
|
|||||||
/// Note: the actual upvar access contains invisible derefs of closure
|
/// Note: the actual upvar access contains invisible derefs of closure
|
||||||
/// environment and upvar reference as appropriate. Only regionck cares
|
/// environment and upvar reference as appropriate. Only regionck cares
|
||||||
/// about these dereferences, so we let it compute them as needed.
|
/// about these dereferences, so we let it compute them as needed.
|
||||||
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult<PlaceWithHirId<'tcx>> {
|
fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult<PlaceWithHirId<'tcx>> {
|
||||||
let closure_expr_def_id = self.body_owner;
|
let closure_expr_def_id = self.body_owner;
|
||||||
|
|
||||||
@ -439,24 +436,20 @@ fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult<PlaceWit
|
|||||||
};
|
};
|
||||||
let var_ty = self.node_ty(var_id)?;
|
let var_ty = self.node_ty(var_id)?;
|
||||||
|
|
||||||
let ret = PlaceWithHirId::new(hir_id, var_ty, PlaceBase::Upvar(upvar_id), Vec::new());
|
Ok(PlaceWithHirId::new(hir_id, var_ty, PlaceBase::Upvar(upvar_id), Vec::new()))
|
||||||
|
|
||||||
debug!("cat_upvar ret={:?}", ret);
|
|
||||||
Ok(ret)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self), ret)]
|
||||||
pub(crate) fn cat_rvalue(
|
pub(crate) fn cat_rvalue(
|
||||||
&self,
|
&self,
|
||||||
hir_id: hir::HirId,
|
hir_id: hir::HirId,
|
||||||
span: Span,
|
span: Span,
|
||||||
expr_ty: Ty<'tcx>,
|
expr_ty: Ty<'tcx>,
|
||||||
) -> PlaceWithHirId<'tcx> {
|
) -> PlaceWithHirId<'tcx> {
|
||||||
debug!("cat_rvalue hir_id={:?}, expr_ty={:?}, span={:?}", hir_id, expr_ty, span);
|
PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new())
|
||||||
let ret = PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new());
|
|
||||||
debug!("cat_rvalue ret={:?}", ret);
|
|
||||||
ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self, node), ret)]
|
||||||
pub(crate) fn cat_projection<N: HirNode>(
|
pub(crate) fn cat_projection<N: HirNode>(
|
||||||
&self,
|
&self,
|
||||||
node: &N,
|
node: &N,
|
||||||
@ -464,16 +457,23 @@ pub(crate) fn cat_projection<N: HirNode>(
|
|||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
kind: ProjectionKind,
|
kind: ProjectionKind,
|
||||||
) -> PlaceWithHirId<'tcx> {
|
) -> PlaceWithHirId<'tcx> {
|
||||||
|
let place_ty = base_place.place.ty();
|
||||||
let mut projections = base_place.place.projections;
|
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 });
|
projections.push(Projection { kind, ty });
|
||||||
let ret = PlaceWithHirId::new(
|
PlaceWithHirId::new(
|
||||||
node.hir_id(),
|
node.hir_id(),
|
||||||
base_place.place.base_ty,
|
base_place.place.base_ty,
|
||||||
base_place.place.base,
|
base_place.place.base,
|
||||||
projections,
|
projections,
|
||||||
);
|
)
|
||||||
debug!("cat_field ret {:?}", ret);
|
|
||||||
ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
@ -497,7 +497,7 @@ fn cat_overloaded_place(
|
|||||||
self.cat_deref(expr, base)
|
self.cat_deref(expr, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, node))]
|
#[instrument(level = "debug", skip(self, node), ret)]
|
||||||
fn cat_deref(
|
fn cat_deref(
|
||||||
&self,
|
&self,
|
||||||
node: &impl HirNode,
|
node: &impl HirNode,
|
||||||
@ -514,14 +514,12 @@ fn cat_deref(
|
|||||||
let mut projections = base_place.place.projections;
|
let mut projections = base_place.place.projections;
|
||||||
projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });
|
projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });
|
||||||
|
|
||||||
let ret = PlaceWithHirId::new(
|
Ok(PlaceWithHirId::new(
|
||||||
node.hir_id(),
|
node.hir_id(),
|
||||||
base_place.place.base_ty,
|
base_place.place.base_ty,
|
||||||
base_place.place.base,
|
base_place.place.base,
|
||||||
projections,
|
projections,
|
||||||
);
|
))
|
||||||
debug!("cat_deref ret {:?}", ret);
|
|
||||||
Ok(ret)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cat_pattern<F>(
|
pub(crate) fn cat_pattern<F>(
|
||||||
@ -603,6 +601,13 @@ fn total_fields_in_tuple(&self, pat_hir_id: hir::HirId, span: Span) -> McResult<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Here, `place` is the `PlaceWithHirId` being matched and pat is the pattern it
|
||||||
|
/// is being matched against.
|
||||||
|
///
|
||||||
|
/// In general, the way that this works is that we walk down the pattern,
|
||||||
|
/// constructing a `PlaceWithHirId` that represents the path that will be taken
|
||||||
|
/// to reach the value being matched.
|
||||||
|
#[instrument(skip(self, op), ret, level = "debug")]
|
||||||
fn cat_pattern_<F>(
|
fn cat_pattern_<F>(
|
||||||
&self,
|
&self,
|
||||||
mut place_with_id: PlaceWithHirId<'tcx>,
|
mut place_with_id: PlaceWithHirId<'tcx>,
|
||||||
@ -612,15 +617,6 @@ fn cat_pattern_<F>(
|
|||||||
where
|
where
|
||||||
F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>),
|
F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>),
|
||||||
{
|
{
|
||||||
// Here, `place` is the `PlaceWithHirId` being matched and pat is the pattern it
|
|
||||||
// is being matched against.
|
|
||||||
//
|
|
||||||
// In general, the way that this works is that we walk down the pattern,
|
|
||||||
// constructing a `PlaceWithHirId` that represents the path that will be taken
|
|
||||||
// to reach the value being matched.
|
|
||||||
|
|
||||||
debug!("cat_pattern(pat={:?}, place_with_id={:?})", pat, place_with_id);
|
|
||||||
|
|
||||||
// If (pattern) adjustments are active for this pattern, adjust the `PlaceWithHirId` correspondingly.
|
// If (pattern) adjustments are active for this pattern, adjust the `PlaceWithHirId` correspondingly.
|
||||||
// `PlaceWithHirId`s are constructed differently from patterns. For example, in
|
// `PlaceWithHirId`s are constructed differently from patterns. For example, in
|
||||||
//
|
//
|
||||||
@ -654,11 +650,11 @@ fn cat_pattern_<F>(
|
|||||||
// `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)`
|
// `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)`
|
||||||
// and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`.
|
// and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`.
|
||||||
for _ in 0..self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len()) {
|
for _ in 0..self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len()) {
|
||||||
debug!("cat_pattern: applying adjustment to place_with_id={:?}", place_with_id);
|
debug!("applying adjustment to place_with_id={:?}", place_with_id);
|
||||||
place_with_id = self.cat_deref(pat, place_with_id)?;
|
place_with_id = self.cat_deref(pat, place_with_id)?;
|
||||||
}
|
}
|
||||||
let place_with_id = place_with_id; // lose mutability
|
let place_with_id = place_with_id; // lose mutability
|
||||||
debug!("cat_pattern: applied adjustment derefs to get place_with_id={:?}", place_with_id);
|
debug!("applied adjustment derefs to get place_with_id={:?}", place_with_id);
|
||||||
|
|
||||||
// Invoke the callback, but only now, after the `place_with_id` has adjusted.
|
// Invoke the callback, but only now, after the `place_with_id` has adjusted.
|
||||||
//
|
//
|
||||||
|
@ -264,12 +264,12 @@ fn analyze_closure(
|
|||||||
self.demand_eqtype(span, closure_kind.to_ty(self.tcx), closure_kind_ty);
|
self.demand_eqtype(span, closure_kind.to_ty(self.tcx), closure_kind_ty);
|
||||||
|
|
||||||
// If we have an origin, store it.
|
// If we have an origin, store it.
|
||||||
if let Some(origin) = origin {
|
if let Some(mut origin) = origin {
|
||||||
let origin = if enable_precise_capture(span) {
|
if !enable_precise_capture(span) {
|
||||||
(origin.0, origin.1)
|
// Without precise captures, we just capture the base and ignore
|
||||||
} else {
|
// the projections.
|
||||||
(origin.0, Place { projections: vec![], ..origin.1 })
|
origin.1.projections.clear()
|
||||||
};
|
}
|
||||||
|
|
||||||
self.typeck_results
|
self.typeck_results
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
@ -294,10 +294,7 @@ fn analyze_closure(
|
|||||||
|
|
||||||
// Equate the type variables for the upvars with the actual types.
|
// Equate the type variables for the upvars with the actual types.
|
||||||
let final_upvar_tys = self.final_upvar_tys(closure_def_id);
|
let final_upvar_tys = self.final_upvar_tys(closure_def_id);
|
||||||
debug!(
|
debug!(?closure_hir_id, ?args, ?final_upvar_tys);
|
||||||
"analyze_closure: id={:?} args={:?} final_upvar_tys={:?}",
|
|
||||||
closure_hir_id, args, final_upvar_tys
|
|
||||||
);
|
|
||||||
|
|
||||||
// Build a tuple (U0..Un) of the final upvar types U0..Un
|
// Build a tuple (U0..Un) of the final upvar types U0..Un
|
||||||
// and unify the upvar tuple type in the closure with it:
|
// and unify the upvar tuple type in the closure with it:
|
||||||
@ -338,10 +335,7 @@ fn final_upvar_tys(&self, closure_id: LocalDefId) -> Vec<Ty<'tcx>> {
|
|||||||
let upvar_ty = captured_place.place.ty();
|
let upvar_ty = captured_place.place.ty();
|
||||||
let capture = captured_place.info.capture_kind;
|
let capture = captured_place.info.capture_kind;
|
||||||
|
|
||||||
debug!(
|
debug!(?captured_place.place, ?upvar_ty, ?capture, ?captured_place.mutability);
|
||||||
"final_upvar_tys: place={:?} upvar_ty={:?} capture={:?}, mutability={:?}",
|
|
||||||
captured_place.place, upvar_ty, capture, captured_place.mutability,
|
|
||||||
);
|
|
||||||
|
|
||||||
apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture, captured_place.region)
|
apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture, captured_place.region)
|
||||||
})
|
})
|
||||||
@ -679,6 +673,7 @@ fn compute_min_captures(
|
|||||||
match (p1.kind, p2.kind) {
|
match (p1.kind, p2.kind) {
|
||||||
// Paths are the same, continue to next loop.
|
// Paths are the same, continue to next loop.
|
||||||
(ProjectionKind::Deref, ProjectionKind::Deref) => {}
|
(ProjectionKind::Deref, ProjectionKind::Deref) => {}
|
||||||
|
(ProjectionKind::OpaqueCast, ProjectionKind::OpaqueCast) => {}
|
||||||
(ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _))
|
(ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _))
|
||||||
if i1 == i2 => {}
|
if i1 == i2 => {}
|
||||||
|
|
||||||
@ -701,10 +696,12 @@ fn compute_min_captures(
|
|||||||
l @ (ProjectionKind::Index
|
l @ (ProjectionKind::Index
|
||||||
| ProjectionKind::Subslice
|
| ProjectionKind::Subslice
|
||||||
| ProjectionKind::Deref
|
| ProjectionKind::Deref
|
||||||
|
| ProjectionKind::OpaqueCast
|
||||||
| ProjectionKind::Field(..)),
|
| ProjectionKind::Field(..)),
|
||||||
r @ (ProjectionKind::Index
|
r @ (ProjectionKind::Index
|
||||||
| ProjectionKind::Subslice
|
| ProjectionKind::Subslice
|
||||||
| ProjectionKind::Deref
|
| ProjectionKind::Deref
|
||||||
|
| ProjectionKind::OpaqueCast
|
||||||
| ProjectionKind::Field(..)),
|
| ProjectionKind::Field(..)),
|
||||||
) => bug!(
|
) => bug!(
|
||||||
"ProjectionKinds Index or Subslice were unexpected: ({:?}, {:?})",
|
"ProjectionKinds Index or Subslice were unexpected: ({:?}, {:?})",
|
||||||
@ -1890,6 +1887,7 @@ fn restrict_capture_precision(
|
|||||||
return (place, curr_mode);
|
return (place, curr_mode);
|
||||||
}
|
}
|
||||||
ProjectionKind::Deref => {}
|
ProjectionKind::Deref => {}
|
||||||
|
ProjectionKind::OpaqueCast => {}
|
||||||
ProjectionKind::Field(..) => {} // ignore
|
ProjectionKind::Field(..) => {} // ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1946,6 +1944,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String
|
|||||||
ProjectionKind::Deref => String::from("Deref"),
|
ProjectionKind::Deref => String::from("Deref"),
|
||||||
ProjectionKind::Index => String::from("Index"),
|
ProjectionKind::Index => String::from("Index"),
|
||||||
ProjectionKind::Subslice => String::from("Subslice"),
|
ProjectionKind::Subslice => String::from("Subslice"),
|
||||||
|
ProjectionKind::OpaqueCast => String::from("OpaqueCast"),
|
||||||
};
|
};
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
projections_str.push(',');
|
projections_str.push(',');
|
||||||
|
@ -36,6 +36,10 @@ pub enum ProjectionKind {
|
|||||||
|
|
||||||
/// A subslice covering a range of values like `B[x..y]`.
|
/// A subslice covering a range of values like `B[x..y]`.
|
||||||
Subslice,
|
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)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
|
||||||
|
@ -174,6 +174,8 @@ pub fn to_symbol(&self) -> Symbol {
|
|||||||
// Ignore derefs for now, as they are likely caused by
|
// Ignore derefs for now, as they are likely caused by
|
||||||
// autoderefs that don't appear in the original code.
|
// autoderefs that don't appear in the original code.
|
||||||
HirProjectionKind::Deref => {}
|
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),
|
proj => bug!("Unexpected projection {:?} in captured place", proj),
|
||||||
}
|
}
|
||||||
ty = proj.ty;
|
ty = proj.ty;
|
||||||
|
@ -236,6 +236,9 @@ fn strip_prefix<'a, 'tcx>(
|
|||||||
}
|
}
|
||||||
assert_matches!(iter.next(), Some(ProjectionElem::Field(..)));
|
assert_matches!(iter.next(), Some(ProjectionElem::Field(..)));
|
||||||
}
|
}
|
||||||
|
HirProjectionKind::OpaqueCast => {
|
||||||
|
assert_matches!(iter.next(), Some(ProjectionElem::OpaqueCast(..)));
|
||||||
|
}
|
||||||
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
||||||
bug!("unexpected projection kind: {:?}", projection);
|
bug!("unexpected projection kind: {:?}", projection);
|
||||||
}
|
}
|
||||||
|
@ -1072,6 +1072,9 @@ fn convert_captured_hir_place(
|
|||||||
variant_index,
|
variant_index,
|
||||||
name: field,
|
name: field,
|
||||||
},
|
},
|
||||||
|
HirProjectionKind::OpaqueCast => {
|
||||||
|
ExprKind::Use { source: self.thir.exprs.push(captured_place_expr) }
|
||||||
|
}
|
||||||
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
||||||
// We don't capture these projections, so we can ignore them here
|
// We don't capture these projections, so we can ignore them here
|
||||||
continue;
|
continue;
|
||||||
|
@ -1011,6 +1011,8 @@ fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) {
|
|||||||
},
|
},
|
||||||
// note: unable to trigger `Subslice` kind in tests
|
// note: unable to trigger `Subslice` kind in tests
|
||||||
ProjectionKind::Subslice => (),
|
ProjectionKind::Subslice => (),
|
||||||
|
// Doesn't have surface syntax. Only occurs in patterns.
|
||||||
|
ProjectionKind::OpaqueCast => (),
|
||||||
ProjectionKind::Deref => {
|
ProjectionKind::Deref => {
|
||||||
// Explicit derefs are typically handled later on, but
|
// Explicit derefs are typically handled later on, but
|
||||||
// some items do not need explicit deref, such as array accesses,
|
// some items do not need explicit deref, such as array accesses,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
// check-pass
|
// check-pass
|
||||||
|
// revisions: default edition2021
|
||||||
|
//[edition2021] compile-flags: --edition 2021
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
type T = impl Copy;
|
type T = impl Copy;
|
||||||
|
Loading…
Reference in New Issue
Block a user