Auto merge of #57714 - matthewjasper:wellformed-unreachable, r=pnkfelix

[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
This commit is contained in:
bors 2019-01-25 14:25:37 +00:00
commit 0b1669d96c
49 changed files with 849 additions and 291 deletions

View File

@ -1240,16 +1240,22 @@ impl_stable_hash_for!(
}
);
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::UserTypeAnnotation<'gcx> {
impl_stable_hash_for!(
struct ty::CanonicalUserTypeAnnotation<'tcx> {
user_ty, span, inferred_ty
}
);
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::UserType<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
ty::UserTypeAnnotation::Ty(ref ty) => {
ty::UserType::Ty(ref ty) => {
ty.hash_stable(hcx, hasher);
}
ty::UserTypeAnnotation::TypeOf(ref def_id, ref substs) => {
ty::UserType::TypeOf(ref def_id, ref substs) => {
def_id.hash_stable(hcx, hasher);
substs.hash_stable(hcx, hasher);
}

View File

@ -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;

View File

@ -75,8 +75,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
elem: &PlaceElem<'tcx>)
-> PlaceTy<'tcx>
{
self.projection_ty_core(tcx, elem, |_, _, ty| -> Result<Ty<'tcx>, ()> { Ok(ty) })
.unwrap()
self.projection_ty_core(tcx, elem, |_, _, ty| ty)
}
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@ -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<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 @@ 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
}
}

View 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 @@ 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),

View 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 @@ 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
}
}

View 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 @@ 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<StableHashingContext<'a>> for TypeckTables<'gcx> {
newtype_index! {
pub struct UserTypeAnnotationIndex {
DEBUG_FORMAT = "UserTypeAnnotation({})",
DEBUG_FORMAT = "UserType({})",
const START_INDEX = 0,
}
}
/// Mapping of type annotation indices to canonical user type annotations.
pub type CanonicalUserTypeAnnotations<'tcx> =
IndexVec<UserTypeAnnotationIndex, (Span, CanonicalUserTypeAnnotation<'tcx>)>;
IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct CanonicalUserTypeAnnotation<'tcx> {
pub user_ty: CanonicalUserType<'tcx>,
pub span: Span,
pub inferred_ty: Ty<'tcx>,
}
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for CanonicalUserTypeAnnotation<'tcx> {
user_ty, span, inferred_ty
}
}
BraceStructLiftImpl! {
impl<'a, 'tcx> Lift<'tcx> for CanonicalUserTypeAnnotation<'a> {
type Lifted = CanonicalUserTypeAnnotation<'tcx>;
user_ty, span, inferred_ty
}
}
/// Canonicalized user type annotation.
pub type CanonicalUserTypeAnnotation<'gcx> = Canonical<'gcx, UserTypeAnnotation<'gcx>>;
pub type CanonicalUserType<'gcx> = Canonical<'gcx, UserType<'gcx>>;
impl CanonicalUserTypeAnnotation<'gcx> {
impl CanonicalUserType<'gcx> {
/// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`,
/// i.e. each thing is mapped to a canonical variable with the same index.
pub fn is_identity(&self) -> bool {
match self.value {
UserTypeAnnotation::Ty(_) => false,
UserTypeAnnotation::TypeOf(_, user_substs) => {
UserType::Ty(_) => false,
UserType::TypeOf(_, user_substs) => {
if user_substs.user_self_ty.is_some() {
return false;
}
@ -853,7 +874,7 @@ impl CanonicalUserTypeAnnotation<'gcx> {
/// from constants that are named via paths, like `Foo::<A>::new` and
/// so forth.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum UserTypeAnnotation<'tcx> {
pub enum UserType<'tcx> {
Ty(Ty<'tcx>),
/// The canonical type is the result of `type_of(def_id)` with the
@ -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),
}
}

View File

@ -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};

View File

@ -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
);

View 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 @@ 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);

View File

@ -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 (`<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 @@ 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<PlaceTy, HitTyVar>;
let tcx = self.infcx.tcx;
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);
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,

View 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 @@ 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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View 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

View File

@ -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::<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,

View File

@ -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<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 @@ 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>
}

View 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>;
@ -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<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)

View 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(), 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, "|")?;

View File

@ -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<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`.
//

View File

@ -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);
}

View File

@ -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);

View 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;

View 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: {

View 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() {}

View File

@ -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

View File

@ -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() {}

View 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`...

View 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`...

View File

@ -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() {}

View File

@ -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

View File

@ -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
}

View File

@ -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`.

View File

@ -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))) => (),
_ => (),
}
}

View File

@ -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() {}

View File

@ -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

View File

@ -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`.

View File

@ -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

View 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() {

View File

@ -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`.

View File

@ -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

View 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() {}

View 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
For more information about this error, try `rustc --explain E0716`.
error: aborting due to 2 previous errors
Some errors occurred: E0597, E0716.
For more information about an error, try `rustc --explain E0597`.

View File

@ -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`.

View File

@ -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

View 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
}

View File

@ -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`.

View File

@ -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

View 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() {