mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Rollup merge of #97206 - jackh726:issue-73154, r=nikomatsakis
Do leak check after function pointer coercion cc #73154 I still need to clean diagnostics just a tad, but figured I would put this up anyways. This change is made in order to make match arm coercion order-independent. Basically, any time we do function pointer coercion, we follow it by doing a leak check. This is necessary because the LUB code doesn't handler higher-ranked things correctly, leading us to "coerce", but use the wrong type. A proper fix is to actually fix that code (so the type returned by `unify_and` is a supertype of both `a` and `b` if `Ok`). However, that requires a more in-depth fix, likely heavily overlapping with the new subtyping changes. Here, I've been conservative and error early if we generate unsatisfiable constraints. Note, this should *mostly* only affect NLL, since migrate mode falls back to the LUB implementation (followed by leak check), whereas NLL only does sub. There could be other coercion code that has an order-dependence where a leak check in the coercion code might be useful. However, this is more of a spot-fix for #73154 than a "permanent" fix, since we likely want to go the other way long-term, and allow this pattern without error. r? `@nikomatsakis`
This commit is contained in:
commit
4f97de8dc5
@ -1442,6 +1442,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
/// the message in `secondary_span` as the primary label, and apply the message that would
|
||||
/// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on
|
||||
/// E0271, like `src/test/ui/issues/issue-39970.stderr`.
|
||||
#[tracing::instrument(
|
||||
level = "debug",
|
||||
skip(self, diag, secondary_span, swap_secondary_and_primary, force_label)
|
||||
)]
|
||||
pub fn note_type_err(
|
||||
&self,
|
||||
diag: &mut Diagnostic,
|
||||
@ -1453,7 +1457,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
force_label: bool,
|
||||
) {
|
||||
let span = cause.span(self.tcx);
|
||||
debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr);
|
||||
|
||||
// For some types of errors, expected-found does not make
|
||||
// sense, so just ignore the values we were given.
|
||||
@ -1621,9 +1624,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
// Ignore msg for object safe coercion
|
||||
// since E0038 message will be printed
|
||||
match terr {
|
||||
// Ignore msg for object safe coercion
|
||||
// since E0038 message will be printed
|
||||
TypeError::ObjectUnsafeCoercion(_) => {}
|
||||
_ => {
|
||||
let mut label_or_note = |span: Span, msg: &str| {
|
||||
@ -1774,6 +1777,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
// It reads better to have the error origin as the final
|
||||
// thing.
|
||||
self.note_error_origin(diag, cause, exp_found, terr);
|
||||
|
||||
debug!(?diag);
|
||||
}
|
||||
|
||||
fn suggest_tuple_pattern(
|
||||
|
@ -135,11 +135,10 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
||||
ArgCount => write!(f, "incorrect number of function parameters"),
|
||||
FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field),
|
||||
RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
|
||||
RegionsInsufficientlyPolymorphic(br, _) => write!(
|
||||
f,
|
||||
"expected bound lifetime parameter{}, found concrete lifetime",
|
||||
br_string(br)
|
||||
),
|
||||
// Actually naming the region here is a bit confusing because context is lacking
|
||||
RegionsInsufficientlyPolymorphic(..) => {
|
||||
write!(f, "one type is more general than the other")
|
||||
}
|
||||
RegionsOverlyPolymorphic(br, _) => write!(
|
||||
f,
|
||||
"expected concrete lifetime, found bound lifetime parameter{}",
|
||||
|
@ -151,6 +151,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
///
|
||||
/// * From each pre-binding block to the next pre-binding block.
|
||||
/// * From each otherwise block to the next pre-binding block.
|
||||
#[tracing::instrument(level = "debug", skip(self, arms))]
|
||||
pub(crate) fn match_expr(
|
||||
&mut self,
|
||||
destination: Place<'tcx>,
|
||||
|
@ -75,6 +75,7 @@ impl<'tcx> Cx<'tcx> {
|
||||
};
|
||||
|
||||
let mut pattern = self.pattern_from_hir(local.pat);
|
||||
debug!(?pattern);
|
||||
|
||||
if let Some(ty) = &local.ty {
|
||||
if let Some(&user_ty) =
|
||||
|
@ -98,6 +98,7 @@ impl<'tcx> Cx<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
|
||||
let p = match self.tcx.hir().get(p.hir_id) {
|
||||
Node::Pat(p) | Node::Binding(p) => p,
|
||||
|
@ -56,6 +56,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let mut all_arms_diverge = Diverges::WarnedAlways;
|
||||
|
||||
let expected = orig_expected.adjust_for_branches(self);
|
||||
debug!(?expected);
|
||||
|
||||
let mut coercion = {
|
||||
let coerce_first = match expected {
|
||||
@ -127,6 +128,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Some(&arm.body),
|
||||
arm_ty,
|
||||
Some(&mut |err: &mut Diagnostic| {
|
||||
let Some(ret) = self.ret_type_span else {
|
||||
return;
|
||||
};
|
||||
let Expectation::IsLast(stmt) = orig_expected else {
|
||||
return
|
||||
};
|
||||
let can_coerce_to_return_ty = match self.ret_coercion.as_ref() {
|
||||
Some(ret_coercion) if self.in_tail_expr => {
|
||||
let ret_ty = ret_coercion.borrow().expected_ty();
|
||||
@ -138,38 +145,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if let (Expectation::IsLast(stmt), Some(ret), true) =
|
||||
(orig_expected, self.ret_type_span, can_coerce_to_return_ty)
|
||||
{
|
||||
let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi());
|
||||
let mut ret_span: MultiSpan = semi_span.into();
|
||||
ret_span.push_span_label(
|
||||
expr.span,
|
||||
"this could be implicitly returned but it is a statement, not a \
|
||||
tail expression"
|
||||
.to_owned(),
|
||||
);
|
||||
ret_span.push_span_label(
|
||||
ret,
|
||||
"the `match` arms can conform to this return type".to_owned(),
|
||||
);
|
||||
ret_span.push_span_label(
|
||||
semi_span,
|
||||
"the `match` is a statement because of this semicolon, consider \
|
||||
removing it"
|
||||
.to_owned(),
|
||||
);
|
||||
err.span_note(
|
||||
ret_span,
|
||||
"you might have meant to return the `match` expression",
|
||||
);
|
||||
err.tool_only_span_suggestion(
|
||||
semi_span,
|
||||
"remove this semicolon",
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
if !can_coerce_to_return_ty {
|
||||
return;
|
||||
}
|
||||
|
||||
let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi());
|
||||
let mut ret_span: MultiSpan = semi_span.into();
|
||||
ret_span.push_span_label(
|
||||
expr.span,
|
||||
"this could be implicitly returned but it is a statement, not a \
|
||||
tail expression"
|
||||
.to_owned(),
|
||||
);
|
||||
ret_span.push_span_label(
|
||||
ret,
|
||||
"the `match` arms can conform to this return type".to_owned(),
|
||||
);
|
||||
ret_span.push_span_label(
|
||||
semi_span,
|
||||
"the `match` is a statement because of this semicolon, consider \
|
||||
removing it"
|
||||
.to_owned(),
|
||||
);
|
||||
err.span_note(
|
||||
ret_span,
|
||||
"you might have meant to return the `match` expression",
|
||||
);
|
||||
err.tool_only_span_suggestion(
|
||||
semi_span,
|
||||
"remove this semicolon",
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}),
|
||||
false,
|
||||
);
|
||||
@ -199,7 +206,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// We won't diverge unless the scrutinee or all arms diverge.
|
||||
self.diverges.set(scrut_diverges | all_arms_diverge);
|
||||
|
||||
coercion.complete(self)
|
||||
let match_ty = coercion.complete(self);
|
||||
debug!(?match_ty);
|
||||
match_ty
|
||||
}
|
||||
|
||||
fn get_appropriate_arm_semicolon_removal_span(
|
||||
|
@ -737,14 +737,27 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
F: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
|
||||
G: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
|
||||
{
|
||||
if let ty::FnPtr(fn_ty_b) = b.kind()
|
||||
&& let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) =
|
||||
(fn_ty_a.unsafety(), fn_ty_b.unsafety())
|
||||
{
|
||||
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
|
||||
return self.unify_and(unsafe_a, b, to_unsafe);
|
||||
}
|
||||
self.unify_and(a, b, normal)
|
||||
self.commit_unconditionally(|snapshot| {
|
||||
let result = if let ty::FnPtr(fn_ty_b) = b.kind()
|
||||
&& let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) =
|
||||
(fn_ty_a.unsafety(), fn_ty_b.unsafety())
|
||||
{
|
||||
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
|
||||
self.unify_and(unsafe_a, b, to_unsafe)
|
||||
} else {
|
||||
self.unify_and(a, b, normal)
|
||||
};
|
||||
|
||||
// FIXME(#73154): This is a hack. Currently LUB can generate
|
||||
// unsolvable constraints. Additionally, it returns `a`
|
||||
// unconditionally, even when the "LUB" is `b`. In the future, we
|
||||
// want the coerced type to be the actual supertype of these two,
|
||||
// but for now, we want to just error to ensure we don't lock
|
||||
// ourselves into a specific behavior with NLL.
|
||||
self.leak_check(false, snapshot)?;
|
||||
|
||||
result
|
||||
})
|
||||
}
|
||||
|
||||
fn coerce_from_fn_pointer(
|
||||
@ -1133,8 +1146,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let (adjustments, target) = self.register_infer_ok_obligations(ok);
|
||||
self.apply_adjustments(new, adjustments);
|
||||
debug!(
|
||||
"coercion::try_find_coercion_lub: was able to coerce from previous type {:?} to new type {:?}",
|
||||
prev_ty, new_ty,
|
||||
"coercion::try_find_coercion_lub: was able to coerce from new type {:?} to previous type {:?} ({:?})",
|
||||
new_ty, prev_ty, target
|
||||
);
|
||||
return Ok(target);
|
||||
}
|
||||
@ -1190,15 +1203,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
Ok(ok) => {
|
||||
debug!(
|
||||
"coercion::try_find_coercion_lub: was able to coerce previous type {:?} to new type {:?}",
|
||||
prev_ty, new_ty,
|
||||
);
|
||||
let (adjustments, target) = self.register_infer_ok_obligations(ok);
|
||||
for expr in exprs {
|
||||
let expr = expr.as_coercion_site();
|
||||
self.apply_adjustments(expr, adjustments.clone());
|
||||
}
|
||||
debug!(
|
||||
"coercion::try_find_coercion_lub: was able to coerce previous type {:?} to new type {:?} ({:?})",
|
||||
prev_ty, new_ty, target
|
||||
);
|
||||
Ok(target)
|
||||
}
|
||||
}
|
||||
@ -1430,6 +1443,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
})
|
||||
};
|
||||
|
||||
debug!(?result);
|
||||
match result {
|
||||
Ok(v) => {
|
||||
self.final_ty = Some(v);
|
||||
@ -1520,7 +1534,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
augment_error(&mut err);
|
||||
}
|
||||
|
||||
if let Some(expr) = expression {
|
||||
let is_insufficiently_polymorphic =
|
||||
matches!(coercion_error, TypeError::RegionsInsufficientlyPolymorphic(..));
|
||||
|
||||
if !is_insufficiently_polymorphic && let Some(expr) = expression {
|
||||
fcx.emit_coerce_suggestions(
|
||||
&mut err,
|
||||
expr,
|
||||
|
@ -129,6 +129,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
///
|
||||
/// N.B., this code relies on `self.diverges` to be accurate. In particular, assignments to `!`
|
||||
/// will be permitted if the diverges flag is currently "always".
|
||||
#[tracing::instrument(level = "debug", skip(self, expr, expected_ty_expr, allow_two_phase))]
|
||||
pub fn demand_coerce_diag(
|
||||
&self,
|
||||
expr: &hir::Expr<'tcx>,
|
||||
@ -150,7 +151,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let expr_ty = self.resolve_vars_with_obligations(checked_ty);
|
||||
let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone());
|
||||
|
||||
self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
|
||||
let is_insufficiently_polymorphic =
|
||||
matches!(e, TypeError::RegionsInsufficientlyPolymorphic(..));
|
||||
|
||||
// FIXME(#73154): For now, we do leak check when coercing function
|
||||
// pointers in typeck, instead of only during borrowck. This can lead
|
||||
// to these `RegionsInsufficientlyPolymorphic` errors that aren't helpful.
|
||||
if !is_insufficiently_polymorphic {
|
||||
self.emit_coerce_suggestions(
|
||||
&mut err,
|
||||
expr,
|
||||
expr_ty,
|
||||
expected,
|
||||
expected_ty_expr,
|
||||
Some(e),
|
||||
);
|
||||
}
|
||||
|
||||
(expected, Some(err))
|
||||
}
|
||||
|
@ -1,37 +1,12 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/placeholder-pattern-fail.rs:9:12
|
||||
--> $DIR/placeholder-pattern-fail.rs:9:47
|
||||
|
|
||||
LL | let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
| ^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b> fn(Inv<'a>, Inv<'b>)`
|
||||
found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/placeholder-pattern-fail.rs:9:12
|
||||
|
|
||||
LL | let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b> fn(Inv<'a>, Inv<'b>)`
|
||||
found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/placeholder-pattern-fail.rs:14:13
|
||||
|
|
||||
LL | fn simple1<'c>(x: (&'c i32,)) {
|
||||
| -- lifetime `'c` defined here
|
||||
LL | let _x: (&'static i32,) = x;
|
||||
| ^^^^^^^^^^^^^^^ type annotation requires that `'c` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/placeholder-pattern-fail.rs:19:12
|
||||
|
|
||||
LL | fn simple2<'c>(x: (&'c i32,)) {
|
||||
| -- lifetime `'c` defined here
|
||||
LL | let _: (&'static i32,) = x;
|
||||
| ^^^^^^^^^^^^^^^ type annotation requires that `'c` must outlive `'static`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/hrtb-exists-forall-fn.rs:17:12
|
||||
--> $DIR/hrtb-exists-forall-fn.rs:17:34
|
||||
|
|
||||
LL | let _: for<'b> fn(&'b u32) = foo();
|
||||
| ^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
| ^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'b> fn(&'b u32)`
|
||||
found fn pointer `fn(&u32)`
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/old-lub-glb-hr-noteq1.rs:11:14
|
||||
--> $DIR/old-lub-glb-hr-noteq1.rs:17:14
|
||||
|
|
||||
LL | let z = match 22 {
|
||||
| _____________-
|
||||
@ -7,6 +7,9 @@ LL | | 0 => x,
|
||||
| | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
||||
LL | | _ => y,
|
||||
| | ^ one type is more general than the other
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
21
src/test/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr
Normal file
21
src/test/ui/lub-glb/old-lub-glb-hr-noteq1.basenoleak.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/old-lub-glb-hr-noteq1.rs:17:14
|
||||
|
|
||||
LL | let z = match 22 {
|
||||
| _____________-
|
||||
LL | | 0 => x,
|
||||
| | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
||||
LL | | _ => y,
|
||||
| | ^ one type is more general than the other
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
||||
found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
21
src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr
Normal file
21
src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/old-lub-glb-hr-noteq1.rs:17:14
|
||||
|
|
||||
LL | let z = match 22 {
|
||||
| _____________-
|
||||
LL | | 0 => x,
|
||||
| | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
||||
LL | | _ => y,
|
||||
| | ^ one type is more general than the other
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
||||
found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -1,5 +1,5 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/old-lub-glb-hr-noteq1.rs:11:14
|
||||
--> $DIR/old-lub-glb-hr-noteq1.rs:17:14
|
||||
|
|
||||
LL | _ => y,
|
||||
| ^ one type is more general than the other
|
@ -2,13 +2,23 @@
|
||||
// general than the other. Test the case where the more general type (`x`) is the first
|
||||
// match arm specifically.
|
||||
|
||||
// revisions: baseleak basenoleak nllleak nllnoleak
|
||||
// ignore-compare-mode-nll
|
||||
//[nllleak] compile-flags: -Zborrowck=mir
|
||||
//[nllnoleak] compile-flags: -Zborrowck=mir -Zno-leak-check
|
||||
//[basenoleak] compile-flags:-Zno-leak-check
|
||||
|
||||
fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
|
||||
// The two types above are not equivalent. With the older LUB/GLB
|
||||
// algorithm, this may have worked (I don't remember), but now it
|
||||
// doesn't because we require equality.
|
||||
let z = match 22 {
|
||||
0 => x,
|
||||
_ => y, //~ ERROR `match` arms have incompatible types
|
||||
_ => y,
|
||||
//[baseleak]~^ ERROR `match` arms have incompatible types
|
||||
//[nllleak]~^^ ERROR `match` arms have incompatible types
|
||||
//[basenoleak]~^^^ ERROR `match` arms have incompatible types
|
||||
//[nllnoleak]~^^^^ ERROR mismatched types
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/old-lub-glb-hr-noteq2.rs:21:14
|
||||
--> $DIR/old-lub-glb-hr-noteq2.rs:28:14
|
||||
|
|
||||
LL | let z = match 22 {
|
||||
| _____________-
|
||||
@ -7,6 +7,9 @@ LL | | 0 => y,
|
||||
| | - this is found to be of type `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
|
||||
LL | | _ => x,
|
||||
| | ^ one type is more general than the other
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
21
src/test/ui/lub-glb/old-lub-glb-hr-noteq2.basenoleak.stderr
Normal file
21
src/test/ui/lub-glb/old-lub-glb-hr-noteq2.basenoleak.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/old-lub-glb-hr-noteq2.rs:28:14
|
||||
|
|
||||
LL | let z = match 22 {
|
||||
| _____________-
|
||||
LL | | 0 => y,
|
||||
| | - this is found to be of type `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
|
||||
LL | | _ => x,
|
||||
| | ^ one type is more general than the other
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
= note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
|
||||
found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
21
src/test/ui/lub-glb/old-lub-glb-hr-noteq2.nllleak.stderr
Normal file
21
src/test/ui/lub-glb/old-lub-glb-hr-noteq2.nllleak.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/old-lub-glb-hr-noteq2.rs:28:14
|
||||
|
|
||||
LL | let z = match 22 {
|
||||
| _____________-
|
||||
LL | | 0 => y,
|
||||
| | - this is found to be of type `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
|
||||
LL | | _ => x,
|
||||
| | ^ one type is more general than the other
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
= note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
|
||||
found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -2,15 +2,22 @@
|
||||
// one is more general than the other. Test the case where the more general type
|
||||
// (`x`) is the second match arm specifically.
|
||||
//
|
||||
// FIXME(#73154) Skip for compare-mode because the pure NLL checker accepts this
|
||||
// test. (Note that it still errors in old-lub-glb-hr-noteq1.rs). What happens
|
||||
// FIXME(#73154) Pure NLL checker without leak check accepts this test.
|
||||
// (Note that it still errors in old-lub-glb-hr-noteq1.rs). What happens
|
||||
// is that, due to the ordering of the match arms, we pick the correct "more
|
||||
// general" fn type, and we ignore the errors from the non-NLL type checker that
|
||||
// requires equality. The NLL type checker only requires a subtyping
|
||||
// relationship, and that holds.
|
||||
//
|
||||
// relationship, and that holds. To unblock landing NLL - and ensure that we can
|
||||
// choose to make this always in error in the future - we perform the leak check
|
||||
// after coercing a function pointer.
|
||||
|
||||
// revisions: baseleak basenoleak nllleak nllnoleak
|
||||
// ignore-compare-mode-nll
|
||||
// ignore-compare-mode-polonius
|
||||
//[nllleak] compile-flags: -Zborrowck=mir
|
||||
//[nllnoleak] compile-flags: -Zborrowck=mir -Zno-leak-check
|
||||
//[basenoleak] compile-flags:-Zno-leak-check
|
||||
|
||||
//[nllnoleak] check-pass
|
||||
|
||||
fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
|
||||
// The two types above are not equivalent. With the older LUB/GLB
|
||||
@ -18,7 +25,10 @@ fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8
|
||||
// doesn't because we require equality.
|
||||
let z = match 22 {
|
||||
0 => y,
|
||||
_ => x, //~ ERROR `match` arms have incompatible types
|
||||
_ => x,
|
||||
//[baseleak]~^ ERROR `match` arms have incompatible types
|
||||
//[nllleak]~^^ ERROR `match` arms have incompatible types
|
||||
//[basenoleak]~^^^ ERROR `match` arms have incompatible types
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ LL | *x = *y;
|
||||
| ^^ ...but data from `y` flows into `x` here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:7
|
||||
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:19:7
|
||||
|
|
||||
LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
| --------- --------- these two types are declared with different lifetimes...
|
||||
@ -17,13 +17,13 @@ LL | a(x, y);
|
||||
| ^ ...but data from `y` flows into `x` here
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:28:43
|
||||
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:26:43
|
||||
|
|
||||
LL | let _: fn(&mut &isize, &mut &isize) = a;
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
|
||||
found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)`
|
||||
found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -1,50 +1,12 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:12:5
|
||||
|
|
||||
LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | // Illegal now because there is no `'b:'a` declaration.
|
||||
LL | *x = *y;
|
||||
| ^^^^^^^ assignment requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:5
|
||||
|
|
||||
LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | a(x, y);
|
||||
| ^^^^^^^ argument requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
= note: requirement occurs because of a mutable reference to `&isize`
|
||||
= 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[E0308]: mismatched types
|
||||
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:28:12
|
||||
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:26:43
|
||||
|
|
||||
LL | let _: fn(&mut &isize, &mut &isize) = a;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
|
||||
found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)`
|
||||
found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:28:12
|
||||
|
|
||||
LL | let _: fn(&mut &isize, &mut &isize) = a;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
|
||||
found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -11,7 +11,6 @@ fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
// Illegal now because there is no `'b:'a` declaration.
|
||||
*x = *y;
|
||||
//[base]~^ ERROR E0623
|
||||
//[nll]~^^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
@ -19,7 +18,6 @@ fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
// related as required.
|
||||
a(x, y);
|
||||
//[base]~^ ERROR lifetime mismatch [E0623]
|
||||
//[nll]~^^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn d() {
|
||||
@ -27,7 +25,6 @@ fn d() {
|
||||
// inconstraints:
|
||||
let _: fn(&mut &isize, &mut &isize) = a;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
//[nll]~^^ ERROR mismatched types [E0308]
|
||||
}
|
||||
|
||||
fn e() {
|
||||
|
@ -8,7 +8,7 @@ LL | *x = *y;
|
||||
| ^^ ...but data from `y` flows into `x` here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:10
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:15:10
|
||||
|
|
||||
LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
|
||||
| --------- ---------
|
||||
@ -19,7 +19,7 @@ LL | *z = *y;
|
||||
| ^^ ...but data from `y` flows into `z` here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:7
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:21:7
|
||||
|
|
||||
LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
|
||||
| --------- --------- these two types are declared with different lifetimes...
|
||||
@ -28,13 +28,13 @@ LL | a(x, y, z);
|
||||
| ^ ...but data from `y` flows into `x` here
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:30:56
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:28:56
|
||||
|
|
||||
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)`
|
||||
found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)`
|
||||
found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -1,59 +1,12 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:13:5
|
||||
|
|
||||
LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | // Illegal now because there is no `'b:'a` declaration.
|
||||
LL | *x = *y;
|
||||
| ^^^^^^^ assignment requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:5
|
||||
|
|
||||
LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | a(x, y, z);
|
||||
| ^^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
= note: requirement occurs because of a mutable reference to `&isize`
|
||||
= 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[E0308]: mismatched types
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:30:12
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:28:56
|
||||
|
|
||||
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)`
|
||||
found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)`
|
||||
found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:30:12
|
||||
|
|
||||
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)`
|
||||
found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:30:12
|
||||
|
|
||||
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)`
|
||||
found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -12,7 +12,6 @@ fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
|
||||
// Illegal now because there is no `'b:'a` declaration.
|
||||
*x = *y;
|
||||
//[base]~^ ERROR E0623
|
||||
//[nll]~^^ ERROR lifetime may not live long enough
|
||||
*z = *y; //[base]~ ERROR E0623
|
||||
}
|
||||
|
||||
@ -21,7 +20,6 @@ fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) {
|
||||
// related as required.
|
||||
a(x, y, z);
|
||||
//[base]~^ ERROR lifetime mismatch [E0623]
|
||||
//[nll]~^^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn d() {
|
||||
@ -29,8 +27,6 @@ fn d() {
|
||||
// inconstraints:
|
||||
let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
|
||||
//~^ ERROR E0308
|
||||
//[nll]~^^ ERROR mismatched types [E0308]
|
||||
//[nll]~| ERROR mismatched types [E0308]
|
||||
}
|
||||
|
||||
fn e() {
|
||||
|
@ -2,10 +2,17 @@ error[E0308]: mismatched types
|
||||
--> $DIR/regions-fn-subtyping-return-static-fail.rs:52:12
|
||||
|
|
||||
LL | want_G(baz);
|
||||
| ^^^ one type is more general than the other
|
||||
| ------ ^^^ one type is more general than the other
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S`
|
||||
found fn pointer `for<'r> fn(&'r S) -> &'r S`
|
||||
found fn item `for<'r> fn(&'r S) -> &'r S {baz}`
|
||||
note: function defined here
|
||||
--> $DIR/regions-fn-subtyping-return-static-fail.rs:24:4
|
||||
|
|
||||
LL | fn want_G(f: G) {}
|
||||
| ^^^^^^ ----
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,11 +1,18 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/regions-fn-subtyping-return-static-fail.rs:52:5
|
||||
--> $DIR/regions-fn-subtyping-return-static-fail.rs:52:12
|
||||
|
|
||||
LL | want_G(baz);
|
||||
| ^^^^^^^^^^^ one type is more general than the other
|
||||
| ------ ^^^ one type is more general than the other
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S`
|
||||
found fn pointer `for<'r> fn(&'r S) -> &'r S`
|
||||
found fn item `for<'r> fn(&'r S) -> &'r S {baz}`
|
||||
note: function defined here
|
||||
--> $DIR/regions-fn-subtyping-return-static-fail.rs:24:4
|
||||
|
|
||||
LL | fn want_G(f: G) {}
|
||||
| ^^^^^^ ----
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,7 +8,7 @@ LL | *x = *y;
|
||||
| ^^ ...but data from `y` flows into `x` here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/regions-lifetime-bounds-on-fns.rs:20:7
|
||||
--> $DIR/regions-lifetime-bounds-on-fns.rs:19:7
|
||||
|
|
||||
LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
| --------- --------- these two types are declared with different lifetimes...
|
||||
@ -17,13 +17,13 @@ LL | a(x, y);
|
||||
| ^ ...but data from `y` flows into `x` here
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/regions-lifetime-bounds-on-fns.rs:28:43
|
||||
--> $DIR/regions-lifetime-bounds-on-fns.rs:26:43
|
||||
|
|
||||
LL | let _: fn(&mut &isize, &mut &isize) = a;
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
|
||||
found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)`
|
||||
found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -1,50 +1,12 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/regions-lifetime-bounds-on-fns.rs:12:5
|
||||
|
|
||||
LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | // Illegal now because there is no `'b:'a` declaration.
|
||||
LL | *x = *y;
|
||||
| ^^^^^^^ assignment requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/regions-lifetime-bounds-on-fns.rs:20:5
|
||||
|
|
||||
LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | a(x, y);
|
||||
| ^^^^^^^ argument requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
= note: requirement occurs because of a mutable reference to `&isize`
|
||||
= 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[E0308]: mismatched types
|
||||
--> $DIR/regions-lifetime-bounds-on-fns.rs:28:12
|
||||
--> $DIR/regions-lifetime-bounds-on-fns.rs:26:43
|
||||
|
|
||||
LL | let _: fn(&mut &isize, &mut &isize) = a;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
| ^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
|
||||
found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)`
|
||||
found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/regions-lifetime-bounds-on-fns.rs:28:12
|
||||
|
|
||||
LL | let _: fn(&mut &isize, &mut &isize) = a;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
|
||||
found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -11,7 +11,6 @@ fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
// Illegal now because there is no `'b:'a` declaration.
|
||||
*x = *y;
|
||||
//[base]~^ ERROR lifetime mismatch [E0623]
|
||||
//[nll]~^^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
@ -19,7 +18,6 @@ fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||
// related as required.
|
||||
a(x, y);
|
||||
//[base]~^ ERROR lifetime mismatch [E0623]
|
||||
//[nll]~^^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn d() {
|
||||
@ -27,7 +25,6 @@ fn d() {
|
||||
// inconstraints:
|
||||
let _: fn(&mut &isize, &mut &isize) = a;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
//[nll]~^^ ERROR mismatched types [E0308]
|
||||
}
|
||||
|
||||
fn e() {
|
||||
|
Loading…
Reference in New Issue
Block a user