correctly deal with user type ascriptions in pat
This commit is contained in:
parent
4a86c7907b
commit
39a03779f8
12 changed files with 208 additions and 103 deletions
|
@ -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,
|
||||
),
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue