diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index ef7fb0128ef4b..79c2b89522dbf 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1240,16 +1240,22 @@ impl_stable_hash_for!( } ); -impl<'a, 'gcx> HashStable> for ty::UserTypeAnnotation<'gcx> { +impl_stable_hash_for!( + struct ty::CanonicalUserTypeAnnotation<'tcx> { + user_ty, span, inferred_ty + } +); + +impl<'a, 'gcx> HashStable> for ty::UserType<'gcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { 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); } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index a1a6e890b1292..f824ab7e5b395 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -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; diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index c5b884525da4b..649370059f0ea 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -75,8 +75,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { elem: &PlaceElem<'tcx>) -> PlaceTy<'tcx> { - self.projection_ty_core(tcx, elem, |_, _, ty| -> Result, ()> { Ok(ty) }) - .unwrap() + self.projection_ty_core(tcx, elem, |_, _, ty| ty) } /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })` @@ -84,12 +83,12 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'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( + pub fn projection_ty_core( self, tcx: TyCtxt<'a, 'gcx, 'tcx>, elem: &ProjectionElem<'tcx, V, T>, - mut handle_field: impl FnMut(&Self, &Field, &T) -> Result, E>) - -> Result, 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 @@ 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 } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index a0fae3aa927ce..598303f29328f 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -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 @@ 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); } @@ -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); @@ -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>) { @@ -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), diff --git a/src/librustc/traits/query/type_op/ascribe_user_type.rs b/src/librustc/traits/query/type_op/ascribe_user_type.rs index b2f30564de93a..15f627b3ee8c4 100644 --- a/src/librustc/traits/query/type_op/ascribe_user_type.rs +++ b/src/librustc/traits/query/type_op/ascribe_user_type.rs @@ -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>, } 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>, ) -> Self { - Self { mir_ty, variance, def_id, user_substs, projs } + Self { mir_ty, def_id, user_substs } } } @@ -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 } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index e37eab622df3f..4c8f81411163c 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -350,7 +350,7 @@ pub struct TypeckTables<'tcx> { /// canonical substitutions would include only `for { Vec }`. /// /// See also `AscribeUserType` statement in MIR. - user_provided_types: ItemLocalMap>, + user_provided_types: ItemLocalMap>, /// Stores the canonicalized types provided by the user. See also /// `AscribeUserType` statement in MIR. @@ -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 @@ -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 @@ -800,25 +800,46 @@ impl<'a, 'gcx> HashStable> 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)>; + IndexVec>; + +#[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 @@ impl CanonicalUserTypeAnnotation<'gcx> { /// from constants that are named via paths, like `Foo::::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), } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index dd315cf42ce7e..930bbc0888517 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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}; diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index e1c2b611d0117..588f46cb77fe2 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -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; @@ -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 ); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 5c24da7621b2d..e6a974fd8cc94 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -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 @@ 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); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 180aa1907e8d1..3e6aa358ee0d1 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -35,10 +35,10 @@ use rustc::traits::query::type_op::custom::CustomTypeOp; 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 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { 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 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { 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 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, '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 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { 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 (`>::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>, } struct BorrowCheckContext<'a, 'tcx: 'a> { @@ -905,36 +901,69 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { 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; - - 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 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { 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, diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index a431bfc61b37a..31e0c0daa3fa6 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -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 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, '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, diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 3ed00d5797907..6bd61ab53fd21 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -6,7 +6,7 @@ use build::{BlockAnd, BlockAndExtension, Builder}; 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 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); 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, diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index e0fc90931696e..3de2f47578650 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -9,7 +9,7 @@ use hair::*; 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 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { .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, diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index d52ce9a67d29a..2f1e8c03f2f7e 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -9,7 +9,7 @@ use build::{BlockAnd, BlockAndExtension, Builder}; 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 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // // 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 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); 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, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index eb536fbcf69bb..8d64c9e9ada89 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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> { +) -> Option> { 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 diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index e902423cd30fc..f0f8acb31df42 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -9,7 +9,7 @@ use rustc::hir::def_id::DefId; 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:: { ... }`. - user_ty: Option>>, + user_ty: Option>>, fields: Vec>, base: Option> @@ -273,12 +273,12 @@ pub enum ExprKind<'tcx> { PlaceTypeAscription { source: ExprRef<'tcx>, /// Type that the user gave to this expression - user_ty: Option>>, + user_ty: Option>>, }, ValueTypeAscription { source: ExprRef<'tcx>, /// Type that the user gave to this expression - user_ty: Option>>, + user_ty: Option>>, }, Closure { closure_id: DefId, @@ -288,7 +288,7 @@ pub enum ExprKind<'tcx> { }, Literal { literal: &'tcx LazyConst<'tcx>, - user_ty: Option>>, + user_ty: Option>>, }, InlineAsm { asm: &'tcx hir::InlineAsm, diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index cdaffe5d45673..06a50f35be1cf 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -12,10 +12,10 @@ use hair::util::UserAnnotatedTyHelpers; 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>, + 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 @@ macro_rules! CloneImpls { 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> } diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir/hair/util.rs index f0f8263b64de5..cb4a72387fa16 100644 --- a/src/librustc_mir/hair/util.rs +++ b/src/librustc_mir/hair/util.rs @@ -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>; @@ -12,13 +12,13 @@ crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> { fn user_substs_applied_to_ty_of_hir_id( &self, hir_id: hir::HirId, - ) -> Option> { + ) -> Option> { 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) diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index f4685e0ddc909..3a15356806a97 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -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(), annotation, span)?; + 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, "|")?; diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index 52fcb5b80f4ae..526637e108d40 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -2,8 +2,6 @@ use rustc::infer::at::ToTrace; 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 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { 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 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { 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; - 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`. // diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ad4bc3cd83958..240db801fb2f2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -103,8 +103,8 @@ use rustc::middle::region; 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 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> { }; 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, '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); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index c61159eb49481..238b087fe32f8 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -404,7 +404,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { .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); diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index 88fd53d4ba59d..1bbbe67a12cb8 100644 --- a/src/test/mir-opt/basic_assignment.rs +++ b/src/test/mir-opt/basic_assignment.rs @@ -37,7 +37,7 @@ fn main() { // StorageLive(_4); // _4 = std::option::Option>::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; diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index 5b00c5c460316..bb794409ae01f 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -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: { diff --git a/src/test/ui/issue-54943.rs b/src/test/ui/issue-54943.rs index c720f62797580..ce4e010674359 100644 --- a/src/test/ui/issue-54943.rs +++ b/src/test/ui/issue-54943.rs @@ -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 index 0000000000000..aa68177bcdb58 --- /dev/null +++ b/src/test/ui/issue-54943.stderr @@ -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 index 0000000000000..77c50e53868e1 --- /dev/null +++ b/src/test/ui/issues/issue-57866.rs @@ -0,0 +1,26 @@ +// compile-pass + +#![feature(type_alias_enum_variants)] + +enum Outer { + A(T) +} + +enum Inner { + A(i32) +} + +type OuterAlias = Outer; + +fn ice(x: OuterAlias) { + // Fine + match x { + OuterAlias::A(Inner::A(_)) => (), + } + // Not fine + match x { + OuterAlias::A(Inner::A(y)) => (), + } +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr index acb978b5d5a2c..597b096dbe607 100644 --- a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr @@ -2,7 +2,7 @@ error[E0309]: the associated type `>::Output` may not live long --> $DIR/projection-where-clause-env-wrong-bound.rs:17:5 | LL | bar::() //~ ERROR may not live long enough - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = help: consider adding an explicit lifetime bound `>::Output: 'a`... diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr index 2d171a98789f8..3c2ac474778f9 100644 --- a/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr @@ -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::() //~ 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 index 0000000000000..a2e3ab41614f6 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/wf-unreachable.rs @@ -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 index 0000000000000..14642a1e615df --- /dev/null +++ b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr @@ -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 index 0000000000000..123be6b3e4098 --- /dev/null +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.rs @@ -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 index 0000000000000..57cfaa2db0432 --- /dev/null +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr @@ -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 index 0000000000000..23b76bb196470 --- /dev/null +++ b/src/test/ui/nll/user-annotations/downcast-infer.rs @@ -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::>(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 index 0000000000000..f4969bb4067c7 --- /dev/null +++ b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs @@ -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); +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 index 0000000000000..76be637220a15 --- /dev/null +++ b/src/test/ui/nll/user-annotations/issue-57731-ascibed-coupled-types.stderr @@ -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 index 0000000000000..76ead4e94ef66 --- /dev/null +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.ast.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'a WithAssoc>`, 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> = 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 index 0000000000000..ad94d375b5bb7 --- /dev/null +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.mir.stderr @@ -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> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + +error: aborting due to previous error + diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs index df7c1e0c7c78b..1d53492199230 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs @@ -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> = 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 index 0000000000000..73266ab50fad0 --- /dev/null +++ b/src/test/ui/regions/regions-free-region-ordering-caller.ast.stderr @@ -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 index 0000000000000..abec468c9ea3e --- /dev/null +++ b/src/test/ui/regions/regions-free-region-ordering-caller.mir.stderr @@ -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 + diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.rs b/src/test/ui/regions/regions-free-region-ordering-caller.rs index e26799fcc4711..621e6e78b4650 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller.rs +++ b/src/test/ui/regions/regions-free-region-ordering-caller.rs @@ -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() {} diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr index 92c21fcb4aec5..539343a68294f 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr @@ -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 index 0000000000000..d83301840088d --- /dev/null +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.ast.stderr @@ -0,0 +1,37 @@ +error[E0491]: in type `&'a WithHrAssoc>`, reference has a longer lifetime than the data it references + --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12 + | +LL | let _: &'a WithHrAssoc> = 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>`, reference has a longer lifetime than the data it references + --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12 + | +LL | let _: &'a WithHrAssocSub> = 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 index 0000000000000..5028663ba6d04 --- /dev/null +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.mir.stderr @@ -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> = 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> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs index 3483f24ecbf66..2871d962c42c9 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs @@ -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> = 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> = 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 index 0000000000000..9e31065ca4eec --- /dev/null +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.ast.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifetime than the data it references + --> $DIR/regions-outlives-projection-container-wc.rs:37:12 + | +LL | let _: &'a WithAssoc> = 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 index 0000000000000..880fe17b740e4 --- /dev/null +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.mir.stderr @@ -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> = loop { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` + +error: aborting due to previous error + diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.rs b/src/test/ui/regions/regions-outlives-projection-container-wc.rs index 91a0d8590ff34..37622211327c0 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.rs @@ -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> = loop { }; - //~^ ERROR reference has a longer lifetime + //[ast]~^ ERROR reference has a longer lifetime + //[mir]~^^ ERROR lifetime may not live long enough } fn main() {