Stop well-formedness checking unreachable code.
This commit stops well-formedness checking applying to unreachable code and therefore stops some of the ICEs that the intended solution taken by this PR causes. By disabling these checks, we can land the other fixes and larger refactors that this PR includes.
This commit is contained in:
parent
95c18382cb
commit
28fd1b04e5
@ -62,8 +62,7 @@ use syntax_pos::symbol::InternedString;
|
||||
use traits;
|
||||
use traits::query::{
|
||||
CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
|
||||
CanonicalTypeOpAscribeUserTypeWellFormedGoal, CanonicalTypeOpEqGoal,
|
||||
CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal,
|
||||
CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal,
|
||||
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
|
||||
};
|
||||
use ty::{TyCtxt, FnSig, Instance, InstanceDef,
|
||||
@ -651,7 +650,6 @@ define_dep_nodes!( <'tcx>
|
||||
[] EvaluateObligation(CanonicalPredicateGoal<'tcx>),
|
||||
[] EvaluateGoal(traits::ChalkCanonicalGoal<'tcx>),
|
||||
[] TypeOpAscribeUserType(CanonicalTypeOpAscribeUserTypeGoal<'tcx>),
|
||||
[] TypeOpAscribeUserTypeWellFormed(CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>),
|
||||
[] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>),
|
||||
[] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>),
|
||||
[] TypeOpProvePredicate(CanonicalTypeOpProvePredicateGoal<'tcx>),
|
||||
|
@ -28,10 +28,6 @@ pub type CanonicalPredicateGoal<'tcx> =
|
||||
pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
|
||||
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ascribe_user_type::AscribeUserType<'tcx>>>;
|
||||
|
||||
pub type CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx> =
|
||||
Canonical<'tcx, ty::ParamEnvAnd<'tcx,
|
||||
type_op::ascribe_user_type::AscribeUserTypeWellFormed<'tcx>>>;
|
||||
|
||||
pub type CanonicalTypeOpEqGoal<'tcx> =
|
||||
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::eq::Eq<'tcx>>>;
|
||||
|
||||
|
@ -2,7 +2,7 @@ use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, Que
|
||||
use traits::query::Fallible;
|
||||
use hir::def_id::DefId;
|
||||
use mir::ProjectionKind;
|
||||
use ty::{self, ParamEnvAnd, Ty, TyCtxt, UserTypeAnnotation};
|
||||
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
|
||||
use ty::subst::UserSubsts;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
@ -68,59 +68,3 @@ impl_stable_hash_for! {
|
||||
mir_ty, variance, def_id, user_substs, projs
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct AscribeUserTypeWellFormed<'tcx> {
|
||||
pub user_type_annotation: UserTypeAnnotation<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> AscribeUserTypeWellFormed<'tcx> {
|
||||
pub fn new(
|
||||
user_type_annotation: UserTypeAnnotation<'tcx>,
|
||||
) -> Self {
|
||||
Self { user_type_annotation, }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for AscribeUserTypeWellFormed<'tcx> {
|
||||
type QueryResponse = ();
|
||||
|
||||
fn try_fast_path(
|
||||
_tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||
_key: &ParamEnvAnd<'tcx, Self>,
|
||||
) -> Option<Self::QueryResponse> {
|
||||
None
|
||||
}
|
||||
|
||||
fn perform_query(
|
||||
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
|
||||
) -> Fallible<CanonicalizedQueryResponse<'gcx, ()>> {
|
||||
tcx.type_op_ascribe_user_type_well_formed(canonicalized)
|
||||
}
|
||||
|
||||
fn shrink_to_tcx_lifetime(
|
||||
v: &'a CanonicalizedQueryResponse<'gcx, ()>,
|
||||
) -> &'a Canonical<'tcx, QueryResponse<'tcx, ()>> {
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for AscribeUserTypeWellFormed<'tcx> {
|
||||
user_type_annotation
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for AscribeUserTypeWellFormed<'a> {
|
||||
type Lifted = AscribeUserTypeWellFormed<'tcx>;
|
||||
user_type_annotation
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for! {
|
||||
struct AscribeUserTypeWellFormed<'tcx> {
|
||||
user_type_annotation
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,7 @@ use mir::interpret::GlobalId;
|
||||
use traits;
|
||||
use traits::query::{
|
||||
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
|
||||
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpAscribeUserTypeWellFormedGoal,
|
||||
CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
|
||||
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
|
||||
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
|
||||
};
|
||||
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
|
||||
@ -125,15 +124,6 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_ascribe_user_type<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::type_op_ascribe_user_type_well_formed<'tcx> {
|
||||
fn describe(
|
||||
_tcx: TyCtxt<'_, '_, '_>,
|
||||
goal: CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>,
|
||||
) -> Cow<'static, str> {
|
||||
format!("evaluating `type_op_ascribe_user_type_well_formed` `{:?}`", goal).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> {
|
||||
fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpEqGoal<'tcx>) -> Cow<'static, str> {
|
||||
format!("evaluating `type_op_eq` `{:?}`", goal).into()
|
||||
|
@ -27,8 +27,7 @@ use traits::{self, Vtable};
|
||||
use traits::query::{
|
||||
CanonicalPredicateGoal, CanonicalProjectionGoal,
|
||||
CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
|
||||
CanonicalTypeOpAscribeUserTypeWellFormedGoal, CanonicalTypeOpEqGoal,
|
||||
CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal,
|
||||
CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal,
|
||||
CanonicalTypeOpNormalizeGoal, NoSolution,
|
||||
};
|
||||
use traits::query::method_autoderef::MethodAutoderefStepsResult;
|
||||
@ -610,14 +609,6 @@ define_queries! { <'tcx>
|
||||
NoSolution,
|
||||
>,
|
||||
|
||||
/// Do not call this query directly: part of the `Eq` type-op
|
||||
[] fn type_op_ascribe_user_type_well_formed: TypeOpAscribeUserTypeWellFormed(
|
||||
CanonicalTypeOpAscribeUserTypeWellFormedGoal<'tcx>
|
||||
) -> Result<
|
||||
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
|
||||
NoSolution,
|
||||
>,
|
||||
|
||||
/// Do not call this query directly: part of the `Eq` type-op
|
||||
[] fn type_op_eq: TypeOpEq(
|
||||
CanonicalTypeOpEqGoal<'tcx>
|
||||
|
@ -1208,7 +1208,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
||||
DepKind::EvaluateObligation |
|
||||
DepKind::EvaluateGoal |
|
||||
DepKind::TypeOpAscribeUserType |
|
||||
DepKind::TypeOpAscribeUserTypeWellFormed |
|
||||
DepKind::TypeOpEq |
|
||||
DepKind::TypeOpSubtype |
|
||||
DepKind::TypeOpProvePredicate |
|
||||
|
@ -289,6 +289,11 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||
self.out.extend(obligations);
|
||||
}
|
||||
|
||||
ty::FnDef(did, substs) => {
|
||||
let obligations = self.nominal_obligations(did, substs);
|
||||
self.out.extend(obligations);
|
||||
}
|
||||
|
||||
ty::Ref(r, rty, _) => {
|
||||
// WfReference
|
||||
if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
|
||||
@ -349,7 +354,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::FnDef(..) | ty::FnPtr(_) => {
|
||||
ty::FnPtr(_) => {
|
||||
// let the loop iterate into the argument/return
|
||||
// types appearing in the fn signature
|
||||
}
|
||||
|
@ -928,37 +928,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
);
|
||||
}
|
||||
|
||||
/// Check that user type annotations are well formed.
|
||||
fn check_user_type_annotations_are_well_formed(&mut self) {
|
||||
for index in self.mir.user_type_annotations.indices() {
|
||||
let (span, _) = &self.mir.user_type_annotations[index];
|
||||
let type_annotation = self.instantiated_type_annotations[&index];
|
||||
match type_annotation {
|
||||
// We can't check the well-formedness of a `UserTypeAnnotation::Ty` here, it will
|
||||
// cause ICEs (see comment in `relate_type_and_user_type`).
|
||||
UserTypeAnnotation::TypeOf(..) => {
|
||||
if let Err(terr) = self.fully_perform_op(
|
||||
Locations::All(*span),
|
||||
ConstraintCategory::Assignment,
|
||||
self.param_env.and(
|
||||
type_op::ascribe_user_type::AscribeUserTypeWellFormed::new(
|
||||
type_annotation,
|
||||
)
|
||||
),
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
type_annotation,
|
||||
"bad user type annotation: {:?}",
|
||||
terr,
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given some operation `op` that manipulates types, proves
|
||||
/// predicates, or otherwise uses the inference context, executes
|
||||
/// `op` and then executes all the further obligations that `op`
|
||||
@ -1127,27 +1096,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
if let Ok(projected_ty) = curr_projected_ty {
|
||||
let ty = projected_ty.to_ty(tcx);
|
||||
self.relate_types(ty, v1, a, locations, category)?;
|
||||
|
||||
// We'll get an ICE if we check for well-formedness of a
|
||||
// `UserTypeAnnotation::Ty` that hasn't had types related.
|
||||
//
|
||||
// Doing this without the types having been related will result in
|
||||
// `probe_ty_var` failing in the canonicalizer - in practice, this
|
||||
// results in three run-pass tests failing. You can work around that
|
||||
// by keeping an vec of projections instead of annotations and performing
|
||||
// the projections before storing into `instantiated_type_annotations`
|
||||
// but that still fails in dead code.
|
||||
self.fully_perform_op(
|
||||
locations,
|
||||
category,
|
||||
self.param_env.and(
|
||||
type_op::ascribe_user_type::AscribeUserTypeWellFormed::new(
|
||||
UserTypeAnnotation::Ty(ty),
|
||||
)
|
||||
),
|
||||
)?;
|
||||
}
|
||||
|
||||
}
|
||||
UserTypeAnnotation::TypeOf(def_id, user_substs) => {
|
||||
let projs = self.infcx.tcx.intern_projs(&user_ty.projs);
|
||||
@ -2453,8 +2402,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
self.check_terminator(mir, block_data.terminator(), location);
|
||||
self.check_iscleanup(mir, block_data);
|
||||
}
|
||||
|
||||
self.check_user_type_annotations_are_well_formed();
|
||||
}
|
||||
|
||||
fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
|
||||
|
@ -4,7 +4,7 @@ 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, AscribeUserTypeWellFormed};
|
||||
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;
|
||||
use rustc::traits::query::type_op::prove_predicate::ProvePredicate;
|
||||
@ -17,7 +17,6 @@ use rustc::ty::query::Providers;
|
||||
use rustc::ty::subst::{Kind, Subst, UserSubsts, UserSelfTy};
|
||||
use rustc::ty::{
|
||||
FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance,
|
||||
UserTypeAnnotation,
|
||||
};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use std::fmt;
|
||||
@ -27,7 +26,6 @@ use syntax_pos::DUMMY_SP;
|
||||
crate fn provide(p: &mut Providers) {
|
||||
*p = Providers {
|
||||
type_op_ascribe_user_type,
|
||||
type_op_ascribe_user_type_well_formed,
|
||||
type_op_eq,
|
||||
type_op_prove_predicate,
|
||||
type_op_subtype,
|
||||
@ -62,28 +60,6 @@ fn type_op_ascribe_user_type<'tcx>(
|
||||
})
|
||||
}
|
||||
|
||||
fn type_op_ascribe_user_type_well_formed<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserTypeWellFormed<'tcx>>>,
|
||||
) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> {
|
||||
tcx.infer_ctxt()
|
||||
.enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
|
||||
let (
|
||||
param_env, AscribeUserTypeWellFormed { user_type_annotation }
|
||||
) = key.into_parts();
|
||||
|
||||
debug!(
|
||||
"type_op_ascribe_user_type_well_formed: user_type_annotation={:?}",
|
||||
user_type_annotation,
|
||||
);
|
||||
|
||||
let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
|
||||
cx.well_formed(user_type_annotation)?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
struct AscribeUserTypeCx<'me, 'gcx: 'tcx, 'tcx: 'me> {
|
||||
infcx: &'me InferCtxt<'me, 'gcx, 'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
@ -133,56 +109,6 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> {
|
||||
value.subst(self.tcx(), substs)
|
||||
}
|
||||
|
||||
fn well_formed(
|
||||
&mut self,
|
||||
type_annotation: UserTypeAnnotation<'tcx>
|
||||
) -> Result<(), NoSolution> {
|
||||
match type_annotation {
|
||||
UserTypeAnnotation::Ty(ty) => {
|
||||
self.prove_predicate(Predicate::WellFormed(ty));
|
||||
Ok(())
|
||||
},
|
||||
UserTypeAnnotation::TypeOf(did, user_substs) => {
|
||||
let UserSubsts {
|
||||
user_self_ty,
|
||||
substs,
|
||||
} = user_substs;
|
||||
|
||||
let ty = self.tcx().type_of(did);
|
||||
let ty = self.subst(ty, substs);
|
||||
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
|
||||
let ty = self.normalize(ty);
|
||||
|
||||
if let Some(UserSelfTy {
|
||||
impl_def_id,
|
||||
self_ty,
|
||||
}) = user_self_ty {
|
||||
let impl_self_ty = self.tcx().type_of(impl_def_id);
|
||||
let impl_self_ty = self.subst(impl_self_ty, &substs);
|
||||
let impl_self_ty = self.normalize(impl_self_ty);
|
||||
|
||||
self.relate(self_ty, Variance::Invariant, impl_self_ty)?;
|
||||
|
||||
self.prove_predicate(Predicate::WellFormed(impl_self_ty));
|
||||
}
|
||||
|
||||
// In addition to proving the predicates, we have to
|
||||
// prove that `ty` is well-formed -- this is because
|
||||
// the WF of `ty` is predicated on the substs being
|
||||
// well-formed, and we haven't proven *that*. We don't
|
||||
// want to prove the WF of types from `substs` directly because they
|
||||
// haven't been normalized.
|
||||
//
|
||||
// FIXME(nmatsakis): Well, perhaps we should normalize
|
||||
// them? This would only be relevant if some input
|
||||
// type were ill-formed but did not appear in `ty`,
|
||||
// which...could happen with normalization...
|
||||
self.prove_predicate(Predicate::WellFormed(ty));
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn relate_mir_and_user_ty(
|
||||
&mut self,
|
||||
mir_ty: Ty<'tcx>,
|
||||
@ -192,7 +118,7 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> {
|
||||
projs: &[ProjectionKind<'tcx>],
|
||||
) -> Result<(), NoSolution> {
|
||||
let UserSubsts {
|
||||
user_self_ty: _,
|
||||
user_self_ty,
|
||||
substs,
|
||||
} = user_substs;
|
||||
let tcx = self.tcx();
|
||||
@ -245,6 +171,31 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> {
|
||||
self.prove_predicate(instantiated_predicate);
|
||||
}
|
||||
|
||||
if let Some(UserSelfTy {
|
||||
impl_def_id,
|
||||
self_ty,
|
||||
}) = user_self_ty {
|
||||
let impl_self_ty = self.tcx().type_of(impl_def_id);
|
||||
let impl_self_ty = self.subst(impl_self_ty, &substs);
|
||||
let impl_self_ty = self.normalize(impl_self_ty);
|
||||
|
||||
self.relate(self_ty, Variance::Invariant, impl_self_ty)?;
|
||||
|
||||
self.prove_predicate(Predicate::WellFormed(impl_self_ty));
|
||||
}
|
||||
|
||||
// In addition to proving the predicates, we have to
|
||||
// prove that `ty` is well-formed -- this is because
|
||||
// the WF of `ty` is predicated on the substs being
|
||||
// well-formed, and we haven't proven *that*. We don't
|
||||
// want to prove the WF of types from `substs` directly because they
|
||||
// haven't been normalized.
|
||||
//
|
||||
// FIXME(nmatsakis): Well, perhaps we should normalize
|
||||
// them? This would only be relevant if some input
|
||||
// type were ill-formed but did not appear in `ty`,
|
||||
// which...could happen with normalization...
|
||||
self.prove_predicate(Predicate::WellFormed(ty));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
21
src/test/ui/issue-54943-3.rs
Normal file
21
src/test/ui/issue-54943-3.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// compile-pass
|
||||
// FIXME(#54943) This test targets the scenario where proving the WF requirements requires
|
||||
// knowing the value of the `_` type present in the user type annotation - unfortunately, figuring
|
||||
// out the value of that `_` requires type-checking the surrounding code, but that code is dead,
|
||||
// so our NLL region checker doesn't have access to it. This test should actually fail to compile.
|
||||
|
||||
#![feature(nll)]
|
||||
#![allow(warnings)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
fn foo<T: 'static + Debug>(_: T) { }
|
||||
|
||||
fn bar<'a>() {
|
||||
return;
|
||||
|
||||
let _x = foo::<Vec<_>>(Vec::<&'a u32>::new());
|
||||
//~^ ERROR the type `&'a u32` does not fulfill the required lifetime [E0477]
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,8 +1,17 @@
|
||||
// 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)]
|
||||
|
||||
fn foo<T: 'static>() { }
|
||||
|
||||
fn main<'a>() {
|
||||
fn boo<'a>() {
|
||||
return;
|
||||
|
||||
let x = foo::<&'a u32>();
|
||||
//~^ ERROR the type `&'a u32` does not fulfill the required lifetime [E0477]
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,11 +0,0 @@
|
||||
error[E0477]: the type `&'a u32` does not fulfill the required lifetime
|
||||
--> $DIR/issue-54943.rs:6:13
|
||||
|
|
||||
LL | let x = foo::<&'a u32>();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: type must satisfy the static lifetime
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0477`.
|
@ -12,21 +12,6 @@ LL | let z: &'a & usize = &(&y);
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
||||
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 previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors occurred: E0597, E0716.
|
||||
For more information about an error, try `rustc --explain E0597`.
|
||||
For more information about this error, try `rustc --explain E0716`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user