Skip to content

Commit

Permalink
Auto merge of #55937 - davidtwco:issue-54943, r=pnkfelix
Browse files Browse the repository at this point in the history
NLL: User type annotations refactor, associated constant patterns and ref bindings.

Fixes #55511 and Fixes #55401. Contributes to #54943.

This PR performs a large refactoring on user type annotations, checks user type annotations for associated constants in patterns and that user type annotations for `ref` bindings are respected.

r? @nikomatsakis
  • Loading branch information
bors committed Jan 1, 2019
2 parents 36500de + c20ba65 commit cae1647
Show file tree
Hide file tree
Showing 47 changed files with 804 additions and 500 deletions.
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

0 comments on commit cae1647

Please sign in to comment.