]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #57714 - matthewjasper:wellformed-unreachable, r=pnkfelix
authorbors <bors@rust-lang.org>
Fri, 25 Jan 2019 14:25:37 +0000 (14:25 +0000)
committerbors <bors@rust-lang.org>
Fri, 25 Jan 2019 14:25:37 +0000 (14:25 +0000)
[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

49 files changed:
src/librustc/ich/impls_ty.rs
src/librustc/mir/mod.rs
src/librustc/mir/tcx.rs
src/librustc/mir/visit.rs
src/librustc/traits/query/type_op/ascribe_user_type.rs
src/librustc/ty/context.rs
src/librustc/ty/mod.rs
src/librustc_mir/borrow_check/nll/constraint_generation.rs
src/librustc_mir/borrow_check/nll/renumber.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/build/expr/as_constant.rs
src/librustc_mir/build/expr/as_place.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/hair/util.rs
src/librustc_mir/util/pretty.rs
src/librustc_traits/type_op.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/writeback.rs
src/test/mir-opt/basic_assignment.rs
src/test/mir-opt/retag.rs
src/test/ui/issue-54943.rs
src/test/ui/issue-54943.stderr [new file with mode: 0644]
src/test/ui/issues/issue-57866.rs [new file with mode: 0644]
src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr
src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr
src/test/ui/nll/ty-outlives/wf-unreachable.rs [new file with mode: 0644]
src/test/ui/nll/ty-outlives/wf-unreachable.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr [new file with mode: 0644]
src/test/ui/nll/user-annotations/downcast-infer.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs [new file with mode: 0644]
src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr [new file with mode: 0644]
src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.ast.stderr [new file with mode: 0644]
src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.mir.stderr [new file with mode: 0644]
src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs
src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr [new file with mode: 0644]
src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr [new file with mode: 0644]
src/test/ui/regions/regions-free-region-ordering-caller.rs
src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr
src/test/ui/regions/regions-outlives-projection-container-hrtb.ast.stderr [new file with mode: 0644]
src/test/ui/regions/regions-outlives-projection-container-hrtb.mir.stderr [new file with mode: 0644]
src/test/ui/regions/regions-outlives-projection-container-hrtb.rs
src/test/ui/regions/regions-outlives-projection-container-wc.ast.stderr [new file with mode: 0644]
src/test/ui/regions/regions-outlives-projection-container-wc.mir.stderr [new file with mode: 0644]
src/test/ui/regions/regions-outlives-projection-container-wc.rs

index ef7fb0128ef4b4740df08cde6ccc5461469b4b3c..79c2b89522dbf4683123e7b22723eb9dd4430007 100644 (file)
@@ -1240,16 +1240,22 @@ impl<'tcx, G> for struct traits::InEnvironment<'tcx, G> {
     }
 );
 
-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);
             }
index a1a6e890b1292de4691455187d3226128c357283..f824ab7e5b39546c4c989a827b346b4b237067ea 100644 (file)
@@ -31,7 +31,7 @@
 use ty::layout::VariantIdx;
 use ty::{
     self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
-    UserTypeAnnotationIndex, UserTypeAnnotation,
+    UserTypeAnnotationIndex,
 };
 use util::ppaux;
 
index c5b884525da4b29a027848496487de15cc63c852..649370059f0ea7e01c18e1b87f2ce38ae91d2e4e 100644 (file)
@@ -75,8 +75,7 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, '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, |...| { ... })`
@@ -84,12 +83,12 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
     /// `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
     {
@@ -140,10 +139,10 @@ pub fn projection_ty_core<V, T, E>(
                     }
                 },
             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
     }
 }
 
index a0fae3aa927ce3f5f6d72eca981e9c453a44ea41..598303f29328fb8cb883ef787dcbad0a2b64b055 100644 (file)
@@ -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;
 
@@ -221,7 +220,7 @@ fn visit_user_type_projection(
             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);
             }
@@ -309,12 +308,15 @@ macro_rules! basic_blocks {
                     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);
@@ -882,8 +884,10 @@ fn super_user_type_projection(
             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>) {
@@ -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),
 
index b2f30564de93a5d387a7fe19a666d892df02691b..15f627b3ee8c4ab4d4c0694b8a2f74ecd1262718 100644 (file)
@@ -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 }
     }
 }
 
@@ -52,19 +47,19 @@ fn shrink_to_tcx_lifetime(
 
 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
     }
 }
index e37eab622df3f062e79e48783f064dc38c527868..4c8f81411163c374a2c464815376fef0f41bf4db 100644 (file)
@@ -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.
@@ -493,7 +493,7 @@ pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, usize> {
 
     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
@@ -502,7 +502,7 @@ pub fn user_provided_types(
 
     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
@@ -800,25 +800,46 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 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;
                 }
@@ -853,7 +874,7 @@ pub fn is_identity(&self) -> bool {
 /// 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
@@ -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),
     }
 }
 
index dd315cf42ce7e78a42801d71d16db690a5d84780..930bbc0888517a0e78f9d72b20eaa88cc1817574 100644 (file)
@@ -73,8 +73,8 @@
 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};
index e1c2b611d011700ec721c2f40948a45baced9b63..588f46cb77fe26f845e342178d8567d63911843b 100644 (file)
@@ -7,7 +7,7 @@
 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;
@@ -66,11 +66,12 @@ fn visit_region(&mut self, region: &ty::Region<'tcx>, location: Location) {
     /// 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
                 );
index 5c24da7621b2d827626fd7b7d799d0a0841a50d2..e6a974fd8cc94d92407d9eead619066d866305d9 100644 (file)
@@ -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};
@@ -59,18 +55,6 @@ fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
         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);
 
index 180aa1907e8d140eafa62076edc8b17217f20611..3e6aa358ee0d15d1d7491cd34f9bf2b1ff85225e 100644 (file)
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{Subst, Substs, UnpackedKind};
+use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSubsts};
 use rustc::ty::{
-    self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserTypeAnnotation,
-    UserTypeAnnotationIndex,
+    self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserType,
+    CanonicalUserTypeAnnotation, UserTypeAnnotationIndex,
 };
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -283,7 +283,7 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
                 location.to_locations(),
                 ConstraintCategory::Boring,
             ) {
-                let annotation = self.cx.instantiated_type_annotations[&annotation_index];
+                let annotation = &self.mir.user_type_annotations[annotation_index];
                 span_mirbug!(
                     self,
                     constant,
@@ -293,6 +293,39 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
                     terr,
                 );
             }
+        } else {
+            match *constant.literal {
+                ty::LazyConst::Unevaluated(def_id, substs) => {
+                    if let Err(terr) = self.cx.fully_perform_op(
+                        location.to_locations(),
+                        ConstraintCategory::Boring,
+                        self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+                            constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
+                        )),
+                    ) {
+                        span_mirbug!(
+                            self,
+                            constant,
+                            "bad constant type {:?} ({:?})",
+                            constant,
+                            terr
+                        );
+                    }
+                }
+                ty::LazyConst::Evaluated(lit) => {
+                    if let ty::FnDef(def_id, substs) = lit.ty.sty {
+                        let tcx = self.tcx();
+
+                        let instantiated_predicates = tcx
+                            .predicates_of(def_id)
+                            .instantiate(tcx, substs);
+                        self.cx.normalize_and_prove_instantiated_predicates(
+                            instantiated_predicates,
+                            location.to_locations(),
+                        );
+                    }
+                }
+            }
         }
     }
 
@@ -374,8 +407,9 @@ fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
         }
     }
 
-    /// Checks that the constant's `ty` field matches up with what
-    /// would be expected from its literal.
+    /// Checks that the constant's `ty` field matches up with what would be
+    /// expected from its literal. Unevaluated constants and well-formed
+    /// constraints are checked by `visit_constant`.
     fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         debug!(
             "sanitize_constant(constant={:?}, location={:?})",
@@ -387,35 +421,6 @@ fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
             ty::LazyConst::Unevaluated(..) => return,
         };
 
-        // FIXME(#46702) -- We need some way to get the predicates
-        // associated with the "pre-evaluated" form of the
-        // constant. For example, consider that the constant
-        // may have associated constant projections (`<Foo as
-        // Trait<'a, 'b>>::SOME_CONST`) that impose
-        // constraints on `'a` and `'b`. These constraints
-        // would be lost if we just look at the normalized
-        // value.
-        if let ty::FnDef(def_id, substs) = literal.ty.sty {
-            let tcx = self.tcx();
-            let type_checker = &mut self.cx;
-
-            // FIXME -- For now, use the substitutions from
-            // `value.ty` rather than `value.val`. The
-            // renumberer will rewrite them to independent
-            // sets of regions; in principle, we ought to
-            // derive the type of the `value.val` from "first
-            // principles" and equate with value.ty, but as we
-            // are transitioning to the miri-based system, we
-            // don't have a handy function for that, so for
-            // now we just ignore `value.val` regions.
-
-            let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
-            type_checker.normalize_and_prove_instantiated_predicates(
-                instantiated_predicates,
-                location.to_locations(),
-            );
-        }
-
         debug!("sanitize_constant: expected_ty={:?}", literal.ty);
 
         if let Err(terr) = self.cx.eq_types(
@@ -740,15 +745,6 @@ struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> {
     reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
     borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
     universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>,
-    /// For each user-type annotation (identified by a UserTypeAnnotationIndex), we create
-    /// an "instantiated" version at the beginning of type check, which replaces each
-    /// canonical variable with a fresh inference variable. These instantiated versions are
-    /// stored either in this field or in user_substs, depending on the kind of user-type
-    /// annotation. They are then referenced by the code which has the job of enforcing these
-    /// annotations. Part of the reason for this setup is that it allows us to enforce basic
-    /// WF criteria on the types even if the code that referenced them is dead
-    /// code (see #54943).
-    instantiated_type_annotations: FxHashMap<UserTypeAnnotationIndex, UserTypeAnnotation<'tcx>>,
 }
 
 struct BorrowCheckContext<'a, 'tcx: 'a> {
@@ -905,36 +901,69 @@ fn new(
             borrowck_context,
             reported_errors: Default::default(),
             universal_region_relations,
-            instantiated_type_annotations: Default::default(),
         };
-        checker.instantiate_user_type_annotations();
+        checker.check_user_type_annotations();
         checker
     }
 
-    /// Instantiate canonical types from user type annotations in the `Mir` into the
-    /// `TypeChecker`. Used when relating user type annotations and when checking if
-    /// annotations are well-formed.
-    fn instantiate_user_type_annotations(&mut self) {
+    /// Equate the inferred type and the annotated type for user type annotations
+    fn check_user_type_annotations(&mut self) {
         debug!(
-            "instantiate_user_type_annotations: user_type_annotations={:?}",
+            "check_user_type_annotations: user_type_annotations={:?}",
              self.mir.user_type_annotations
         );
-        for annotation_index in self.mir.user_type_annotations.indices() {
-            let (span, canonical_annotation) = &self.mir.user_type_annotations[annotation_index];
-            let (mut annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
-                *span, &canonical_annotation
+        for user_annotation in &self.mir.user_type_annotations {
+            let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
+            let (annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
+                span, user_ty
             );
             match annotation {
-                UserTypeAnnotation::Ty(ref mut ty) =>
-                    *ty = self.normalize(ty, Locations::All(*span)),
-                _ => {},
+                UserType::Ty(mut ty) => {
+                    ty = self.normalize(ty, Locations::All(span));
+
+                    if let Err(terr) = self.eq_types(
+                        ty,
+                        inferred_ty,
+                        Locations::All(span),
+                        ConstraintCategory::BoringNoLocation,
+                    ) {
+                        span_mirbug!(
+                            self,
+                            user_annotation,
+                            "bad user type ({:?} = {:?}): {:?}",
+                            ty,
+                            inferred_ty,
+                            terr
+                        );
+                    }
+
+                    self.prove_predicate(
+                        ty::Predicate::WellFormed(inferred_ty),
+                        Locations::All(span),
+                        ConstraintCategory::TypeAnnotation,
+                    );
+                },
+                UserType::TypeOf(def_id, user_substs) => {
+                    if let Err(terr) = self.fully_perform_op(
+                        Locations::All(span),
+                        ConstraintCategory::BoringNoLocation,
+                        self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+                            inferred_ty, def_id, user_substs,
+                        )),
+                    ) {
+                        span_mirbug!(
+                            self,
+                            user_annotation,
+                            "bad user type AscribeUserType({:?}, {:?} {:?}): {:?}",
+                            inferred_ty,
+                            def_id,
+                            user_substs,
+                            terr
+                        );
+                    }
+                },
             }
-            self.instantiated_type_annotations.insert(annotation_index, annotation);
         }
-        debug!(
-            "instantiate_user_type_annotations: instantiated_type_annotations={:?}",
-            self.instantiated_type_annotations,
-        );
     }
 
     /// Given some operation `op` that manipulates types, proves
@@ -1066,58 +1095,23 @@ fn relate_type_and_user_type(
             a, v, user_ty, locations,
         );
 
-        let type_annotation = self.instantiated_type_annotations[&user_ty.base];
-        match type_annotation {
-            UserTypeAnnotation::Ty(ty) => {
-                // The `TypeRelating` code assumes that "unresolved inference
-                // variables" appear in the "a" side, so flip `Contravariant`
-                // ambient variance to get the right relationship.
-                let v1 = ty::Contravariant.xform(v);
-                let tcx = self.infcx.tcx;
+        let annotated_type = self.mir.user_type_annotations[user_ty.base].inferred_ty;
+        let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
 
-                // We need to follow any provided projetions into the type.
-                //
-                // if we hit a ty var as we descend, then just skip the
-                // attempt to relate the mir local with any type.
-                #[derive(Debug)] struct HitTyVar;
-                let mut curr_projected_ty: Result<PlaceTy, HitTyVar>;
-
-                curr_projected_ty = Ok(PlaceTy::from_ty(ty));
-                for proj in &user_ty.projs {
-                    let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
-                        projected_ty
-                    } else {
-                        break;
-                    };
-                    curr_projected_ty = projected_ty.projection_ty_core(
-                        tcx, proj, |this, field, &()| {
-                            if this.to_ty(tcx).is_ty_var() {
-                                Err(HitTyVar)
-                            } else {
-                                let ty = this.field_ty(tcx, field);
-                                Ok(self.normalize(ty, locations))
-                            }
-                        });
-                }
-                debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
-                       user_ty.base, ty, user_ty.projs, curr_projected_ty);
+        let tcx = self.infcx.tcx;
 
-                if let Ok(projected_ty) = curr_projected_ty {
-                    let ty = projected_ty.to_ty(tcx);
-                    self.relate_types(ty, v1, a, locations, category)?;
-                }
-            }
-            UserTypeAnnotation::TypeOf(def_id, user_substs) => {
-                let projs = self.infcx.tcx.intern_projs(&user_ty.projs);
-                self.fully_perform_op(
-                    locations,
-                    category,
-                    self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
-                        a, v, def_id, user_substs, projs,
-                    )),
-                )?;
-            }
+        for proj in &user_ty.projs {
+            let projected_ty = curr_projected_ty.projection_ty_core(tcx, proj, |this, field, &()| {
+                let ty = this.field_ty(tcx, field);
+                self.normalize(ty, locations)
+            });
+            curr_projected_ty = projected_ty;
         }
+        debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
+                user_ty.base, annotated_type, user_ty.projs, curr_projected_ty);
+
+        let ty = curr_projected_ty.to_ty(tcx);
+        self.relate_types(a, v, ty, locations, category)?;
 
         Ok(())
     }
@@ -1286,7 +1280,7 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
                         location.to_locations(),
                         ConstraintCategory::Boring,
                     ) {
-                        let annotation = self.instantiated_type_annotations[&annotation_index];
+                        let annotation = &mir.user_type_annotations[annotation_index];
                         span_mirbug!(
                             self,
                             stmt,
@@ -1345,7 +1339,7 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>, location: Loca
                     Locations::All(stmt.source_info.span),
                     ConstraintCategory::TypeAnnotation,
                 ) {
-                    let annotation = self.instantiated_type_annotations[&projection.base];
+                    let annotation = &mir.user_type_annotations[projection.base];
                     span_mirbug!(
                         self,
                         stmt,
index a431bfc61b37ae8c2aa2f9855d2c935b02bb492d..31e0c0daa3fa66ad0dc6f9a8a9413c41b0254314 100644 (file)
@@ -3,6 +3,7 @@
 use build::Builder;
 use hair::*;
 use rustc::mir::*;
+use rustc::ty::CanonicalUserTypeAnnotation;
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     /// Compile `expr`, yielding a compile-time constant. Assumes that
@@ -30,8 +31,12 @@ fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> {
                 value,
             } => this.as_constant(value),
             ExprKind::Literal { literal, user_ty } => {
-                let user_ty = user_ty.map(|ty| {
-                    this.canonical_user_type_annotations.push((span, ty))
+                let user_ty = user_ty.map(|user_ty| {
+                    this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
+                        span,
+                        user_ty,
+                        inferred_ty: ty,
+                    })
                 });
                 Constant {
                     span,
index 3ed00d5797907f638932cb4d51e097d6e94f724c..6bd61ab53fd2182df6c75dfb0ebd0721a9b4d58b 100644 (file)
@@ -6,7 +6,7 @@
 use hair::*;
 use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
 use rustc::mir::*;
-use rustc::ty::Variance;
+use rustc::ty::{CanonicalUserTypeAnnotation, Variance};
 
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -134,7 +134,11 @@ fn expr_as_place(
                 let place = unpack!(block = this.as_place(block, source));
                 if let Some(user_ty) = user_ty {
                     let annotation_index = this.canonical_user_type_annotations.push(
-                        (source_info.span, user_ty)
+                        CanonicalUserTypeAnnotation {
+                            span: source_info.span,
+                            user_ty,
+                            inferred_ty: expr.ty,
+                        }
                     );
                     this.cfg.push(
                         block,
@@ -157,7 +161,11 @@ fn expr_as_place(
                 );
                 if let Some(user_ty) = user_ty {
                     let annotation_index = this.canonical_user_type_annotations.push(
-                        (source_info.span, user_ty)
+                        CanonicalUserTypeAnnotation {
+                            span: source_info.span,
+                            user_ty,
+                            inferred_ty: expr.ty,
+                        }
                     );
                     this.cfg.push(
                         block,
index e0fc90931696e57851889e5f8286f9d083d711a6..3de2f4757865044f9e020817130dd97493a4209b 100644 (file)
@@ -9,7 +9,7 @@
 use rustc::middle::region;
 use rustc::mir::interpret::EvalErrorKind;
 use rustc::mir::*;
-use rustc::ty::{self, Ty, UpvarSubsts};
+use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, UpvarSubsts};
 use syntax_pos::Span;
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
@@ -331,8 +331,13 @@ fn expr_as_rvalue(
                         .collect()
                 };
 
+                let inferred_ty = expr.ty;
                 let user_ty = user_ty.map(|ty| {
-                    this.canonical_user_type_annotations.push((expr_span, ty))
+                    this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
+                        span: source_info.span,
+                        user_ty: ty,
+                        inferred_ty,
+                    })
                 });
                 let adt = box AggregateKind::Adt(
                     adt_def,
index d52ce9a67d29a87dd4a35dfb68c7260dfb716e41..2f1e8c03f2f7eefddb32199b0b551ac764eaa165 100644 (file)
@@ -9,7 +9,7 @@
 use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
 use hair::*;
 use rustc::mir::*;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty};
 use rustc::ty::layout::VariantIdx;
 use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::fx::FxHashMap;
@@ -303,7 +303,9 @@ pub(super) fn expr_into_pattern(
 
                 let ty_source_info = self.source_info(user_ty_span);
                 let user_ty = box pat_ascription_ty.user_ty(
-                    &mut self.canonical_user_type_annotations, ty_source_info.span
+                    &mut self.canonical_user_type_annotations,
+                    place.ty(&self.local_decls, self.hir.tcx()).to_ty(self.hir.tcx()),
+                    ty_source_info.span,
                 );
                 self.cfg.push(
                     block,
@@ -570,10 +572,14 @@ pub(super) fn visit_bindings(
                 //
                 // 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 = (user_ty_span, user_ty.base);
+                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),
-                    projs: user_ty.projs.clone(),
+                    projs: Vec::new(),
                 };
                 let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span);
                 self.visit_bindings(subpattern, subpattern_user_ty, f)
@@ -1337,7 +1343,9 @@ fn ascribe_types<'pat>(
             );
 
             let user_ty = box ascription.user_ty.clone().user_ty(
-                &mut self.canonical_user_type_annotations, source_info.span
+                &mut self.canonical_user_type_annotations,
+                ascription.source.ty(&self.local_decls, self.hir.tcx()).to_ty(self.hir.tcx()),
+                source_info.span
             );
             self.cfg.push(
                 block,
index eb536fbcf69bb9683484cc2c2a862a22c5109415..8d64c9e9ada89daa8ea5e71d444527f63d20d979 100644 (file)
@@ -278,7 +278,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     let user_ty = user_provided_types.get(fun.hir_id)
                         .map(|u_ty| *u_ty)
                         .map(|mut u_ty| {
-                            if let UserTypeAnnotation::TypeOf(ref mut did, _) = &mut u_ty.value {
+                            if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value {
                                 *did = adt_def.did;
                             }
                             u_ty
@@ -797,7 +797,7 @@ fn user_substs_applied_to_def(
     cx: &mut Cx<'a, 'gcx, 'tcx>,
     hir_id: hir::HirId,
     def: &Def,
-) -> Option<ty::CanonicalUserTypeAnnotation<'tcx>> {
+) -> Option<ty::CanonicalUserType<'tcx>> {
     debug!("user_substs_applied_to_def: def={:?}", def);
     let user_provided_type = match def {
         // A reference to something callable -- e.g., a fn, method, or
index e902423cd30fc5170192e92a80cbc5ebb40a31a0..f0f8acb31df4208eaedcd6a0423f9f550e6ea879 100644 (file)
@@ -9,7 +9,7 @@
 use rustc::infer::canonical::Canonical;
 use rustc::middle::region;
 use rustc::ty::subst::Substs;
-use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, LazyConst, UserTypeAnnotation};
+use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, LazyConst, UserType};
 use rustc::ty::layout::VariantIdx;
 use rustc::hir;
 use syntax::ast;
@@ -265,7 +265,7 @@ pub enum ExprKind<'tcx> {
 
         /// Optional user-given substs: for something like `let x =
         /// Bar::<T> { ... }`.
-        user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
+        user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
 
         fields: Vec<FieldExprRef<'tcx>>,
         base: Option<FruInfo<'tcx>>
@@ -273,12 +273,12 @@ pub enum ExprKind<'tcx> {
     PlaceTypeAscription {
         source: ExprRef<'tcx>,
         /// Type that the user gave to this expression
-        user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
+        user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
     },
     ValueTypeAscription {
         source: ExprRef<'tcx>,
         /// Type that the user gave to this expression
-        user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
+        user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
     },
     Closure {
         closure_id: DefId,
@@ -288,7 +288,7 @@ pub enum ExprKind<'tcx> {
     },
     Literal {
         literal: &'tcx LazyConst<'tcx>,
-        user_ty: Option<Canonical<'tcx, UserTypeAnnotation<'tcx>>>,
+        user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
     },
     InlineAsm {
         asm: &'tcx hir::InlineAsm,
index cdaffe5d45673adc747c08d93a069b1f17a03dc2..06a50f35be1cf428280e52f5841dbf208a9d8646 100644 (file)
 use hair::constant::*;
 
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
-use rustc::mir::{ProjectionElem, UserTypeProjection};
+use rustc::mir::{UserTypeProjection};
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
-use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift};
-use rustc::ty::{CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, UserTypeAnnotation};
+use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift, UserType};
+use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::ty::layout::VariantIdx;
 use rustc::hir::{self, PatKind, RangeEnd};
@@ -60,26 +60,29 @@ pub struct Pattern<'tcx> {
 
 #[derive(Clone, Debug)]
 pub struct PatternTypeProjection<'tcx> {
-    pub base: CanonicalUserTypeAnnotation<'tcx>,
-    pub projs: Vec<ProjectionElem<'tcx, (), ()>>,
+    pub user_ty: CanonicalUserType<'tcx>,
 }
 
 impl<'tcx> PatternTypeProjection<'tcx> {
-    pub(crate) fn from_user_type(user_annotation: CanonicalUserTypeAnnotation<'tcx>) -> Self {
+    pub(crate) fn from_user_type(user_annotation: CanonicalUserType<'tcx>) -> Self {
         Self {
-            base: user_annotation,
-            projs: Vec::new(),
+            user_ty: user_annotation,
         }
     }
 
     pub(crate) fn user_ty(
         self,
         annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
+        inferred_ty: Ty<'tcx>,
         span: Span,
     ) -> UserTypeProjection<'tcx> {
         UserTypeProjection {
-            base: annotations.push((span, self.base)),
-            projs: self.projs
+            base: annotations.push(CanonicalUserTypeAnnotation {
+                span,
+                user_ty: self.user_ty,
+                inferred_ty,
+            }),
+            projs: Vec::new(),
         }
     }
 }
@@ -1040,7 +1043,7 @@ fn super_fold_with<F: PatternFolder<$lt_tcx>>(&self, _: &mut F) -> Self {
 CloneImpls!{ <'tcx>
     Span, Field, Mutability, ast::Name, ast::NodeId, usize, ty::Const<'tcx>,
     Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef,
-    &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, UserTypeAnnotation<'tcx>,
+    &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, UserType<'tcx>,
     UserTypeProjection<'tcx>, PatternTypeProjection<'tcx>
 }
 
index f0f8263b64de53f286e090e225f8060473897057..cb4a72387fa161bab7be4c6cb14e0929a2d50c8d 100644 (file)
@@ -1,5 +1,5 @@
 use rustc::hir;
-use rustc::ty::{self, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotation};
+use rustc::ty::{self, CanonicalUserType, TyCtxt, UserType};
 
 crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> {
     fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>;
     fn user_substs_applied_to_ty_of_hir_id(
         &self,
         hir_id: hir::HirId,
-    ) -> Option<CanonicalUserTypeAnnotation<'tcx>> {
+    ) -> Option<CanonicalUserType<'tcx>> {
         let user_provided_types = self.tables().user_provided_types();
         let mut user_ty = *user_provided_types.get(hir_id)?;
         debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty);
         match &self.tables().node_id_to_type(hir_id).sty {
             ty::Adt(adt_def, ..) => {
-                if let UserTypeAnnotation::TypeOf(ref mut did, _) = &mut user_ty.value {
+                if let UserType::TypeOf(ref mut did, _) = &mut user_ty.value {
                     *did = adt_def.did;
                 }
                 Some(user_ty)
index f4685e0ddc909dc5434f955b48aff2fb877792d1..3a15356806a9767b13e6fdb4d1b2b211ffac547d 100644 (file)
@@ -634,8 +634,8 @@ fn write_user_type_annotations(mir: &Mir, w: &mut dyn Write) -> io::Result<()> {
     if !mir.user_type_annotations.is_empty() {
         writeln!(w, "| User Type Annotations")?;
     }
-    for (index, (span, annotation)) in mir.user_type_annotations.iter_enumerated() {
-        writeln!(w, "| {:?}: {:?} at {:?}", index.index(), annotationspan)?;
+    for (index, annotation) in mir.user_type_annotations.iter_enumerated() {
+        writeln!(w, "| {:?}: {:?} at {:?}", index.index(), annotation.user_ty, annotation.span)?;
     }
     if !mir.user_type_annotations.is_empty() {
         writeln!(w, "|")?;
index 52fcb5b80f4ae9d4dec96886c8dd3b0cc02b31aa..526637e108d40bb861f1f90f19b3e330172e43eb 100644 (file)
@@ -2,8 +2,6 @@
 use rustc::infer::canonical::{Canonical, QueryResponse};
 use rustc::infer::InferCtxt;
 use rustc::hir::def_id::DefId;
-use rustc::mir::ProjectionKind;
-use rustc::mir::tcx::PlaceTy;
 use rustc::traits::query::type_op::ascribe_user_type::AscribeUserType;
 use rustc::traits::query::type_op::eq::Eq;
 use rustc::traits::query::type_op::normalize::Normalize;
@@ -44,17 +42,16 @@ fn type_op_ascribe_user_type<'tcx>(
     tcx.infer_ctxt()
         .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
             let (
-                param_env, AscribeUserType { mir_ty, variance, def_id, user_substs, projs }
+                param_env, AscribeUserType { mir_ty, def_id, user_substs }
             ) = key.into_parts();
 
             debug!(
-                "type_op_ascribe_user_type: mir_ty={:?} variance={:?} def_id={:?} \
-                 user_substs={:?} projs={:?}",
-                mir_ty, variance, def_id, user_substs, projs
+                "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
+                mir_ty, def_id, user_substs
             );
 
             let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
-            cx.relate_mir_and_user_ty(mir_ty, variance, def_id, user_substs, projs)?;
+            cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?;
 
             Ok(())
         })
@@ -112,10 +109,8 @@ fn subst<T>(&self, value: T, substs: &[Kind<'tcx>]) -> T
     fn relate_mir_and_user_ty(
         &mut self,
         mir_ty: Ty<'tcx>,
-        variance: Variance,
         def_id: DefId,
         user_substs: UserSubsts<'tcx>,
-        projs: &[ProjectionKind<'tcx>],
     ) -> Result<(), NoSolution> {
         let UserSubsts {
             user_self_ty,
@@ -128,35 +123,7 @@ fn relate_mir_and_user_ty(
         debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
         let ty = self.normalize(ty);
 
-        // We need to follow any provided projetions into the type.
-        //
-        // if we hit a ty var as we descend, then just skip the
-        // attempt to relate the mir local with any type.
-
-        struct HitTyVar;
-        let mut curr_projected_ty: Result<PlaceTy, HitTyVar>;
-        curr_projected_ty = Ok(PlaceTy::from_ty(ty));
-        for proj in projs {
-            let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
-                projected_ty
-            } else {
-                break;
-            };
-            curr_projected_ty = projected_ty.projection_ty_core(
-                tcx, proj, |this, field, &()| {
-                    if this.to_ty(tcx).is_ty_var() {
-                        Err(HitTyVar)
-                    } else {
-                        let ty = this.field_ty(tcx, field);
-                        Ok(self.normalize(ty))
-                    }
-                });
-        }
-
-        if let Ok(projected_ty) = curr_projected_ty {
-            let ty = projected_ty.to_ty(tcx);
-            self.relate(mir_ty, variance, ty)?;
-        }
+        self.relate(mir_ty, Variance::Invariant, ty)?;
 
         // Prove the predicates coming along with `def_id`.
         //
index ad4bc3cd83958e448be8955986ba2fad8adcbce5..240db801fb2f22c4ffd6d91ff6bd27e97263ed10 100644 (file)
 use rustc::mir::interpret::{ConstValue, GlobalId};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
 use rustc::ty::{
-    self, AdtKind, CanonicalUserTypeAnnotation, Ty, TyCtxt, GenericParamDefKind, Visibility,
-    ToPolyTraitRef, ToPredicate, RegionKind, UserTypeAnnotation
+    self, AdtKind, CanonicalUserType, Ty, TyCtxt, GenericParamDefKind, Visibility,
+    ToPolyTraitRef, ToPredicate, RegionKind, UserType
 };
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::fold::TypeFoldable;
@@ -985,7 +985,7 @@ fn visit_local(&mut self, local: &'gcx hir::Local) {
                 };
 
                 let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(
-                    &UserTypeAnnotation::Ty(revealed_ty)
+                    &UserType::Ty(revealed_ty)
                 );
                 debug!("visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}",
                        ty.hir_id, o_ty, revealed_ty, c_ty);
@@ -2194,7 +2194,7 @@ pub fn write_method_call(&self,
                         user_self_ty: None, // not relevant here
                     };
 
-                    self.infcx.canonicalize_user_type_annotation(&UserTypeAnnotation::TypeOf(
+                    self.infcx.canonicalize_user_type_annotation(&UserType::TypeOf(
                         method.def_id,
                         user_substs,
                     ))
@@ -2239,7 +2239,7 @@ pub fn write_user_type_annotation_from_substs(
 
         if !substs.is_noop() {
             let canonicalized = self.infcx.canonicalize_user_type_annotation(
-                &UserTypeAnnotation::TypeOf(def_id, UserSubsts {
+                &UserType::TypeOf(def_id, UserSubsts {
                     substs,
                     user_self_ty,
                 })
@@ -2252,7 +2252,7 @@ pub fn write_user_type_annotation_from_substs(
     pub fn write_user_type_annotation(
         &self,
         hir_id: hir::HirId,
-        canonical_user_type_annotation: CanonicalUserTypeAnnotation<'tcx>,
+        canonical_user_type_annotation: CanonicalUserType<'tcx>,
     ) {
         debug!(
             "write_user_type_annotation: hir_id={:?} canonical_user_type_annotation={:?} tag={}",
@@ -2437,10 +2437,11 @@ pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
         // types that involve projections, since those can resolve to
         // `'static` bounds (modulo #54940, which hopefully will be
         // fixed by the time you see this comment, dear reader,
-        // although I have my doubts). Other sorts of things are
-        // already sufficiently enforced with erased regions. =)
-        if ty.has_free_regions() || ty.has_projections() {
-            let c_ty = self.infcx.canonicalize_response(&UserTypeAnnotation::Ty(ty));
+        // although I have my doubts). Also pass in types with inference
+        // types, because they may be repeated. Other sorts of things
+        // are already sufficiently enforced with erased regions. =)
+        if ty.has_free_regions() || ty.has_projections() || ty.has_infer_types() {
+            let c_ty = self.infcx.canonicalize_response(&UserType::Ty(ty));
             debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
             self.tables.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
         }
index c61159eb4948121bb64bcfb2bfd46122a3bf3071..238b087fe32f86b3dc431672d4396aeaba2775cb 100644 (file)
@@ -404,7 +404,7 @@ fn visit_user_provided_tys(&mut self) {
                 .user_provided_types_mut()
                 .insert(hir_id, c_ty.clone());
 
-            if let ty::UserTypeAnnotation::TypeOf(_, user_substs) = c_ty.value {
+            if let ty::UserType::TypeOf(_, user_substs) = c_ty.value {
                 if self.rustc_dump_user_substs {
                     // This is a unit-testing mechanism.
                     let node_id = self.tcx().hir().hir_to_node_id(hir_id);
index 88fd53d4ba59d3feb878618276ba80d84ac67272..1bbbe67a12cb8f990274ed7818be22877fba0f56 100644 (file)
@@ -37,7 +37,7 @@ fn main() {
 //        StorageLive(_4);
 //        _4 = std::option::Option<std::boxed::Box<u32>>::None;
 //        FakeRead(ForLet, _4);
-//        AscribeUserType(_4, o, UserTypeProjection { base: UserTypeAnnotation(1), projs: [] });
+//        AscribeUserType(_4, o, UserTypeProjection { base: UserType(1), projs: [] });
 //        StorageLive(_5);
 //        StorageLive(_6);
 //        _6 = move _4;
index 5b00c5c46031666ff7e9650247537c05ba91196b..bb794409ae01f635c02baa4cf814d749db2ba570 100644 (file)
@@ -75,18 +75,18 @@ fn main() {
 //         _10 = move _8;
 //         Retag(_10);
 //         ...
-//         _14 = &mut (*_10);
-//         Retag(_14);
-//         _13 = move _14 as *mut i32 (Misc);
-//         Retag([raw] _13);
+//         _15 = &mut (*_10);
+//         Retag(_15);
+//         _14 = move _15 as *mut i32 (Misc);
+//         Retag([raw] _14);
 //         ...
-//         _17 = move _18(move _19) -> bb2;
+//         _18 = move _19(move _20) -> bb2;
 //     }
 //
 //     bb2: {
-//         Retag(_17);
+//         Retag(_18);
 //         ...
-//         _21 = const Test::foo_shr(move _22, move _24) -> bb3;
+//         _22 = const Test::foo_shr(move _23, move _25) -> bb3;
 //     }
 //
 //     bb3: {
index c720f6279758068643488b9a43fcc873358840eb..ce4e010674359670526297c83d84bef3cf11d4d9 100644 (file)
@@ -1,7 +1,3 @@
-// compile-pass
-// FIXME(#54943) This test targets the scenario where proving the WF requirements of a user
-// type annotation requires checking dead code. This test should actually fail to compile.
-
 #![feature(nll)]
 #![allow(warnings)]
 
@@ -11,7 +7,7 @@ fn boo<'a>() {
     return;
 
     let x = foo::<&'a u32>();
-    //~^ ERROR the type `&'a u32` does not fulfill the required lifetime [E0477]
+    //~^ ERROR lifetime may not live long enough
 }
 
 fn main() {}
diff --git a/src/test/ui/issue-54943.stderr b/src/test/ui/issue-54943.stderr
new file mode 100644 (file)
index 0000000..aa68177
--- /dev/null
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-54943.rs:9:13
+   |
+LL | fn boo<'a>() {
+   |        -- lifetime `'a` defined here
+...
+LL |     let x = foo::<&'a u32>();
+   |             ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-57866.rs b/src/test/ui/issues/issue-57866.rs
new file mode 100644 (file)
index 0000000..77c50e5
--- /dev/null
@@ -0,0 +1,26 @@
+// compile-pass
+
+#![feature(type_alias_enum_variants)]
+
+enum Outer<T> {
+    A(T)
+}
+
+enum Inner {
+    A(i32)
+}
+
+type OuterAlias = Outer<Inner>;
+
+fn ice(x: OuterAlias) {
+    // Fine
+    match x {
+        OuterAlias::A(Inner::A(_)) => (),
+    }
+    // Not fine
+    match x {
+        OuterAlias::A(Inner::A(y)) => (),
+    }
+}
+
+fn main() {}
index acb978b5d5a2c955229c0ebf7adb432f70416ab3..597b096dbe60747e62822051882d8ce97c7deaa1 100644 (file)
@@ -2,7 +2,7 @@ error[E0309]: the associated type `<T as MyTrait<'_>>::Output` may not live long
   --> $DIR/projection-where-clause-env-wrong-bound.rs:17:5
    |
 LL |     bar::<T::Output>() //~ ERROR may not live long enough
-   |     ^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
 
index 2d171a98789f8f626a37efde0eb8bc0b787ad263..3c2ac474778f9463f3c111527743b7d233287a37 100644 (file)
@@ -2,7 +2,7 @@ error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/projection-where-clause-none.rs:16:5
    |
 LL |     bar::<T::Output>() //~ ERROR the parameter type `T` may not live long enough
-   |     ^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `T: 'a`...
 
diff --git a/src/test/ui/nll/ty-outlives/wf-unreachable.rs b/src/test/ui/nll/ty-outlives/wf-unreachable.rs
new file mode 100644 (file)
index 0000000..a2e3ab4
--- /dev/null
@@ -0,0 +1,54 @@
+// Test that we check that user type annotations are well-formed, even in dead
+// code.
+
+#![feature(nll)]
+
+fn uninit<'a>() {
+    return;
+    let x: &'static &'a ();                         //~ ERROR lifetime may not live long enough
+}
+
+fn var_type<'a>() {
+    return;
+    let x: &'static &'a () = &&();                  //~ ERROR lifetime may not live long enough
+}
+
+fn uninit_infer<'a>() {
+    let x: &'static &'a _;                          //~ ERROR lifetime may not live long enough
+    x = && ();
+}
+
+fn infer<'a>() {
+    return;
+    let x: &'static &'a _ = &&();                   //~ ERROR lifetime may not live long enough
+}
+
+fn uninit_no_var<'a>() {
+    return;
+    let _: &'static &'a ();                         //~ ERROR lifetime may not live long enough
+}
+
+fn no_var<'a>() {
+    return;
+    let _: &'static &'a () = &&();                  //~ ERROR lifetime may not live long enough
+}
+
+fn infer_no_var<'a>() {
+    return;
+    let _: &'static &'a _ = &&();                   //~ ERROR lifetime may not live long enough
+}
+
+trait X<'a, 'b> {}
+
+struct C<'a, 'b, T: X<'a, 'b>>(T, &'a (), &'b ());
+
+impl X<'_, '_> for i32 {}
+impl<'a> X<'a, 'a> for () {}
+
+// This type annotation is not well-formed because we substitute `()` for `_`.
+fn required_substs<'a>() {
+    return;
+    let _: C<'static, 'a, _> = C((), &(), &());     //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/wf-unreachable.stderr b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr
new file mode 100644 (file)
index 0000000..14642a1
--- /dev/null
@@ -0,0 +1,73 @@
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:8:12
+   |
+LL | fn uninit<'a>() {
+   |           -- lifetime `'a` defined here
+LL |     return;
+LL |     let x: &'static &'a ();                         //~ ERROR lifetime may not live long enough
+   |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:13:12
+   |
+LL | fn var_type<'a>() {
+   |             -- lifetime `'a` defined here
+LL |     return;
+LL |     let x: &'static &'a () = &&();                  //~ ERROR lifetime may not live long enough
+   |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:17:12
+   |
+LL | fn uninit_infer<'a>() {
+   |                 -- lifetime `'a` defined here
+LL |     let x: &'static &'a _;                          //~ ERROR lifetime may not live long enough
+   |            ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:23:12
+   |
+LL | fn infer<'a>() {
+   |          -- lifetime `'a` defined here
+LL |     return;
+LL |     let x: &'static &'a _ = &&();                   //~ ERROR lifetime may not live long enough
+   |            ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:28:12
+   |
+LL | fn uninit_no_var<'a>() {
+   |                  -- lifetime `'a` defined here
+LL |     return;
+LL |     let _: &'static &'a ();                         //~ ERROR lifetime may not live long enough
+   |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:33:12
+   |
+LL | fn no_var<'a>() {
+   |           -- lifetime `'a` defined here
+LL |     return;
+LL |     let _: &'static &'a () = &&();                  //~ ERROR lifetime may not live long enough
+   |            ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:38:12
+   |
+LL | fn infer_no_var<'a>() {
+   |                 -- lifetime `'a` defined here
+LL |     return;
+LL |     let _: &'static &'a _ = &&();                   //~ ERROR lifetime may not live long enough
+   |            ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/wf-unreachable.rs:51:12
+   |
+LL | fn required_substs<'a>() {
+   |                    -- lifetime `'a` defined here
+LL |     return;
+LL |     let _: C<'static, 'a, _> = C((), &(), &());     //~ ERROR lifetime may not live long enough
+   |            ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.rs b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.rs
new file mode 100644 (file)
index 0000000..123be6b
--- /dev/null
@@ -0,0 +1,29 @@
+// Test that we still check constants are well-formed, even when we there's no
+// type annotation to check.
+
+#![feature(nll)]
+
+const FUN: fn(&'static ()) = |_| {};
+struct A;
+impl A {
+    const ASSOCIATED_FUN: fn(&'static ()) = |_| {};
+}
+
+struct B<'a>(&'a ());
+impl B<'static> {
+    const ALSO_ASSOCIATED_FUN: fn(&'static ()) = |_| {};
+}
+
+trait Z: 'static {
+    const TRAIT_ASSOCIATED_FUN: fn(&'static Self) = |_| ();
+}
+
+impl Z for () {}
+
+fn main() {
+    let x = ();
+    FUN(&x);                        //~ ERROR `x` does not live long enough
+    A::ASSOCIATED_FUN(&x);          //~ ERROR `x` does not live long enough
+    B::ALSO_ASSOCIATED_FUN(&x);     //~ ERROR `x` does not live long enough
+    <_>::TRAIT_ASSOCIATED_FUN(&x);  //~ ERROR `x` does not live long enough
+}
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr
new file mode 100644 (file)
index 0000000..57cfaa2
--- /dev/null
@@ -0,0 +1,50 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:25:9
+   |
+LL |     FUN(&x);                        //~ ERROR `x` does not live long enough
+   |     ----^^-
+   |     |   |
+   |     |   borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+...
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:26:23
+   |
+LL |     A::ASSOCIATED_FUN(&x);          //~ ERROR `x` does not live long enough
+   |     ------------------^^-
+   |     |                 |
+   |     |                 borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+...
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:27:28
+   |
+LL |     B::ALSO_ASSOCIATED_FUN(&x);     //~ ERROR `x` does not live long enough
+   |     -----------------------^^-
+   |     |                      |
+   |     |                      borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+LL |     <_>::TRAIT_ASSOCIATED_FUN(&x);  //~ ERROR `x` does not live long enough
+LL | }
+   | - `x` dropped here while still borrowed
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/constant-in-expr-inherent-2.rs:28:31
+   |
+LL |     <_>::TRAIT_ASSOCIATED_FUN(&x);  //~ ERROR `x` does not live long enough
+   |     --------------------------^^-
+   |     |                         |
+   |     |                         borrowed value does not live long enough
+   |     argument requires that `x` is borrowed for `'static`
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/user-annotations/downcast-infer.rs b/src/test/ui/nll/user-annotations/downcast-infer.rs
new file mode 100644 (file)
index 0000000..23b76bb
--- /dev/null
@@ -0,0 +1,11 @@
+// compile-pass
+
+// Check that we don't try to downcast `_` when type-checking the annotation.
+fn main() {
+    let x = Some(Some(Some(1)));
+
+    match x {
+        Some::<Option<_>>(Some(Some(v))) => (),
+        _ => (),
+    }
+}
diff --git a/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs
new file mode 100644 (file)
index 0000000..f4969bb
--- /dev/null
@@ -0,0 +1,40 @@
+// Check that repeated type variables are correctly handled
+
+#![allow(unused)]
+#![feature(nll, type_ascription)]
+
+type PairUncoupled<'a, 'b, T> = (&'a T, &'b T);
+type PairCoupledTypes<T> = (T, T);
+type PairCoupledRegions<'a, T> = (&'a T, &'a T);
+
+fn uncoupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),): (PairUncoupled<_>,);
+    y // OK
+}
+
+fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),): (PairCoupledTypes<_>,);
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),): (PairCoupledRegions<_>,);
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn cast_uncoupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),) as (PairUncoupled<_>,);
+    y // OK
+}
+
+fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,);
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+    let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,);
+    y //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr
new file mode 100644 (file)
index 0000000..76be637
--- /dev/null
@@ -0,0 +1,38 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:17:5
+   |
+LL | fn coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                      -- lifetime `'a` defined here
+LL |     let ((y, _z),) = ((s, _x),): (PairCoupledTypes<_>,);
+LL |     y //~ ERROR lifetime may not live long enough
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:22:5
+   |
+LL | fn coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                        -- lifetime `'a` defined here
+LL |     let ((y, _z),) = ((s, _x),): (PairCoupledRegions<_>,);
+LL |     y //~ ERROR lifetime may not live long enough
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:32:5
+   |
+LL | fn cast_coupled_wilds_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                           -- lifetime `'a` defined here
+LL |     let ((y, _z),) = ((s, _x),) as (PairCoupledTypes<_>,);
+LL |     y //~ ERROR lifetime may not live long enough
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/issue-57731-ascibed-coupled-types.rs:37:5
+   |
+LL | fn cast_coupled_regions_rhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 {
+   |                             -- lifetime `'a` defined here
+LL |     let ((y, _z),) = ((s, _x),) as (PairCoupledRegions<_>,);
+LL |     y //~ ERROR lifetime may not live long enough
+   |     ^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.ast.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.ast.stderr
new file mode 100644 (file)
index 0000000..76ead4e
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:45:13
+   |
+LL |     let _x: &'a WithAssoc<TheType<'b>> = loop { };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 37:15
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:37:15
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 37:18
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:37:18
+   |
+LL | fn with_assoc<'a,'b>() {
+   |                  ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.mir.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.mir.stderr
new file mode 100644 (file)
index 0000000..ad94d37
--- /dev/null
@@ -0,0 +1,13 @@
+error: lifetime may not live long enough
+  --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:45:13
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               -- -- lifetime `'b` defined here
+   |               |
+   |               lifetime `'a` defined here
+...
+LL |     let _x: &'a WithAssoc<TheType<'b>> = loop { };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to previous error
+
index df7c1e0c7c78be2dedd4404ea51567a7e17ff38b..1d5349219923063f67d9a6584754cceed4ad00a1 100644 (file)
@@ -3,6 +3,9 @@
 // outlive the location in which the type appears, even when the
 // associted type is in a supertype. Issue #22246.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
 #![allow(dead_code)]
 
 ///////////////////////////////////////////////////////////////////////////
@@ -40,7 +43,8 @@ fn with_assoc<'a,'b>() {
     // FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if
     // `_x` is changed to `_`
     let _x: &'a WithAssoc<TheType<'b>> = loop { };
-    //~^ ERROR reference has a longer lifetime
+    //[ast]~^ ERROR reference has a longer lifetime
+    //[mir]~^^ ERROR lifetime may not live long enough
 }
 
 fn main() {
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr
new file mode 100644 (file)
index 0000000..73266ab
--- /dev/null
@@ -0,0 +1,32 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-free-region-ordering-caller.rs:11:12
+   |
+LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |                     ---------     ---------
+   |                     |
+   |                     these two types are declared with different lifetimes...
+LL |     let z: Option<&'b &'a usize> = None;//[ast]~ ERROR E0623
+   |            ^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-free-region-ordering-caller.rs:17:12
+   |
+LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |                     ---------     ---------
+   |                     |
+   |                     these two types are declared with different lifetimes...
+LL |     let y: Paramd<'a> = Paramd { x: a };
+LL |     let z: Option<&'b Paramd<'a>> = None;//[ast]~ ERROR E0623
+   |            ^^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
+
+error[E0623]: lifetime mismatch
+  --> $DIR/regions-free-region-ordering-caller.rs:22:12
+   |
+LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |                     ---------     --------- these two types are declared with different lifetimes...
+LL |     let z: Option<&'a &'b usize> = None;//[ast]~ ERROR E0623
+   |            ^^^^^^^^^^^^^^^^^^^^^ ...but data from `b` flows into `a` here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr
new file mode 100644 (file)
index 0000000..abec468
--- /dev/null
@@ -0,0 +1,33 @@
+error: lifetime may not live long enough
+  --> $DIR/regions-free-region-ordering-caller.rs:11:12
+   |
+LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          --  -- lifetime `'b` defined here
+   |          |
+   |          lifetime `'a` defined here
+LL |     let z: Option<&'b &'a usize> = None;//[ast]~ ERROR E0623
+   |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/regions-free-region-ordering-caller.rs:17:12
+   |
+LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          --  -- lifetime `'b` defined here
+   |          |
+   |          lifetime `'a` defined here
+LL |     let y: Paramd<'a> = Paramd { x: a };
+LL |     let z: Option<&'b Paramd<'a>> = None;//[ast]~ ERROR E0623
+   |            ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+  --> $DIR/regions-free-region-ordering-caller.rs:22:12
+   |
+LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
+   |          --  -- lifetime `'b` defined here
+   |          |
+   |          lifetime `'a` defined here
+LL |     let z: Option<&'a &'b usize> = None;//[ast]~ ERROR E0623
+   |            ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to 3 previous errors
+
index e26799fcc471146d3cc9c652657dc451425f09ed..621e6e78b4650861e757420fcffa91f498075a9b 100644 (file)
@@ -2,19 +2,25 @@
 // than the thing it points at and ensure that they result in
 // errors. See also regions-free-region-ordering-callee.rs
 
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
 struct Paramd<'a> { x: &'a usize }
 
 fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
-    let z: Option<&'b &'a usize> = None;//~ ERROR E0623
+    let z: Option<&'b &'a usize> = None;//[ast]~ ERROR E0623
+    //[mir]~^ ERROR lifetime may not live long enough
 }
 
 fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
     let y: Paramd<'a> = Paramd { x: a };
-    let z: Option<&'b Paramd<'a>> = None;//~ ERROR E0623
+    let z: Option<&'b Paramd<'a>> = None;//[ast]~ ERROR E0623
+    //[mir]~^ ERROR lifetime may not live long enough
 }
 
 fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
-    let z: Option<&'a &'b usize> = None;//~ ERROR E0623
+    let z: Option<&'a &'b usize> = None;//[ast]~ ERROR E0623
+    //[mir]~^ ERROR lifetime may not live long enough
 }
 
 fn main() {}
index 92c21fcb4aec5196f7cf1248674969b794bb39aa..539343a68294f35415ce28a8e18a50f3bc8c63d4 100644 (file)
@@ -12,6 +12,21 @@ LL |     let z: &'a & usize = &(&y);
 LL | }
    | - temporary value is freed at the end of this statement
 
-error: aborting due to previous error
+error[E0597]: `y` does not live long enough
+  --> $DIR/regions-free-region-ordering-caller1.rs:9:27
+   |
+LL | fn call1<'a>(x: &'a usize) {
+   |          -- lifetime `'a` defined here
+...
+LL |     let z: &'a & usize = &(&y);
+   |            -----------    ^^^^ borrowed value does not live long enough
+   |            |
+   |            type annotation requires that `y` is borrowed for `'a`
+...
+LL | }
+   | - `y` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0716`.
+Some errors occurred: E0597, E0716.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.ast.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.ast.stderr
new file mode 100644 (file)
index 0000000..d833018
--- /dev/null
@@ -0,0 +1,37 @@
+error[E0491]: in type `&'a WithHrAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12
+   |
+LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 32:15
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:32:15
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 32:18
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:32:18
+   |
+LL | fn with_assoc<'a,'b>() {
+   |                  ^^
+
+error[E0491]: in type `&'a WithHrAssocSub<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12
+   |
+LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 53:19
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:53:19
+   |
+LL | fn with_assoc_sub<'a,'b>() {
+   |                   ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 53:22
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:53:22
+   |
+LL | fn with_assoc_sub<'a,'b>() {
+   |                      ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.mir.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.mir.stderr
new file mode 100644 (file)
index 0000000..5028663
--- /dev/null
@@ -0,0 +1,24 @@
+error: lifetime may not live long enough
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               -- -- lifetime `'b` defined here
+   |               |
+   |               lifetime `'a` defined here
+...
+LL |     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: lifetime may not live long enough
+  --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12
+   |
+LL | fn with_assoc_sub<'a,'b>() {
+   |                   -- -- lifetime `'b` defined here
+   |                   |
+   |                   lifetime `'a` defined here
+...
+LL |     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to 2 previous errors
+
index 3483f24ecbf66c04e666c2c3ea806659a9423a96..2871d962c42c9d13cd215a945f7f2ca7e461e316 100644 (file)
@@ -1,6 +1,9 @@
 // Test that structs with higher-ranked where clauses don't generate
 // "outlives" requirements. Issue #22246.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
 #![allow(dead_code)]
 
 
@@ -30,7 +33,8 @@ fn with_assoc<'a,'b>() {
     // We get an error because 'b:'a does not hold:
 
     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
-    //~^ ERROR reference has a longer lifetime
+    //[ast]~^ ERROR reference has a longer lifetime
+    //[mir]~^^ ERROR lifetime may not live long enough
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -51,7 +55,8 @@ fn with_assoc_sub<'a,'b>() {
     // below to be well-formed, it is not related to the HR relation.
 
     let _: &'a WithHrAssocSub<TheType<'b>> = loop { };
-    //~^ ERROR reference has a longer lifetime
+    //[ast]~^ ERROR reference has a longer lifetime
+    //[mir]~^^ ERROR lifetime may not live long enough
 }
 
 
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.ast.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.ast.stderr
new file mode 100644 (file)
index 0000000..9e31065
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
+  --> $DIR/regions-outlives-projection-container-wc.rs:37:12
+   |
+LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the pointer is valid for the lifetime 'a as defined on the function body at 31:15
+  --> $DIR/regions-outlives-projection-container-wc.rs:31:15
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               ^^
+note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 31:18
+  --> $DIR/regions-outlives-projection-container-wc.rs:31:18
+   |
+LL | fn with_assoc<'a,'b>() {
+   |                  ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0491`.
diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.mir.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.mir.stderr
new file mode 100644 (file)
index 0000000..880fe17
--- /dev/null
@@ -0,0 +1,13 @@
+error: lifetime may not live long enough
+  --> $DIR/regions-outlives-projection-container-wc.rs:37:12
+   |
+LL | fn with_assoc<'a,'b>() {
+   |               -- -- lifetime `'b` defined here
+   |               |
+   |               lifetime `'a` defined here
+...
+LL |     let _: &'a WithAssoc<TheType<'b>> = loop { };
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
+
+error: aborting due to previous error
+
index 91a0d8590ff341e92ff00efaeda65f9dc511f717..37622211327c0ab515d430934b047edd8290f5d1 100644 (file)
@@ -3,6 +3,9 @@
 // outlive the location in which the type appears, even when the
 // constraint is in a where clause not a bound. Issue #22246.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
 #![allow(dead_code)]
 
 ///////////////////////////////////////////////////////////////////////////
@@ -32,7 +35,8 @@ fn with_assoc<'a,'b>() {
     // which is &'b (), must outlive 'a.
 
     let _: &'a WithAssoc<TheType<'b>> = loop { };
-    //~^ ERROR reference has a longer lifetime
+    //[ast]~^ ERROR reference has a longer lifetime
+    //[mir]~^^ ERROR lifetime may not live long enough
 }
 
 fn main() {