Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NLL: User type annotations refactor, associated constant patterns and ref bindings. #55937

Merged
merged 11 commits into from
Jan 1, 2019
17 changes: 0 additions & 17 deletions src/librustc/ich/impls_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,22 +494,5 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::ClosureOutlivesSubj

impl_stable_hash_for!(struct mir::interpret::GlobalId<'tcx> { instance, promoted });

impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::UserTypeAnnotation<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::UserTypeAnnotation::Ty(ref ty) => {
ty.hash_stable(hcx, hasher);
}
mir::UserTypeAnnotation::TypeOf(ref def_id, ref substs) => {
def_id.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
}
}
}
}

impl_stable_hash_for!(struct mir::UserTypeProjection<'tcx> { base, projs });
impl_stable_hash_for!(struct mir::UserTypeProjections<'tcx> { contents });
26 changes: 26 additions & 0 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1251,3 +1251,29 @@ impl_stable_hash_for!(
goal,
}
);

impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::UserTypeAnnotation<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
ty::UserTypeAnnotation::Ty(ref ty) => {
ty.hash_stable(hcx, hasher);
}
ty::UserTypeAnnotation::TypeOf(ref def_id, ref substs) => {
def_id.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
}
}
}
}

impl<'a> HashStable<StableHashingContext<'a>> for ty::UserTypeAnnotationIndex {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
self.index().hash_stable(hcx, hasher);
}
}
125 changes: 92 additions & 33 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@ use syntax::ast::{self, Name};
use syntax::symbol::InternedString;
use syntax_pos::{Span, DUMMY_SP};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use ty::subst::{CanonicalUserSubsts, Subst, Substs};
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt};
use ty::subst::{Subst, Substs};
use ty::layout::VariantIdx;
use ty::{
self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
UserTypeAnnotationIndex, UserTypeAnnotation,
};
use util::ppaux;

pub use mir::interpret::AssertMessage;
Expand Down Expand Up @@ -121,6 +124,9 @@ pub struct Mir<'tcx> {
/// variables and temporaries.
pub local_decls: LocalDecls<'tcx>,

/// User type annotations
pub user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,

/// Number of arguments this function takes.
///
/// Starting at local 1, `arg_count` locals will be provided by the caller
Expand Down Expand Up @@ -161,7 +167,8 @@ impl<'tcx> Mir<'tcx> {
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
promoted: IndexVec<Promoted, Mir<'tcx>>,
yield_ty: Option<Ty<'tcx>>,
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
local_decls: LocalDecls<'tcx>,
user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
arg_count: usize,
upvar_decls: Vec<UpvarDecl>,
span: Span,
Expand All @@ -185,6 +192,7 @@ impl<'tcx> Mir<'tcx> {
generator_drop: None,
generator_layout: None,
local_decls,
user_type_annotations,
arg_count,
upvar_decls,
spread_arg: None,
Expand Down Expand Up @@ -418,6 +426,7 @@ impl_stable_hash_for!(struct Mir<'tcx> {
generator_drop,
generator_layout,
local_decls,
user_type_annotations,
arg_count,
upvar_decls,
spread_arg,
Expand Down Expand Up @@ -2232,7 +2241,7 @@ pub enum AggregateKind<'tcx> {
&'tcx AdtDef,
VariantIdx,
&'tcx Substs<'tcx>,
Option<UserTypeAnnotation<'tcx>>,
Option<UserTypeAnnotationIndex>,
Option<usize>,
),

Expand Down Expand Up @@ -2446,38 +2455,11 @@ pub struct Constant<'tcx> {
/// indicate that `Vec<_>` was explicitly specified.
///
/// Needed for NLL to impose user-given type constraints.
pub user_ty: Option<UserTypeAnnotation<'tcx>>,
pub user_ty: Option<UserTypeAnnotationIndex>,

pub literal: &'tcx ty::Const<'tcx>,
}

/// A user-given type annotation attached to a constant. These arise
/// from constants that are named via paths, like `Foo::<A>::new` and
/// so forth.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum UserTypeAnnotation<'tcx> {
Ty(CanonicalTy<'tcx>),

/// The canonical type is the result of `type_of(def_id)` with the
/// given substitutions applied.
TypeOf(DefId, CanonicalUserSubsts<'tcx>),
}

EnumTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for UserTypeAnnotation<'tcx> {
(UserTypeAnnotation::Ty)(ty),
(UserTypeAnnotation::TypeOf)(def, substs),
}
}

EnumLiftImpl! {
impl<'a, 'tcx> Lift<'tcx> for UserTypeAnnotation<'a> {
type Lifted = UserTypeAnnotation<'tcx>;
(UserTypeAnnotation::Ty)(ty),
(UserTypeAnnotation::TypeOf)(def, substs),
}
}

/// A collection of projections into user types.
///
/// They are projections because a binding can occur a part of a
Expand Down Expand Up @@ -2537,6 +2519,48 @@ impl<'tcx> UserTypeProjections<'tcx> {
pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection<'tcx>> {
self.contents.iter().map(|&(ref user_type, _span)| user_type)
}

pub fn push_projection(
mut self,
user_ty: &UserTypeProjection<'tcx>,
span: Span,
) -> Self {
self.contents.push((user_ty.clone(), span));
self
}

fn map_projections(
mut self,
mut f: impl FnMut(UserTypeProjection<'tcx>) -> UserTypeProjection<'tcx>
) -> Self {
self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
self
}

pub fn index(self) -> Self {
self.map_projections(|pat_ty_proj| pat_ty_proj.index())
}

pub fn subslice(self, from: u32, to: u32) -> Self {
self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
}

pub fn deref(self) -> Self {
self.map_projections(|pat_ty_proj| pat_ty_proj.deref())
}

pub fn leaf(self, field: Field) -> Self {
self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
}

pub fn variant(
self,
adt_def: &'tcx AdtDef,
variant_index: VariantIdx,
field: Field,
) -> Self {
self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
}
}

/// Encodes the effect of a user-supplied type annotation on the
Expand All @@ -2556,12 +2580,45 @@ impl<'tcx> UserTypeProjections<'tcx> {
/// determined by finding the type of the `.0` field from `T`.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct UserTypeProjection<'tcx> {
pub base: UserTypeAnnotation<'tcx>,
pub base: UserTypeAnnotationIndex,
pub projs: Vec<ProjectionElem<'tcx, (), ()>>,
}

impl<'tcx> Copy for ProjectionKind<'tcx> { }

impl<'tcx> UserTypeProjection<'tcx> {
pub(crate) fn index(mut self) -> Self {
self.projs.push(ProjectionElem::Index(()));
self
}

pub(crate) fn subslice(mut self, from: u32, to: u32) -> Self {
self.projs.push(ProjectionElem::Subslice { from, to });
self
}

pub(crate) fn deref(mut self) -> Self {
self.projs.push(ProjectionElem::Deref);
self
}

pub(crate) fn leaf(mut self, field: Field) -> Self {
self.projs.push(ProjectionElem::Field(field, ()));
self
}

pub(crate) fn variant(
mut self,
adt_def: &'tcx AdtDef,
variant_index: VariantIdx,
field: Field,
) -> Self {
self.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
self.projs.push(ProjectionElem::Field(field, ()));
self
}
}

CloneTypeFoldableAndLiftImpls! { ProjectionKind<'tcx>, }

impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> {
Expand Down Expand Up @@ -2970,6 +3027,7 @@ CloneTypeFoldableAndLiftImpls! {
SourceScope,
SourceScopeData,
SourceScopeLocalData,
UserTypeAnnotationIndex,
}

BraceStructTypeFoldableImpl! {
Expand All @@ -2983,6 +3041,7 @@ BraceStructTypeFoldableImpl! {
generator_drop,
generator_layout,
local_decls,
user_type_annotations,
arg_count,
upvar_decls,
spread_arg,
Expand Down
24 changes: 15 additions & 9 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use hir::def_id::DefId;
use infer::canonical::Canonical;
use ty::subst::Substs;
use ty::{ClosureSubsts, GeneratorSubsts, Region, Ty};
use mir::*;
Expand Down Expand Up @@ -219,9 +220,10 @@ macro_rules! make_mir_visitor {

fn visit_user_type_annotation(
&mut self,
ty: & $($mutability)* UserTypeAnnotation<'tcx>,
index: UserTypeAnnotationIndex,
ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>,
) {
self.super_user_type_annotation(ty);
self.super_user_type_annotation(index, ty);
}

fn visit_region(&mut self,
Expand Down Expand Up @@ -307,6 +309,14 @@ macro_rules! make_mir_visitor {
self.visit_local_decl(local, & $($mutability)* mir.local_decls[local]);
}

for index in mir.user_type_annotations.indices() {
let (span, annotation) = & $($mutability)* mir.user_type_annotations[index];
self.visit_user_type_annotation(
index, annotation
);
self.visit_span(span);
}

self.visit_span(&$($mutability)* mir.span);
}

Expand Down Expand Up @@ -865,18 +875,14 @@ macro_rules! make_mir_visitor {

fn super_user_type_projection(
&mut self,
ty: & $($mutability)* UserTypeProjection<'tcx>,
_ty: & $($mutability)* UserTypeProjection<'tcx>,
) {
let UserTypeProjection {
ref $($mutability)* base,
projs: _, // Note: Does not visit projection elems!
} = *ty;
self.visit_user_type_annotation(base);
}

fn super_user_type_annotation(
&mut self,
_ty: & $($mutability)* UserTypeAnnotation<'tcx>,
_index: UserTypeAnnotationIndex,
_ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>,
) {
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/query/type_op/ascribe_user_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl<'tcx> AscribeUserType<'tcx> {
user_substs: UserSubsts<'tcx>,
projs: &'tcx ty::List<ProjectionKind<'tcx>>,
) -> Self {
AscribeUserType { mir_ty, variance, def_id, user_substs, projs }
Self { mir_ty, variance, def_id, user_substs, projs }
}
}

Expand Down
Loading