Checkpoint: Added abstraction over collection of projections into user type.
I did not think I would need this in the MIR, but in general local decls are going to need to support this. (That, or we need to be able define a least-upper-bound for a collection of types encountered via the pattern compilation.)
This commit is contained in:
parent
28ce99df86
commit
b569caf267
@ -608,3 +608,4 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::UserTypeAnnotation<
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct mir::UserTypeProjection<'tcx> { base });
|
||||
impl_stable_hash_for!(struct mir::UserTypeProjections<'tcx> { contents });
|
||||
|
@ -710,7 +710,7 @@ pub struct LocalDecl<'tcx> {
|
||||
/// e.g. via `let x: T`, then we carry that type here. The MIR
|
||||
/// borrow checker needs this information since it can affect
|
||||
/// region inference.
|
||||
pub user_ty: Option<(UserTypeProjection<'tcx>, Span)>,
|
||||
pub user_ty: UserTypeProjections<'tcx>,
|
||||
|
||||
/// Name of the local, used in debuginfo and pretty-printing.
|
||||
///
|
||||
@ -882,7 +882,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
LocalDecl {
|
||||
mutability,
|
||||
ty,
|
||||
user_ty: None,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
name: None,
|
||||
source_info: SourceInfo {
|
||||
span,
|
||||
@ -903,7 +903,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: return_ty,
|
||||
user_ty: None,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
source_info: SourceInfo {
|
||||
span,
|
||||
scope: OUTERMOST_SOURCE_SCOPE,
|
||||
@ -2449,6 +2449,42 @@ EnumLiftImpl! {
|
||||
}
|
||||
}
|
||||
|
||||
/// A collection of projections into user types.
|
||||
///
|
||||
/// They are projections because a binding can occur a part of a
|
||||
/// parent pattern that has been ascribed a type.
|
||||
///
|
||||
/// Its a collection because there can be multiple type ascriptions on
|
||||
/// the path from the root of the pattern down to the binding itself.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct UserTypeProjections<'tcx> {
|
||||
pub(crate) contents: Vec<(UserTypeProjection<'tcx>, Span)>,
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections<'tcx> {
|
||||
contents
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UserTypeProjections<'tcx> {
|
||||
pub fn none() -> Self {
|
||||
UserTypeProjections { contents: vec![] }
|
||||
}
|
||||
|
||||
pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection<'tcx>, Span)>) -> Self {
|
||||
UserTypeProjections { contents: projs.collect() }
|
||||
}
|
||||
|
||||
pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection<'tcx>, Span)> {
|
||||
self.contents.iter()
|
||||
}
|
||||
|
||||
pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection<'tcx>> {
|
||||
self.contents.iter().map(|&(ref user_type, _span)| user_type)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct UserTypeProjection<'tcx> {
|
||||
pub base: UserTypeAnnotation<'tcx>,
|
||||
|
@ -743,7 +743,7 @@ macro_rules! make_mir_visitor {
|
||||
local,
|
||||
source_info: *source_info,
|
||||
});
|
||||
if let Some((user_ty, _)) = user_ty {
|
||||
for (user_ty, _) in & $($mutability)* user_ty.contents {
|
||||
self.visit_user_type_projection(user_ty);
|
||||
}
|
||||
self.visit_source_info(source_info);
|
||||
|
@ -284,7 +284,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||
constant.ty,
|
||||
ty::Variance::Invariant,
|
||||
UserTypeProjection { base: user_ty },
|
||||
&UserTypeProjection { base: user_ty },
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
) {
|
||||
@ -310,12 +310,12 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||
self.super_local_decl(local, local_decl);
|
||||
self.sanitize_type(local_decl, local_decl.ty);
|
||||
|
||||
if let Some((user_ty, span)) = local_decl.user_ty {
|
||||
for (user_ty, span) in local_decl.user_ty.projections_and_spans() {
|
||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||
local_decl.ty,
|
||||
ty::Variance::Invariant,
|
||||
user_ty,
|
||||
Locations::All(span),
|
||||
Locations::All(*span),
|
||||
ConstraintCategory::TypeAnnotation,
|
||||
) {
|
||||
span_mirbug!(
|
||||
@ -971,7 +971,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
&mut self,
|
||||
a: Ty<'tcx>,
|
||||
v: ty::Variance,
|
||||
user_ty: UserTypeProjection<'tcx>,
|
||||
user_ty: &UserTypeProjection<'tcx>,
|
||||
locations: Locations,
|
||||
category: ConstraintCategory,
|
||||
) -> Fallible<()> {
|
||||
@ -1173,7 +1173,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
if let Err(terr) = self.relate_type_and_user_type(
|
||||
rv_ty,
|
||||
ty::Variance::Invariant,
|
||||
UserTypeProjection { base: user_ty },
|
||||
&UserTypeProjection { base: user_ty },
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
) {
|
||||
@ -1226,7 +1226,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
);
|
||||
};
|
||||
}
|
||||
StatementKind::AscribeUserType(ref place, variance, box c_ty) => {
|
||||
StatementKind::AscribeUserType(ref place, variance, box ref c_ty) => {
|
||||
let place_ty = place.ty(mir, tcx).to_ty(tcx);
|
||||
if let Err(terr) = self.relate_type_and_user_type(
|
||||
place_ty,
|
||||
|
@ -151,10 +151,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
None, remainder_span, lint_level, slice::from_ref(&pattern),
|
||||
ArmHasGuard(false), None);
|
||||
|
||||
this.visit_bindings(&pattern, None, &mut |this, _, _, _, node, span, _, _| {
|
||||
this.storage_live_binding(block, node, span, OutsideGuard);
|
||||
this.schedule_drop_for_binding(node, span, OutsideGuard);
|
||||
})
|
||||
this.visit_bindings(
|
||||
&pattern,
|
||||
&PatternTypeProjections::none(),
|
||||
&mut |this, _, _, _, node, span, _, _| {
|
||||
this.storage_live_binding(block, node, span, OutsideGuard);
|
||||
this.schedule_drop_for_binding(node, span, OutsideGuard);
|
||||
})
|
||||
}
|
||||
|
||||
// Enter the source scope, after evaluating the initializer.
|
||||
|
@ -306,7 +306,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let ptr_temp = this.local_decls.push(LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: ptr_ty,
|
||||
user_ty: None,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
name: None,
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
|
@ -18,6 +18,7 @@ use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard};
|
||||
use build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
|
||||
use hair::*;
|
||||
use hair::pattern::PatternTypeProjections;
|
||||
use rustc::hir;
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::{self, Ty};
|
||||
@ -415,7 +416,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let num_patterns = patterns.len();
|
||||
self.visit_bindings(
|
||||
&patterns[0],
|
||||
None,
|
||||
&PatternTypeProjections::none(),
|
||||
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
|
||||
if visibility_scope.is_none() {
|
||||
visibility_scope =
|
||||
@ -491,7 +492,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
pub(super) fn visit_bindings(
|
||||
&mut self,
|
||||
pattern: &Pattern<'tcx>,
|
||||
mut pattern_user_ty: Option<(PatternTypeProjection<'tcx>, Span)>,
|
||||
pattern_user_ty: &PatternTypeProjections<'tcx>,
|
||||
f: &mut impl FnMut(
|
||||
&mut Self,
|
||||
Mutability,
|
||||
@ -500,7 +501,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
NodeId,
|
||||
Span,
|
||||
Ty<'tcx>,
|
||||
Option<(PatternTypeProjection<'tcx>, Span)>,
|
||||
&PatternTypeProjections<'tcx>,
|
||||
),
|
||||
) {
|
||||
match *pattern.kind {
|
||||
@ -513,20 +514,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ref subpattern,
|
||||
..
|
||||
} => {
|
||||
match mode {
|
||||
BindingMode::ByValue => { }
|
||||
let pattern_ref_binding; // sidestep temp lifetime limitations.
|
||||
let binding_user_ty = match mode {
|
||||
BindingMode::ByValue => { pattern_user_ty }
|
||||
BindingMode::ByRef(..) => {
|
||||
// If this is a `ref` binding (e.g., `let ref
|
||||
// x: T = ..`), then the type of `x` is not
|
||||
// `T` but rather `&T`, so ignore
|
||||
// `pattern_user_ty` for now.
|
||||
//
|
||||
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
|
||||
pattern_user_ty = None;
|
||||
// `T` but rather `&T`.
|
||||
pattern_ref_binding = pattern_user_ty.ref_binding();
|
||||
&pattern_ref_binding
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty);
|
||||
f(self, mutability, name, mode, var, pattern.span, ty, binding_user_ty);
|
||||
if let Some(subpattern) = subpattern.as_ref() {
|
||||
self.visit_bindings(subpattern, pattern_user_ty, f);
|
||||
}
|
||||
@ -541,15 +541,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ref slice,
|
||||
ref suffix,
|
||||
} => {
|
||||
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
|
||||
for subpattern in prefix.iter().chain(slice).chain(suffix) {
|
||||
self.visit_bindings(subpattern, None, f);
|
||||
for subpattern in prefix {
|
||||
self.visit_bindings(subpattern, &pattern_user_ty.index(), f);
|
||||
}
|
||||
for subpattern in slice {
|
||||
self.visit_bindings(subpattern, &pattern_user_ty.subslice(), f);
|
||||
}
|
||||
for subpattern in suffix {
|
||||
self.visit_bindings(subpattern, &pattern_user_ty.index(), f);
|
||||
}
|
||||
}
|
||||
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {}
|
||||
PatternKind::Deref { ref subpattern } => {
|
||||
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
|
||||
self.visit_bindings(subpattern, None, f);
|
||||
self.visit_bindings(subpattern, &pattern_user_ty.deref(), f);
|
||||
}
|
||||
PatternKind::AscribeUserType { ref subpattern, user_ty, user_ty_span } => {
|
||||
// This corresponds to something like
|
||||
@ -557,17 +561,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
// ```
|
||||
// let A::<'a>(_): A<'static> = ...;
|
||||
// ```
|
||||
//
|
||||
// FIXME(#47184): handle `pattern_user_ty` somehow
|
||||
self.visit_bindings(subpattern, Some((user_ty, user_ty_span)), f)
|
||||
let pattern_user_ty = pattern_user_ty.add_user_type(user_ty, user_ty_span);
|
||||
self.visit_bindings(subpattern, &pattern_user_ty, f)
|
||||
}
|
||||
PatternKind::Leaf { ref subpatterns }
|
||||
| PatternKind::Variant {
|
||||
ref subpatterns, ..
|
||||
} => {
|
||||
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
|
||||
for subpattern in subpatterns {
|
||||
self.visit_bindings(&subpattern.pattern, None, f);
|
||||
|
||||
PatternKind::Leaf { ref subpatterns } => {
|
||||
for (j, subpattern) in subpatterns.iter().enumerate() {
|
||||
self.visit_bindings(&subpattern.pattern, &pattern_user_ty.leaf(j), f);
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Variant { ref subpatterns, .. } => {
|
||||
for (j, subpattern) in subpatterns.iter().enumerate() {
|
||||
self.visit_bindings(&subpattern.pattern, &pattern_user_ty.variant(j), f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1470,7 +1476,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
num_patterns: usize,
|
||||
var_id: NodeId,
|
||||
var_ty: Ty<'tcx>,
|
||||
user_var_ty: Option<(PatternTypeProjection<'tcx>, Span)>,
|
||||
user_var_ty: &PatternTypeProjections<'tcx>,
|
||||
has_guard: ArmHasGuard,
|
||||
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
|
||||
pat_span: Span,
|
||||
@ -1489,7 +1495,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let local = LocalDecl::<'tcx> {
|
||||
mutability,
|
||||
ty: var_ty,
|
||||
user_ty: user_var_ty.map(|(ut, sp)| (ut.user_ty(), sp)),
|
||||
user_ty: user_var_ty.clone().user_ty(),
|
||||
name: Some(name),
|
||||
source_info,
|
||||
visibility_scope,
|
||||
@ -1522,7 +1528,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
// See previous comment.
|
||||
mutability: Mutability::Not,
|
||||
ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty),
|
||||
user_ty: None,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
name: Some(name),
|
||||
source_info,
|
||||
visibility_scope,
|
||||
|
@ -845,7 +845,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
self.local_decls.push(LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty,
|
||||
user_ty: None,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
name,
|
||||
|
@ -27,7 +27,8 @@ use self::cx::Cx;
|
||||
pub mod cx;
|
||||
|
||||
pub mod pattern;
|
||||
pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternTypeProjection, FieldPattern};
|
||||
pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
|
||||
pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
|
||||
|
||||
mod util;
|
||||
|
||||
|
@ -21,7 +21,7 @@ use const_eval::{const_field, const_variant_index};
|
||||
use hair::util::UserAnnotatedTyHelpers;
|
||||
|
||||
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
|
||||
use rustc::mir::{UserTypeAnnotation, UserTypeProjection};
|
||||
use rustc::mir::{UserTypeAnnotation, UserTypeProjection, UserTypeProjections};
|
||||
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
|
||||
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty};
|
||||
use rustc::ty::subst::{Substs, Kind};
|
||||
@ -65,6 +65,54 @@ pub struct Pattern<'tcx> {
|
||||
pub kind: Box<PatternKind<'tcx>>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct PatternTypeProjections<'tcx> {
|
||||
contents: Vec<(PatternTypeProjection<'tcx>, Span)>,
|
||||
}
|
||||
|
||||
impl<'tcx> PatternTypeProjections<'tcx> {
|
||||
pub(crate) fn user_ty(self) -> UserTypeProjections<'tcx> {
|
||||
UserTypeProjections::from_projections(
|
||||
self.contents.into_iter().map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(), span)))
|
||||
}
|
||||
|
||||
pub(crate) fn none() -> Self {
|
||||
PatternTypeProjections { contents: vec![] }
|
||||
}
|
||||
|
||||
pub(crate) fn ref_binding(&self) -> Self {
|
||||
// FIXME(#47184): ignore for now
|
||||
PatternTypeProjections { contents: vec![] }
|
||||
}
|
||||
|
||||
pub(crate) fn index(&self) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub(crate) fn subslice(&self) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub(crate) fn deref(&self) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub(crate) fn add_user_type(&self, user_ty: PatternTypeProjection<'tcx>, sp: Span) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.contents.push((user_ty, sp));
|
||||
new
|
||||
}
|
||||
|
||||
pub(crate) fn leaf(&self, _index: usize) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub(crate) fn variant(&self, _index: usize) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct PatternTypeProjection<'tcx>(UserTypeProjection<'tcx>);
|
||||
|
||||
|
@ -142,7 +142,7 @@ fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
|
||||
LocalDecl {
|
||||
mutability,
|
||||
ty,
|
||||
user_ty: None,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
name: None,
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
|
@ -303,7 +303,7 @@ fn replace_result_variable<'tcx>(
|
||||
let new_ret = LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: ret_ty,
|
||||
user_ty: None,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
name: None,
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
@ -658,7 +658,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
|
||||
mir.local_decls[RETURN_PLACE] = LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: tcx.mk_unit(),
|
||||
user_ty: None,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
name: None,
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
@ -676,7 +676,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
|
||||
ty: gen_ty,
|
||||
mutbl: hir::Mutability::MutMutable,
|
||||
}),
|
||||
user_ty: None,
|
||||
user_ty: UserTypeProjections::none(),
|
||||
name: None,
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
|
@ -502,7 +502,7 @@ fn write_scope_tree(
|
||||
local,
|
||||
var.ty
|
||||
);
|
||||
if let Some(user_ty) = var.user_ty {
|
||||
for user_ty in var.user_ty.projections() {
|
||||
write!(indented_var, " as {:?}", user_ty).unwrap();
|
||||
}
|
||||
indented_var.push_str(";");
|
||||
|
Loading…
x
Reference in New Issue
Block a user