1
Fork 0

correctly deal with user type ascriptions in pat

This commit is contained in:
lcnr 2022-04-28 13:48:54 +02:00
parent 4a86c7907b
commit 39a03779f8
12 changed files with 208 additions and 103 deletions

View file

@ -523,8 +523,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
},
..
},
ascription:
thir::Ascription { user_ty: pat_ascription_ty, variance: _, user_ty_span },
ascription: thir::Ascription { annotation, variance: _ },
} => {
let place =
self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
@ -535,18 +534,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let cause_let = FakeReadCause::ForLet(None);
self.cfg.push_fake_read(block, pattern_source_info, cause_let, place);
let ty_source_info = self.source_info(user_ty_span);
let user_ty = pat_ascription_ty.user_ty(
&mut self.canonical_user_type_annotations,
place.ty(&self.local_decls, self.tcx).ty,
ty_source_info.span,
);
let ty_source_info = self.source_info(annotation.span);
let base = self.canonical_user_type_annotations.push(annotation);
self.cfg.push(
block,
Statement {
source_info: ty_source_info,
kind: StatementKind::AscribeUserType(
Box::new((place, user_ty)),
Box::new((place, UserTypeProjection { base, projs: Vec::new() })),
// We always use invariant as the variance here. This is because the
// variance field from the ascription refers to the variance to use
// when applying the type to the value being matched, but this
@ -784,7 +780,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
PatKind::AscribeUserType {
ref subpattern,
ascription: thir::Ascription { ref user_ty, user_ty_span, variance: _ },
ascription: thir::Ascription { ref annotation, variance: _ },
} => {
// This corresponds to something like
//
@ -794,16 +790,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
//
// Note that the variance doesn't apply here, as we are tracking the effect
// of `user_ty` on any bindings contained with subpattern.
let annotation = CanonicalUserTypeAnnotation {
span: user_ty_span,
user_ty: user_ty.user_ty,
inferred_ty: subpattern.ty,
};
let projection = UserTypeProjection {
base: self.canonical_user_type_annotations.push(annotation),
base: self.canonical_user_type_annotations.push(annotation.clone()),
projs: Vec::new(),
};
let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span);
let subpattern_user_ty =
pattern_user_ty.push_projection(&projection, annotation.span);
self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
}
@ -927,9 +920,8 @@ struct Binding<'tcx> {
/// influence region inference.
#[derive(Clone, Debug)]
struct Ascription<'tcx> {
span: Span,
source: Place<'tcx>,
user_ty: PatTyProj<'tcx>,
annotation: CanonicalUserTypeAnnotation<'tcx>,
variance: ty::Variance,
}
@ -1858,7 +1850,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
parent_bindings
.iter()
.flat_map(|(_, ascriptions)| ascriptions)
.chain(&candidate.ascriptions),
.cloned()
.chain(candidate.ascriptions),
);
// rust-lang/rust#27282: The `autoref` business deserves some
@ -2062,32 +2055,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Append `AscribeUserType` statements onto the end of `block`
/// for each ascription
fn ascribe_types<'b>(
fn ascribe_types(
&mut self,
block: BasicBlock,
ascriptions: impl IntoIterator<Item = &'b Ascription<'tcx>>,
) where
'tcx: 'b,
{
ascriptions: impl IntoIterator<Item = Ascription<'tcx>>,
) {
for ascription in ascriptions {
let source_info = self.source_info(ascription.span);
let source_info = self.source_info(ascription.annotation.span);
debug!(
"adding user ascription at span {:?} of place {:?} and {:?}",
source_info.span, ascription.source, ascription.user_ty,
);
let user_ty = ascription.user_ty.user_ty(
&mut self.canonical_user_type_annotations,
ascription.source.ty(&self.local_decls, self.tcx).ty,
source_info.span,
);
let base = self.canonical_user_type_annotations.push(ascription.annotation);
self.cfg.push(
block,
Statement {
source_info,
kind: StatementKind::AscribeUserType(
Box::new((ascription.source, user_ty)),
Box::new((
ascription.source,
UserTypeProjection { base, projs: Vec::new() },
)),
ascription.variance,
),
},

View file

@ -152,15 +152,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
match *match_pair.pattern.kind {
PatKind::AscribeUserType {
ref subpattern,
ascription: thir::Ascription { variance, user_ty, user_ty_span },
ascription: thir::Ascription { ref annotation, variance },
} => {
// Apply the type ascription to the value at `match_pair.place`, which is the
if let Ok(place_resolved) =
match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
{
candidate.ascriptions.push(Ascription {
span: user_ty_span,
user_ty,
annotation: annotation.clone(),
source: place_resolved.into_place(self.tcx, self.typeck_results),
variance,
});

View file

@ -6,6 +6,7 @@ use rustc_middle::thir::*;
use rustc_middle::ty;
use rustc_index::vec::Idx;
use rustc_middle::ty::CanonicalUserTypeAnnotation;
impl<'tcx> Cx<'tcx> {
crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block {
@ -80,13 +81,17 @@ impl<'tcx> Cx<'tcx> {
self.typeck_results.user_provided_types().get(ty.hir_id)
{
debug!("mirror_stmts: user_ty={:?}", user_ty);
let annotation = CanonicalUserTypeAnnotation {
user_ty,
span: ty.span,
inferred_ty: self.typeck_results.node_type(ty.hir_id),
};
pattern = Pat {
ty: pattern.ty,
span: pattern.span,
kind: Box::new(PatKind::AscribeUserType {
ascription: Ascription {
user_ty: PatTyProj::from_user_type(user_ty),
user_ty_span: ty.span,
annotation,
variance: ty::Variance::Covariant,
},
subpattern: pattern,

View file

@ -19,8 +19,9 @@ use rustc_middle::mir::interpret::{get_slice_bytes, ConstValue};
use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
use rustc_middle::mir::{self, UserTypeProjection};
use rustc_middle::mir::{BorrowKind, Field, Mutability};
use rustc_middle::thir::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange, PatTyProj};
use rustc_middle::thir::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange};
use rustc_middle::ty::subst::{GenericArg, SubstsRef};
use rustc_middle::ty::CanonicalUserTypeAnnotation;
use rustc_middle::ty::{self, AdtDef, ConstKind, DefIdTree, Region, Ty, TyCtxt, UserType};
use rustc_span::{Span, Symbol};
@ -227,7 +228,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
for end in &[lo, hi] {
if let Some((_, Some(ascription))) = end {
let subpattern = Pat { span: pat.span, ty, kind: Box::new(kind) };
kind = PatKind::AscribeUserType { ascription: *ascription, subpattern };
kind =
PatKind::AscribeUserType { ascription: ascription.clone(), subpattern };
}
}
@ -432,13 +434,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span);
let annotation = CanonicalUserTypeAnnotation {
user_ty,
span,
inferred_ty: self.typeck_results.node_type(hir_id),
};
kind = PatKind::AscribeUserType {
subpattern: Pat { span, ty, kind: Box::new(kind) },
ascription: Ascription {
user_ty: PatTyProj::from_user_type(user_ty),
user_ty_span: span,
variance: ty::Variance::Covariant,
},
ascription: Ascription { annotation, variance: ty::Variance::Covariant },
};
}
@ -499,18 +502,21 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
}
let user_provided_types = self.typeck_results().user_provided_types();
if let Some(u_ty) = user_provided_types.get(id) {
let user_ty = PatTyProj::from_user_type(*u_ty);
if let Some(&user_ty) = user_provided_types.get(id) {
let annotation = CanonicalUserTypeAnnotation {
user_ty,
span,
inferred_ty: self.typeck_results().node_type(id),
};
Pat {
span,
kind: Box::new(PatKind::AscribeUserType {
subpattern: pattern,
ascription: Ascription {
annotation,
/// Note that use `Contravariant` here. See the
/// `variance` field documentation for details.
variance: ty::Variance::Contravariant,
user_ty,
user_ty_span: span,
},
}),
ty: const_.ty(),
@ -645,7 +651,7 @@ impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
}
}
macro_rules! CloneImpls {
macro_rules! ClonePatternFoldableImpls {
(<$lt_tcx:tt> $($ty:ty),+) => {
$(
impl<$lt_tcx> PatternFoldable<$lt_tcx> for $ty {
@ -657,11 +663,11 @@ macro_rules! CloneImpls {
}
}
CloneImpls! { <'tcx>
ClonePatternFoldableImpls! { <'tcx>
Span, Field, Mutability, Symbol, hir::HirId, usize, ty::Const<'tcx>,
Region<'tcx>, Ty<'tcx>, BindingMode, AdtDef<'tcx>,
SubstsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>,
UserTypeProjection, PatTyProj<'tcx>
UserTypeProjection, CanonicalUserTypeAnnotation<'tcx>
}
impl<'tcx> PatternFoldable<'tcx> for FieldPat<'tcx> {
@ -694,14 +700,10 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
PatKind::Wild => PatKind::Wild,
PatKind::AscribeUserType {
ref subpattern,
ascription: Ascription { variance, ref user_ty, user_ty_span },
ascription: Ascription { ref annotation, variance },
} => PatKind::AscribeUserType {
subpattern: subpattern.fold_with(folder),
ascription: Ascription {
user_ty: user_ty.fold_with(folder),
variance,
user_ty_span,
},
ascription: Ascription { annotation: annotation.fold_with(folder), variance },
},
PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, is_primary } => {
PatKind::Binding {