Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] some mir typeck cleanup #95763

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
@@ -89,12 +89,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
locations: Locations,
category: ConstraintCategory,
) {
self.prove_predicates(
Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
self.prove_predicate(
ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}))),
}))
.to_predicate(self.tcx()),
locations,
category,
);
Original file line number Diff line number Diff line change
@@ -280,7 +280,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
// }
// impl Foo for () {
// type Bar = ();
// fn foo(&self) ->&() {}
// fn foo(&self) -> &() {}
// }
// ```
// Both &Self::Bar and &() are WF
231 changes: 88 additions & 143 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
@@ -90,7 +90,7 @@ macro_rules! span_mirbug_and_err {
($context:expr, $elem:expr, $($message:tt)*) => ({
{
span_mirbug!($context, $elem, $($message)*);
$context.error()
$context.tcx().ty_error()
}
})
}
@@ -181,107 +181,69 @@ pub(crate) fn type_check<'mir, 'tcx>(
upvars,
};

let opaque_type_values = type_check_internal(
let mut checker = TypeChecker::new(
infcx,
param_env,
body,
promoted,
param_env,
&region_bound_pairs,
implicit_region_bound,
&mut borrowck_context,
|mut cx| {
cx.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
liveness::generate(
&mut cx,
body,
elements,
flow_inits,
move_data,
location_table,
use_polonius,
);

translate_outlives_facts(&mut cx);
let opaque_type_values =
infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();

opaque_type_values
.into_iter()
.map(|(opaque_type_key, decl)| {
cx.fully_perform_op(
Locations::All(body.span),
ConstraintCategory::OpaqueType,
CustomTypeOp::new(
|infcx| {
infcx.register_member_constraints(
param_env,
opaque_type_key,
decl.hidden_type.ty,
decl.hidden_type.span,
);
Ok(InferOk { value: (), obligations: vec![] })
},
|| "opaque_type_map".to_string(),
),
)
.unwrap();
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
trace!(
"finalized opaque type {:?} to {:#?}",
opaque_type_key,
hidden_type.ty.kind()
);
if hidden_type.has_infer_types_or_consts() {
infcx.tcx.sess.delay_span_bug(
decl.hidden_type.span,
&format!("could not resolve {:#?}", hidden_type.ty.kind()),
);
hidden_type.ty = infcx.tcx.ty_error();
}

(opaque_type_key, (hidden_type, decl.origin))
})
.collect()
},
);

MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
}
let mut verifier = TypeVerifier::new(&mut checker, promoted);
verifier.visit_body(&body);

#[instrument(
skip(infcx, body, promoted, region_bound_pairs, borrowck_context, extra),
level = "debug"
)]
fn type_check_internal<'a, 'tcx, R>(
infcx: &'a InferCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &'a Body<'tcx>,
promoted: &'a IndexVec<Promoted, Body<'tcx>>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R,
) -> R {
let mut checker = TypeChecker::new(
infcx,
checker.typeck_mir(body);

checker.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
liveness::generate(
&mut checker,
body,
param_env,
region_bound_pairs,
implicit_region_bound,
borrowck_context,
elements,
flow_inits,
move_data,
location_table,
use_polonius,
);
let errors_reported = {
let mut verifier = TypeVerifier::new(&mut checker, promoted);
verifier.visit_body(&body);
verifier.errors_reported
};

if !errors_reported {
// if verifier failed, don't do further checks to avoid ICEs
checker.typeck_mir(body);
}
translate_outlives_facts(&mut checker);
let opaque_type_values = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
let opaque_type_values = opaque_type_values
.into_iter()
.map(|(opaque_type_key, decl)| {
checker
.fully_perform_op(
Locations::All(body.span),
ConstraintCategory::OpaqueType,
CustomTypeOp::new(
|infcx| {
infcx.register_member_constraints(
param_env,
opaque_type_key,
decl.hidden_type.ty,
decl.hidden_type.span,
);
Ok(InferOk { value: (), obligations: vec![] })
},
|| "opaque_type_map".to_string(),
),
)
.unwrap();
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
if hidden_type.has_infer_types_or_consts() {
infcx.tcx.sess.delay_span_bug(
decl.hidden_type.span,
&format!("could not resolve {:#?}", hidden_type.ty.kind()),
);
hidden_type.ty = infcx.tcx.ty_error();
}

extra(checker)
(opaque_type_key, (hidden_type, decl.origin))
})
.collect();

MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
}

fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
@@ -323,14 +285,11 @@ enum FieldAccessError {

/// Verifies that MIR types are sane to not crash further checks.
///
/// The sanitize_XYZ methods here take an MIR object and compute its
/// type, calling `span_mirbug` and returning an error type if there
/// is a problem.
/// FIXME: Merge this with `TypeChecker`.
struct TypeVerifier<'a, 'b, 'tcx> {
cx: &'a mut TypeChecker<'b, 'tcx>,
promoted: &'b IndexVec<Promoted, Body<'tcx>>,
last_span: Span,
errors_reported: bool,
}

impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
@@ -387,34 +346,25 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
};
if let Some(uv) = maybe_uneval {
if let Some(promoted) = uv.promoted {
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
promoted: &Body<'tcx>,
ty,
san_ty| {
if let Err(terr) = verifier.cx.eq_types(
let promoted_body = &self.promoted[promoted];
self.sanitize_promoted(promoted_body, location);

let promoted_ty = promoted_body.return_ty();
if let Err(terr) = self.cx.eq_types(
ty,
promoted_ty,
location.to_locations(),
ConstraintCategory::Boring,
) {
span_mirbug!(
self,
promoted_body,
"bad promoted type ({:?}: {:?}): {:?}",
ty,
san_ty,
location.to_locations(),
ConstraintCategory::Boring,
) {
span_mirbug!(
verifier,
promoted,
"bad promoted type ({:?}: {:?}): {:?}",
ty,
san_ty,
terr
);
};
promoted_ty,
terr
);
};

if !self.errors_reported {
let promoted_body = &self.promoted[promoted];
self.sanitize_promoted(promoted_body, location);

let promoted_ty = promoted_body.return_ty();
check_err(self, promoted_body, ty, promoted_ty);
}
} else {
if let Err(terr) = self.cx.fully_perform_op(
location.to_locations(),
@@ -450,14 +400,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
}
}

if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() {
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
self.cx.normalize_and_prove_instantiated_predicates(
def_id,
instantiated_predicates,
location.to_locations(),
);
}
self.cx.prove_predicate(
ty::Binder::dummy(ty::PredicateKind::WellFormed(constant.literal.ty().into()))
.to_predicate(self.tcx()),
location.to_locations(),
ConstraintCategory::Boring,
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't we file a bug about this?

}
}

@@ -512,9 +460,6 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
for local_decl in &body.local_decls {
self.sanitize_type(local_decl, local_decl.ty);
}
if self.errors_reported {
return;
}
self.super_body(body);
}
}
@@ -524,7 +469,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
cx: &'a mut TypeChecker<'b, 'tcx>,
promoted: &'b IndexVec<Promoted, Body<'tcx>>,
) -> Self {
TypeVerifier { promoted, last_span: cx.body.span, cx, errors_reported: false }
TypeVerifier { promoted, last_span: cx.body.span, cx }
}

fn body(&self) -> &Body<'tcx> {
@@ -558,13 +503,21 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
for elem in place.projection.iter() {
if place_ty.variant_index.is_none() {
if place_ty.ty.references_error() {
assert!(self.errors_reported);
return PlaceTy::from_ty(self.tcx().ty_error());
}
}
place_ty = self.sanitize_projection(place_ty, elem, place, location);
}

self.cx.prove_predicate(
ty::Binder::dummy(ty::PredicateKind::WellFormed(
self.body().local_decls[place.local].ty.into(),
))
.to_predicate(self.tcx()),
location.to_locations(),
ConstraintCategory::Boring,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have a known bug that is affected by this?

);

if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
let tcx = self.tcx();
let trait_ref = ty::TraitRef {
@@ -629,10 +582,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {

self.visit_body(&promoted_body);

if !self.errors_reported {
// if verifier failed, don't do further checks to avoid ICEs
self.cx.typeck_mir(promoted_body);
}
self.cx.typeck_mir(promoted_body);

self.cx.body = parent_body;
// Merge the outlives constraints back in, at the given location.
@@ -790,11 +740,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}
}

fn error(&mut self) -> Ty<'tcx> {
self.errors_reported = true;
self.tcx().ty_error()
}

fn field_ty(
&mut self,
parent: &dyn fmt::Debug,
@@ -1926,7 +1871,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}

&Rvalue::NullaryOp(_, ty) => {
&Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
let trait_ref = ty::TraitRef {
def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
substs: tcx.mk_substs_trait(ty, &[]),
Original file line number Diff line number Diff line change
@@ -113,7 +113,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
infcx.tcx.struct_span_lint_hir(
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
infcx.tcx.hir().local_def_id_to_hir_id(local_def_id),
span,
tcx.def_span(local_def_id),
|err| {
err.build("cannot use constants which depend on generic parameters in types")
.emit();
4 changes: 2 additions & 2 deletions library/std/src/collections/hash/map.rs
Original file line number Diff line number Diff line change
@@ -2878,8 +2878,8 @@ where
#[stable(feature = "hash_extend_copy", since = "1.4.0")]
impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap<K, V, S>
where
K: Eq + Hash + Copy,
V: Copy,
K: Eq + Hash + Copy + 'a,
V: Copy + 'a,
S: BuildHasher,
{
#[inline]
2 changes: 2 additions & 0 deletions src/test/ui/borrowck/issue-7573.rs
Original file line number Diff line number Diff line change
@@ -17,6 +17,8 @@ pub fn remove_package_from_database() {
lines_to_use.push(installed_id);
//~^ ERROR borrowed data escapes outside of closure
//~| NOTE `installed_id` escapes the closure body here
//~| NOTE requirement occurs because of a mutable reference to `Vec<&CrateId>`
//~| NOTE mutable references are invariant over their type parameter
};
list_database(push_id);

4 changes: 4 additions & 0 deletions src/test/ui/borrowck/issue-7573.stderr
Original file line number Diff line number Diff line change
@@ -9,6 +9,10 @@ LL | let push_id = |installed_id: &CrateId| {
LL |
LL | lines_to_use.push(installed_id);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `installed_id` escapes the closure body here
|
= note: requirement occurs because of a mutable reference to `Vec<&CrateId>`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

error: aborting due to previous error

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// compile-flags: -Zdeduplicate-diagnostics=yes
// check-pass

const fn foo<T>() -> usize {
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
warning: cannot use constants which depend on generic parameters in types
--> $DIR/function-call.rs:14:17
--> $DIR/function-call.rs:15:17
|
LL | let _ = [0; foo::<T>()];
| ^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// compile-flags: -Zdeduplicate-diagnostics=yes
// check-pass
#![allow(dead_code)]

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
warning: cannot use constants which depend on generic parameters in types
--> $DIR/const-evaluatable-unchecked.rs:5:9
--> $DIR/const-evaluatable-unchecked.rs:6:9
|
LL | [0; std::mem::size_of::<*mut T>()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL | [0; std::mem::size_of::<*mut T>()];
= note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>

warning: cannot use constants which depend on generic parameters in types
--> $DIR/const-evaluatable-unchecked.rs:16:21
--> $DIR/const-evaluatable-unchecked.rs:17:21
|
LL | let _ = [0; Self::ASSOC];
| ^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL | let _ = [0; Self::ASSOC];
= note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>

warning: cannot use constants which depend on generic parameters in types
--> $DIR/const-evaluatable-unchecked.rs:28:21
--> $DIR/const-evaluatable-unchecked.rs:29:21
|
LL | let _ = [0; Self::ASSOC];
| ^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: implementation of `Parser` is not general enough
--> $DIR/issue-71955.rs:54:5
--> $DIR/issue-71955.rs:52:5
|
LL | foo(bar, "string", |s| s.len() == 5);
| ^^^ implementation of `Parser` is not general enough
@@ -8,7 +8,7 @@ LL | foo(bar, "string", |s| s.len() == 5);
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`

error: implementation of `Parser` is not general enough
--> $DIR/issue-71955.rs:58:5
--> $DIR/issue-71955.rs:56:5
|
LL | foo(baz, "string", |s| s.0.len() == 5);
| ^^^ implementation of `Parser` is not general enough
Original file line number Diff line number Diff line change
@@ -1,79 +1,38 @@
error[E0308]: mismatched types
--> $DIR/issue-71955.rs:54:5
error: implementation of `Parser` is not general enough
--> $DIR/issue-71955.rs:52:5
|
LL | foo(bar, "string", |s| s.len() == 5);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough
|
= note: expected type `for<'r, 's> FnOnce<(&'r &'s str,)>`
found type `for<'r> FnOnce<(&'r &str,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-71955.rs:54:24
|
LL | foo(bar, "string", |s| s.len() == 5);
| ^^^^^^^^^^^^^^^^
note: the lifetime requirement is introduced here
--> $DIR/issue-71955.rs:34:9
|
LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`

error[E0308]: mismatched types
--> $DIR/issue-71955.rs:54:5
|
LL | foo(bar, "string", |s| s.len() == 5);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected type `FnOnce<(&&str,)>`
found type `for<'r> FnOnce<(&'r &str,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-71955.rs:54:24
error: implementation of `Parser` is not general enough
--> $DIR/issue-71955.rs:52:5
|
LL | foo(bar, "string", |s| s.len() == 5);
| ^^^^^^^^^^^^^^^^
note: the lifetime requirement is introduced here
--> $DIR/issue-71955.rs:34:44
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough
|
LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
| ^^^^
= note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`

error[E0308]: mismatched types
--> $DIR/issue-71955.rs:58:5
error: implementation of `Parser` is not general enough
--> $DIR/issue-71955.rs:56:5
|
LL | foo(baz, "string", |s| s.0.len() == 5);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough
|
= note: expected type `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>`
found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-71955.rs:58:24
|
LL | foo(baz, "string", |s| s.0.len() == 5);
| ^^^^^^^^^^^^^^^^^^
note: the lifetime requirement is introduced here
--> $DIR/issue-71955.rs:34:9
|
LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`

error[E0308]: mismatched types
--> $DIR/issue-71955.rs:58:5
|
LL | foo(baz, "string", |s| s.0.len() == 5);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected type `FnOnce<(&Wrapper<'_>,)>`
found type `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-71955.rs:58:24
error: implementation of `Parser` is not general enough
--> $DIR/issue-71955.rs:56:5
|
LL | foo(baz, "string", |s| s.0.len() == 5);
| ^^^^^^^^^^^^^^^^^^
note: the lifetime requirement is introduced here
--> $DIR/issue-71955.rs:34:44
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough
|
LL | F2: FnOnce(&<F1 as Parser>::Output) -> bool
| ^^^^
= note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
= note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0308`.
Original file line number Diff line number Diff line change
@@ -6,8 +6,6 @@
// Since we are testing nll (and migration) explicitly as a separate
// revisions, don't worry about the --compare-mode=nll on this test.

// ignore-compare-mode-nll

#![feature(rustc_attrs)]

trait Parser<'s> {
@@ -53,10 +51,10 @@ fn main() {

foo(bar, "string", |s| s.len() == 5);
//[migrate]~^ ERROR implementation of `Parser` is not general enough
//[nll]~^^ ERROR mismatched types
//[nll]~| ERROR mismatched types
//[nll]~^^ ERROR implementation of `Parser` is not general enough
//[nll]~| ERROR implementation of `Parser` is not general enough
foo(baz, "string", |s| s.0.len() == 5);
//[migrate]~^ ERROR implementation of `Parser` is not general enough
//[nll]~^^ ERROR mismatched types
//[nll]~| ERROR mismatched types
//[nll]~^^ ERROR implementation of `Parser` is not general enough
//[nll]~| ERROR implementation of `Parser` is not general enough
}
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y);
| - - ^^^^^^ assignment requires that `'1` must outlive `'2`
| | |
| | has type `&'1 i32`
| has type `&'_#2r mut &'2 i32`
| has type `&'2 mut &'_#3r i32`

note: no external requirements
--> $DIR/escape-argument-callee.rs:20:1
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ LL | let mut closure1 = || p = &y;
(&'_#1r mut &'_#2r i32, &'_#3r i32),
]
= note: number of external vids: 4
= note: where '_#3r: '_#1r
= note: where '_#3r: '_#2r

note: external requirements
@@ -28,6 +29,7 @@ LL | | };
(&'_#1r mut &'_#2r i32, &'_#3r i32),
]
= note: number of external vids: 4
= note: where '_#3r: '_#1r
= note: where '_#3r: '_#2r

note: no external requirements
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ LL | let mut closure = || p = &y;
(&'_#1r mut &'_#2r i32, &'_#3r i32),
]
= note: number of external vids: 4
= note: where '_#3r: '_#1r
= note: where '_#3r: '_#2r

note: no external requirements
Original file line number Diff line number Diff line change
@@ -18,6 +18,8 @@ LL | | });
= note: late-bound region is '_#4r
= note: number of external vids: 5
= note: where '_#1r: '_#2r
= note: where '_#1r: '_#2r
= note: where '_#1r: '_#2r

note: no external requirements
--> $DIR/propagate-approximated-ref.rs:42:1
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ LL | | });
= note: late-bound region is '_#3r
= note: number of external vids: 4
= note: where '_#1r: '_#0r
= note: where '_#1r: '_#0r

note: no external requirements
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:31:1
Original file line number Diff line number Diff line change
@@ -18,6 +18,9 @@ LL | | });
= note: late-bound region is '_#3r
= note: late-bound region is '_#4r
= note: number of external vids: 5
= note: where '_#1r: '_#2r
= note: where '_#1r: '_#2r
= note: where '_#1r: '_#0r
= note: where '_#1r: '_#0r

note: no external requirements
Original file line number Diff line number Diff line change
@@ -23,10 +23,14 @@ error: lifetime may not live long enough
LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
| --------- - has type `&'_#7r Cell<&'1 u32>`
| |
| has type `&'_#5r Cell<&'2 &'_#1r u32>`
| has type `&'2 Cell<&'_#6r &'_#1r u32>`
LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
|
= note: requirement occurs because of the type `Cell<&'_#38r u32>`, which makes the generic argument `&'_#38r u32` invariant
= note: the struct `Cell<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

note: no external requirements
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:34:1
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
// Only works if 'x: 'y:
demand_y(x, y, x.get())
//~^ ERROR
//~| ERROR
});
}

Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
note: no external requirements
note: external requirements
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:39:47
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
| _______________________________________________^
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get())
LL | |
LL | |
LL | | });
| |_____^
|
@@ -16,17 +17,25 @@ LL | | });
]
= note: late-bound region is '_#3r
= note: late-bound region is '_#4r
= note: number of external vids: 5
= note: where '_#1r: '_#2r
= note: where '_#1r: '_#2r
= note: where '_#1r: '_#2r

error: lifetime may not live long enough
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:41:9
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
| ---------- ---------- has type `&'_#8r Cell<&'2 &'_#2r u32>`
| ---------- ---------- has type `&'2 Cell<&'_#9r &'_#2r u32>`
| |
| has type `&'_#6r Cell<&'1 &'_#1r u32>`
LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
|
= note: requirement occurs because of the type `Cell<&'_#44r u32>`, which makes the generic argument `&'_#44r u32` invariant
= note: the struct `Cell<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

note: no external requirements
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:38:1
@@ -35,12 +44,25 @@ LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
LL | | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get())
LL | |
... |
LL | | });
LL | | }
| |_^
|
= note: defining type: supply

error: aborting due to previous error
error: lifetime may not live long enough
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:41:9
|
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
...
LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b`
|
= help: consider adding the following bound: `'a: 'b`

error: aborting due to 2 previous errors

3 changes: 1 addition & 2 deletions src/test/ui/nll/issue-95272.rs
Original file line number Diff line number Diff line change
@@ -10,8 +10,7 @@ where

fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) {
let f = check;
//~^ ERROR lifetime may not live long enough
f(x, y);
f(x, y); //~ ERROR lifetime may not live long enough
}

fn main() {}
9 changes: 5 additions & 4 deletions src/test/ui/nll/issue-95272.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
error: lifetime may not live long enough
--> $DIR/issue-95272.rs:12:13
--> $DIR/issue-95272.rs:13:5
|
LL | fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | let f = check;
| ^^^^^ assignment requires that `'a` must outlive `'b`
LL | f(x, y);
| ^^^^^^^ argument requires that `'a` must outlive `'b`
|
= help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a function pointer to `check`
= note: the function `check` is invariant over the parameter `'a`
= note: requirement occurs because of the type `Cell<&()>`, which makes the generic argument `&()` invariant
= note: the struct `Cell<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

error: aborting due to previous error
Original file line number Diff line number Diff line change
@@ -168,7 +168,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
]
= note: late-bound region is '_#3r
= note: number of external vids: 4
= note: where <T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(0, 'b)>>::AssocType: '_#2r
= note: where '_#1r: '_#2r

note: no external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:83:1
@@ -185,15 +185,15 @@ LL | | }
= note: defining type: two_regions::<'_#1r, T>

error: lifetime may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:87:29
--> $DIR/projection-two-region-trait-bound-closure.rs:87:39
|
LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
...
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
| ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`

@@ -209,7 +209,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
(),
]
= note: number of external vids: 4
= note: where <T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(1, 'b)>>::AssocType: '_#3r
= note: where '_#2r: '_#3r

note: no external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:92:1
@@ -237,7 +237,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
(),
]
= note: number of external vids: 3
= note: where <T as Anything<ReEarlyBound(0, 'a), ReEarlyBound(0, 'a)>>::AssocType: '_#2r
= note: where '_#1r: '_#2r

note: no external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:101:1
16 changes: 4 additions & 12 deletions src/test/ui/nll/type-check-pointer-coercions.stderr
Original file line number Diff line number Diff line change
@@ -22,21 +22,14 @@ LL | x
|
= help: consider adding the following bound: `'a: 'b`

error: lifetime may not live long enough
error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/type-check-pointer-coercions.rs:13:5
|
LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
| ------------ help: add explicit lifetime `'b` to the type of `x`: `&'b mut &'a i32`
LL | // Two errors because *mut is invariant
LL | x
| ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a mutable pointer to `&i32`
= note: mutable pointers are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
| ^ lifetime `'b` required

error: lifetime may not live long enough
--> $DIR/type-check-pointer-coercions.rs:13:5
@@ -54,8 +47,6 @@ LL | x
= note: mutable pointers are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

help: `'b` and `'a` must be the same: replace one with the other

error: lifetime may not live long enough
--> $DIR/type-check-pointer-coercions.rs:18:5
|
@@ -109,3 +100,4 @@ LL | y

error: aborting due to 8 previous errors

For more information about this error, try `rustc --explain E0621`.
2 changes: 1 addition & 1 deletion src/test/ui/nll/type-check-pointer-comparisons.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@

fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
x == y;
//~^ ERROR lifetime may not live long enough
//~^ ERROR explicit lifetime required in the type of `y`
//~| ERROR lifetime may not live long enough
}

16 changes: 4 additions & 12 deletions src/test/ui/nll/type-check-pointer-comparisons.stderr
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
error: lifetime may not live long enough
error[E0621]: explicit lifetime required in the type of `y`
--> $DIR/type-check-pointer-comparisons.rs:6:5
|
LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
| ------------------- help: add explicit lifetime `'a` to the type of `y`: `*const &'a mut &'b i32`
LL | x == y;
| ^ requires that `'a` must outlive `'b`
|
= help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a mutable reference to `&i32`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
| ^ lifetime `'a` required

error: lifetime may not live long enough
--> $DIR/type-check-pointer-comparisons.rs:6:10
@@ -28,8 +21,6 @@ LL | x == y;
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

help: `'a` and `'b` must be the same: replace one with the other

error: lifetime may not live long enough
--> $DIR/type-check-pointer-comparisons.rs:12:5
|
@@ -96,3 +87,4 @@ help: `'a` and `'b` must be the same: replace one with the other

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0621`.
Original file line number Diff line number Diff line change
@@ -4,9 +4,13 @@ error: lifetime may not live long enough
LL | doit(0, &|x, y| {
| - - has type `&'1 i32`
| |
| has type `&Cell<&'2 i32>`
| has type `&'2 Cell<&i32>`
LL | x.set(y);
| ^^^^^^^^ argument requires that `'1` must outlive `'2`
|
= note: requirement occurs because of the type `Cell<&i32>`, which makes the generic argument `&i32` invariant
= note: the struct `Cell<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

error: aborting due to previous error

Original file line number Diff line number Diff line change
@@ -2,10 +2,14 @@ error: lifetime may not live long enough
--> $DIR/underscore-lifetime-elison-mismatch.rs:5:42
|
LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); }
| - - ^^^^^^^^^ argument requires that `'1` must outlive `'2`
| | |
| | let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
| - - ^^^^^^^^^ argument requires that `'1` must outlive `'2`
| | |
| | let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
|
= note: requirement occurs because of a mutable reference to `Vec<&u8>`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

error: aborting due to previous error