Skip to content

Commit

Permalink
Auto merge of #57714 - matthewjasper:wellformed-unreachable, r=pnkfelix
Browse files Browse the repository at this point in the history
[NLL] Clean up handling of type annotations

* Renames (Canonical)?UserTypeAnnotation -> (Canonical)?UserType so that the name CanonicalUserTypeAnnotation is free.
* Keep the inferred type associated to user type annotations in the MIR, so that it can be compared against the annotated type, even when the annotated expression gets removed from the MIR. (#54943)
* Use the inferred type to allow infallible handling of user type projections (#57531)
* Uses revisions for the tests in #56993
* Check the types of `Unevaluated` constants with no annotations (#46702)
* Some drive-by cleanup

Closes #46702
Closes #54943
Closes #57531
Closes #57731
cc #56993 leaving this open to track the underlying issue: we are not running tests with full NLL enabled on CI at the moment

r? @nikomatsakis
  • Loading branch information
bors committed Jan 25, 2019
2 parents 7187db6 + 620a03f commit 0b1669d
Show file tree
Hide file tree
Showing 49 changed files with 849 additions and 291 deletions.
12 changes: 9 additions & 3 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1240,16 +1240,22 @@ impl_stable_hash_for!(
}
);

impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::UserTypeAnnotation<'gcx> {
impl_stable_hash_for!(
struct ty::CanonicalUserTypeAnnotation<'tcx> {
user_ty, span, inferred_ty
}
);

impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::UserType<'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::UserType::Ty(ref ty) => {
ty.hash_stable(hcx, hasher);
}
ty::UserTypeAnnotation::TypeOf(ref def_id, ref substs) => {
ty::UserType::TypeOf(ref def_id, ref substs) => {
def_id.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use ty::subst::{Subst, Substs};
use ty::layout::VariantIdx;
use ty::{
self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
UserTypeAnnotationIndex, UserTypeAnnotation,
UserTypeAnnotationIndex,
};
use util::ppaux;

Expand Down
13 changes: 6 additions & 7 deletions src/librustc/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,20 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
elem: &PlaceElem<'tcx>)
-> PlaceTy<'tcx>
{
self.projection_ty_core(tcx, elem, |_, _, ty| -> Result<Ty<'tcx>, ()> { Ok(ty) })
.unwrap()
self.projection_ty_core(tcx, elem, |_, _, ty| ty)
}

/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
/// projects `place_ty` onto `elem`, returning the appropriate
/// `Ty` or downcast variant corresponding to that projection.
/// The `handle_field` callback must map a `Field` to its `Ty`,
/// (which should be trivial when `T` = `Ty`).
pub fn projection_ty_core<V, T, E>(
pub fn projection_ty_core<V, T>(
self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
elem: &ProjectionElem<'tcx, V, T>,
mut handle_field: impl FnMut(&Self, &Field, &T) -> Result<Ty<'tcx>, E>)
-> Result<PlaceTy<'tcx>, E>
mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>)
-> PlaceTy<'tcx>
where
V: ::std::fmt::Debug, T: ::std::fmt::Debug
{
Expand Down Expand Up @@ -140,10 +139,10 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
}
},
ProjectionElem::Field(ref f, ref fty) =>
PlaceTy::Ty { ty: handle_field(&self, f, fty)? },
PlaceTy::Ty { ty: handle_field(&self, f, fty) },
};
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
Ok(answer)
answer
}
}

Expand Down
21 changes: 14 additions & 7 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use hir::def_id::DefId;
use infer::canonical::Canonical;
use ty::subst::Substs;
use ty::{ClosureSubsts, GeneratorSubsts, Region, Ty};
use ty::{CanonicalUserTypeAnnotation, ClosureSubsts, GeneratorSubsts, Region, Ty};
use mir::*;
use syntax_pos::Span;

Expand Down Expand Up @@ -221,7 +220,7 @@ macro_rules! make_mir_visitor {
fn visit_user_type_annotation(
&mut self,
index: UserTypeAnnotationIndex,
ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>,
ty: & $($mutability)* CanonicalUserTypeAnnotation<'tcx>,
) {
self.super_user_type_annotation(index, ty);
}
Expand Down Expand Up @@ -309,12 +308,15 @@ 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];
macro_rules! type_annotations {
(mut) => (mir.user_type_annotations.iter_enumerated_mut());
() => (mir.user_type_annotations.iter_enumerated());
};

for (index, annotation) in type_annotations!($($mutability)*) {
self.visit_user_type_annotation(
index, annotation
);
self.visit_span(span);
}

self.visit_span(&$($mutability)* mir.span);
Expand Down Expand Up @@ -882,8 +884,10 @@ macro_rules! make_mir_visitor {
fn super_user_type_annotation(
&mut self,
_index: UserTypeAnnotationIndex,
_ty: & $($mutability)* Canonical<'tcx, UserTypeAnnotation<'tcx>>,
ty: & $($mutability)* CanonicalUserTypeAnnotation<'tcx>,
) {
self.visit_span(& $($mutability)* ty.span);
self.visit_ty(& $($mutability)* ty.inferred_ty, TyContext::UserTy(ty.span));
}

fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
Expand Down Expand Up @@ -964,6 +968,9 @@ pub enum TyContext {
source_info: SourceInfo,
},

/// The inferred type of a user type annotation.
UserTy(Span),

/// The return type of the function.
ReturnTy(SourceInfo),

Expand Down
15 changes: 5 additions & 10 deletions src/librustc/traits/query/type_op/ascribe_user_type.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
use traits::query::Fallible;
use hir::def_id::DefId;
use mir::ProjectionKind;
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
use ty::{ParamEnvAnd, Ty, TyCtxt};
use ty::subst::UserSubsts;

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct AscribeUserType<'tcx> {
pub mir_ty: Ty<'tcx>,
pub variance: ty::Variance,
pub def_id: DefId,
pub user_substs: UserSubsts<'tcx>,
pub projs: &'tcx ty::List<ProjectionKind<'tcx>>,
}

impl<'tcx> AscribeUserType<'tcx> {
pub fn new(
mir_ty: Ty<'tcx>,
variance: ty::Variance,
def_id: DefId,
user_substs: UserSubsts<'tcx>,
projs: &'tcx ty::List<ProjectionKind<'tcx>>,
) -> Self {
Self { mir_ty, variance, def_id, user_substs, projs }
Self { mir_ty, def_id, user_substs }
}
}

Expand Down Expand Up @@ -52,19 +47,19 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for AscribeUserType<'tcx>

BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for AscribeUserType<'tcx> {
mir_ty, variance, def_id, user_substs, projs
mir_ty, def_id, user_substs
}
}

BraceStructLiftImpl! {
impl<'a, 'tcx> Lift<'tcx> for AscribeUserType<'a> {
type Lifted = AscribeUserType<'tcx>;
mir_ty, variance, def_id, user_substs, projs
mir_ty, def_id, user_substs
}
}

impl_stable_hash_for! {
struct AscribeUserType<'tcx> {
mir_ty, variance, def_id, user_substs, projs
mir_ty, def_id, user_substs
}
}
55 changes: 38 additions & 17 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ pub struct TypeckTables<'tcx> {
/// canonical substitutions would include only `for<X> { Vec<X> }`.
///
/// See also `AscribeUserType` statement in MIR.
user_provided_types: ItemLocalMap<CanonicalUserTypeAnnotation<'tcx>>,
user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,

/// Stores the canonicalized types provided by the user. See also
/// `AscribeUserType` statement in MIR.
Expand Down Expand Up @@ -493,7 +493,7 @@ impl<'tcx> TypeckTables<'tcx> {

pub fn user_provided_types(
&self
) -> LocalTableInContext<'_, CanonicalUserTypeAnnotation<'tcx>> {
) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
LocalTableInContext {
local_id_root: self.local_id_root,
data: &self.user_provided_types
Expand All @@ -502,7 +502,7 @@ impl<'tcx> TypeckTables<'tcx> {

pub fn user_provided_types_mut(
&mut self
) -> LocalTableInContextMut<'_, CanonicalUserTypeAnnotation<'tcx>> {
) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
LocalTableInContextMut {
local_id_root: self.local_id_root,
data: &mut self.user_provided_types
Expand Down Expand Up @@ -800,25 +800,46 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {

newtype_index! {
pub struct UserTypeAnnotationIndex {
DEBUG_FORMAT = "UserTypeAnnotation({})",
DEBUG_FORMAT = "UserType({})",
const START_INDEX = 0,
}
}

/// Mapping of type annotation indices to canonical user type annotations.
pub type CanonicalUserTypeAnnotations<'tcx> =
IndexVec<UserTypeAnnotationIndex, (Span, CanonicalUserTypeAnnotation<'tcx>)>;
IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct CanonicalUserTypeAnnotation<'tcx> {
pub user_ty: CanonicalUserType<'tcx>,
pub span: Span,
pub inferred_ty: Ty<'tcx>,
}

BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for CanonicalUserTypeAnnotation<'tcx> {
user_ty, span, inferred_ty
}
}

BraceStructLiftImpl! {
impl<'a, 'tcx> Lift<'tcx> for CanonicalUserTypeAnnotation<'a> {
type Lifted = CanonicalUserTypeAnnotation<'tcx>;
user_ty, span, inferred_ty
}
}


/// Canonicalized user type annotation.
pub type CanonicalUserTypeAnnotation<'gcx> = Canonical<'gcx, UserTypeAnnotation<'gcx>>;
pub type CanonicalUserType<'gcx> = Canonical<'gcx, UserType<'gcx>>;

impl CanonicalUserTypeAnnotation<'gcx> {
impl CanonicalUserType<'gcx> {
/// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
/// i.e. each thing is mapped to a canonical variable with the same index.
pub fn is_identity(&self) -> bool {
match self.value {
UserTypeAnnotation::Ty(_) => false,
UserTypeAnnotation::TypeOf(_, user_substs) => {
UserType::Ty(_) => false,
UserType::TypeOf(_, user_substs) => {
if user_substs.user_self_ty.is_some() {
return false;
}
Expand Down Expand Up @@ -853,7 +874,7 @@ impl CanonicalUserTypeAnnotation<'gcx> {
/// 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> {
pub enum UserType<'tcx> {
Ty(Ty<'tcx>),

/// The canonical type is the result of `type_of(def_id)` with the
Expand All @@ -862,17 +883,17 @@ pub enum UserTypeAnnotation<'tcx> {
}

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

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

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ pub use self::binding::BindingMode::*;
pub use self::context::{TyCtxt, FreeRegionInfo, GlobalArenas, AllArenas, tls, keep_local};
pub use self::context::{Lift, TypeckTables, CtxtInterners};
pub use self::context::{
UserTypeAnnotationIndex, UserTypeAnnotation, CanonicalUserTypeAnnotation,
CanonicalUserTypeAnnotations,
UserTypeAnnotationIndex, UserType, CanonicalUserType,
CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
};

pub use self::instance::{Instance, InstanceDef};
Expand Down
11 changes: 6 additions & 5 deletions src/librustc_mir/borrow_check/nll/constraint_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rustc::infer::InferCtxt;
use rustc::mir::visit::TyContext;
use rustc::mir::visit::Visitor;
use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
use rustc::mir::{Statement, Terminator};
use rustc::mir::{SourceInfo, Statement, Terminator};
use rustc::mir::UserTypeProjection;
use rustc::ty::fold::TypeFoldable;
use rustc::ty::subst::Substs;
Expand Down Expand Up @@ -66,11 +66,12 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
/// call. Make them live at the location where they appear.
fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
match ty_context {
TyContext::ReturnTy(source_info)
| TyContext::YieldTy(source_info)
| TyContext::LocalDecl { source_info, .. } => {
TyContext::ReturnTy(SourceInfo { span, .. })
| TyContext::YieldTy(SourceInfo { span, .. })
| TyContext::UserTy(span)
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
span_bug!(
source_info.span,
span,
"should not be visiting outside of the CFG: {:?}",
ty_context
);
Expand Down
18 changes: 1 addition & 17 deletions src/librustc_mir/borrow_check/nll/renumber.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
use rustc::infer::canonical::Canonical;
use rustc::ty::subst::Substs;
use rustc::ty::{
self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable, UserTypeAnnotation,
UserTypeAnnotationIndex,
};
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
use rustc::mir::{Location, Mir};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
Expand Down Expand Up @@ -59,18 +55,6 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
debug!("visit_ty: ty={:?}", ty);
}

fn visit_user_type_annotation(
&mut self,
_index: UserTypeAnnotationIndex,
_ty: &mut Canonical<'tcx, UserTypeAnnotation<'tcx>>,
) {
// User type annotations represent the types that the user
// wrote in the progarm. We don't want to erase the regions
// from these types: rather, we want to add them as
// constraints at type-check time.
debug!("visit_user_type_annotation: skipping renumber");
}

fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
debug!("visit_substs(substs={:?}, location={:?})", substs, location);

Expand Down
Loading

0 comments on commit 0b1669d

Please sign in to comment.