Do leak check after function ptr coercion
This commit is contained in:
parent
4bb4dc4672
commit
683a9c8391
30 changed files with 271 additions and 256 deletions
|
@ -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
|
/// 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
|
/// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on
|
||||||
/// E0271, like `src/test/ui/issues/issue-39970.stderr`.
|
/// 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(
|
pub fn note_type_err(
|
||||||
&self,
|
&self,
|
||||||
diag: &mut Diagnostic,
|
diag: &mut Diagnostic,
|
||||||
|
@ -1453,7 +1457,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
force_label: bool,
|
force_label: bool,
|
||||||
) {
|
) {
|
||||||
let span = cause.span(self.tcx);
|
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
|
// For some types of errors, expected-found does not make
|
||||||
// sense, so just ignore the values we were given.
|
// 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 {
|
match terr {
|
||||||
|
// Ignore msg for object safe coercion
|
||||||
|
// since E0038 message will be printed
|
||||||
TypeError::ObjectUnsafeCoercion(_) => {}
|
TypeError::ObjectUnsafeCoercion(_) => {}
|
||||||
_ => {
|
_ => {
|
||||||
let mut label_or_note = |span: Span, msg: &str| {
|
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
|
// It reads better to have the error origin as the final
|
||||||
// thing.
|
// thing.
|
||||||
self.note_error_origin(diag, cause, exp_found, terr);
|
self.note_error_origin(diag, cause, exp_found, terr);
|
||||||
|
|
||||||
|
debug!(?diag);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suggest_tuple_pattern(
|
fn suggest_tuple_pattern(
|
||||||
|
|
|
@ -135,11 +135,10 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
||||||
ArgCount => write!(f, "incorrect number of function parameters"),
|
ArgCount => write!(f, "incorrect number of function parameters"),
|
||||||
FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field),
|
FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field),
|
||||||
RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
|
RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
|
||||||
RegionsInsufficientlyPolymorphic(br, _) => write!(
|
// Actually naming the region here is a bit confusing because context is lacking
|
||||||
f,
|
RegionsInsufficientlyPolymorphic(..) => {
|
||||||
"expected bound lifetime parameter{}, found concrete lifetime",
|
write!(f, "one type is more general than the other")
|
||||||
br_string(br)
|
}
|
||||||
),
|
|
||||||
RegionsOverlyPolymorphic(br, _) => write!(
|
RegionsOverlyPolymorphic(br, _) => write!(
|
||||||
f,
|
f,
|
||||||
"expected concrete lifetime, found bound lifetime parameter{}",
|
"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 pre-binding block to the next pre-binding block.
|
||||||
/// * From each otherwise 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(
|
pub(crate) fn match_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
destination: Place<'tcx>,
|
destination: Place<'tcx>,
|
||||||
|
|
|
@ -75,6 +75,7 @@ impl<'tcx> Cx<'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut pattern = self.pattern_from_hir(local.pat);
|
let mut pattern = self.pattern_from_hir(local.pat);
|
||||||
|
debug!(?pattern);
|
||||||
|
|
||||||
if let Some(ty) = &local.ty {
|
if let Some(ty) = &local.ty {
|
||||||
if let Some(&user_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> {
|
pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
|
||||||
let p = match self.tcx.hir().get(p.hir_id) {
|
let p = match self.tcx.hir().get(p.hir_id) {
|
||||||
Node::Pat(p) | Node::Binding(p) => p,
|
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 mut all_arms_diverge = Diverges::WarnedAlways;
|
||||||
|
|
||||||
let expected = orig_expected.adjust_for_branches(self);
|
let expected = orig_expected.adjust_for_branches(self);
|
||||||
|
debug!(?expected);
|
||||||
|
|
||||||
let mut coercion = {
|
let mut coercion = {
|
||||||
let coerce_first = match expected {
|
let coerce_first = match expected {
|
||||||
|
@ -127,6 +128,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
Some(&arm.body),
|
Some(&arm.body),
|
||||||
arm_ty,
|
arm_ty,
|
||||||
Some(&mut |err: &mut Diagnostic| {
|
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() {
|
let can_coerce_to_return_ty = match self.ret_coercion.as_ref() {
|
||||||
Some(ret_coercion) if self.in_tail_expr => {
|
Some(ret_coercion) if self.in_tail_expr => {
|
||||||
let ret_ty = ret_coercion.borrow().expected_ty();
|
let ret_ty = ret_coercion.borrow().expected_ty();
|
||||||
|
@ -138,38 +145,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if let (Expectation::IsLast(stmt), Some(ret), true) =
|
if !can_coerce_to_return_ty {
|
||||||
(orig_expected, self.ret_type_span, 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,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
false,
|
||||||
);
|
);
|
||||||
|
@ -199,7 +206,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// We won't diverge unless the scrutinee or all arms diverge.
|
// We won't diverge unless the scrutinee or all arms diverge.
|
||||||
self.diverges.set(scrut_diverges | 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(
|
fn get_appropriate_arm_semicolon_removal_span(
|
||||||
|
|
|
@ -737,14 +737,27 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
F: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
|
F: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
|
||||||
G: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
|
G: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
|
||||||
{
|
{
|
||||||
if let ty::FnPtr(fn_ty_b) = b.kind()
|
self.commit_unconditionally(|snapshot| {
|
||||||
&& let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) =
|
let result = if let ty::FnPtr(fn_ty_b) = b.kind()
|
||||||
(fn_ty_a.unsafety(), fn_ty_b.unsafety())
|
&& 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);
|
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
|
||||||
}
|
self.unify_and(unsafe_a, b, to_unsafe)
|
||||||
self.unify_and(a, b, normal)
|
} 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(
|
fn coerce_from_fn_pointer(
|
||||||
|
@ -1133,8 +1146,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let (adjustments, target) = self.register_infer_ok_obligations(ok);
|
let (adjustments, target) = self.register_infer_ok_obligations(ok);
|
||||||
self.apply_adjustments(new, adjustments);
|
self.apply_adjustments(new, adjustments);
|
||||||
debug!(
|
debug!(
|
||||||
"coercion::try_find_coercion_lub: was able to coerce from previous type {:?} to new type {:?}",
|
"coercion::try_find_coercion_lub: was able to coerce from new type {:?} to previous type {:?} ({:?})",
|
||||||
prev_ty, new_ty,
|
new_ty, prev_ty, target
|
||||||
);
|
);
|
||||||
return Ok(target);
|
return Ok(target);
|
||||||
}
|
}
|
||||||
|
@ -1190,15 +1203,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(ok) => {
|
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);
|
let (adjustments, target) = self.register_infer_ok_obligations(ok);
|
||||||
for expr in exprs {
|
for expr in exprs {
|
||||||
let expr = expr.as_coercion_site();
|
let expr = expr.as_coercion_site();
|
||||||
self.apply_adjustments(expr, adjustments.clone());
|
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)
|
Ok(target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1430,6 +1443,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
debug!(?result);
|
||||||
match result {
|
match result {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
self.final_ty = Some(v);
|
self.final_ty = Some(v);
|
||||||
|
@ -1520,7 +1534,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||||
augment_error(&mut err);
|
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(
|
fcx.emit_coerce_suggestions(
|
||||||
&mut err,
|
&mut err,
|
||||||
expr,
|
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 `!`
|
/// 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".
|
/// 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(
|
pub fn demand_coerce_diag(
|
||||||
&self,
|
&self,
|
||||||
expr: &hir::Expr<'tcx>,
|
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 expr_ty = self.resolve_vars_with_obligations(checked_ty);
|
||||||
let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone());
|
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))
|
(expected, Some(err))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,12 @@
|
||||||
error[E0308]: mismatched types
|
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;
|
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>)`
|
= note: expected fn pointer `for<'a, 'b> fn(Inv<'a>, Inv<'b>)`
|
||||||
found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)`
|
found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error: aborting due to previous error
|
||||||
--> $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
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0308]: mismatched types
|
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();
|
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)`
|
= note: expected fn pointer `for<'b> fn(&'b u32)`
|
||||||
found fn pointer `fn(&u32)`
|
found fn pointer `fn(&u32)`
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0308]: `match` arms have incompatible types
|
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 {
|
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`
|
| | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
||||||
LL | | _ => y,
|
LL | | _ => y,
|
||||||
| | ^ one type is more general than the other
|
| | ^ one type is more general than the other
|
||||||
|
LL | |
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
LL | | };
|
LL | | };
|
||||||
| |_____- `match` arms have incompatible types
|
| |_____- `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
|
error[E0308]: mismatched types
|
||||||
--> $DIR/old-lub-glb-hr-noteq1.rs:11:14
|
--> $DIR/old-lub-glb-hr-noteq1.rs:17:14
|
||||||
|
|
|
|
||||||
LL | _ => y,
|
LL | _ => y,
|
||||||
| ^ one type is more general than the other
|
| ^ 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
|
// general than the other. Test the case where the more general type (`x`) is the first
|
||||||
// match arm specifically.
|
// 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) {
|
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
|
// The two types above are not equivalent. With the older LUB/GLB
|
||||||
// algorithm, this may have worked (I don't remember), but now it
|
// algorithm, this may have worked (I don't remember), but now it
|
||||||
// doesn't because we require equality.
|
// doesn't because we require equality.
|
||||||
let z = match 22 {
|
let z = match 22 {
|
||||||
0 => x,
|
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
|
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 {
|
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`
|
| | - this is found to be of type `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
|
||||||
LL | | _ => x,
|
LL | | _ => x,
|
||||||
| | ^ one type is more general than the other
|
| | ^ one type is more general than the other
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
LL | | };
|
LL | | };
|
||||||
| |_____- `match` arms have incompatible types
|
| |_____- `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
|
// one is more general than the other. Test the case where the more general type
|
||||||
// (`x`) is the second match arm specifically.
|
// (`x`) is the second match arm specifically.
|
||||||
//
|
//
|
||||||
// FIXME(#73154) Skip for compare-mode because the pure NLL checker accepts this
|
// FIXME(#73154) Pure NLL checker without leak check accepts this test.
|
||||||
// test. (Note that it still errors in old-lub-glb-hr-noteq1.rs). What happens
|
// (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
|
// 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
|
// 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
|
// 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-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) {
|
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
|
// 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.
|
// doesn't because we require equality.
|
||||||
let z = match 22 {
|
let z = match 22 {
|
||||||
0 => y,
|
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
|
| ^^ ...but data from `y` flows into `x` here
|
||||||
|
|
||||||
error[E0623]: lifetime mismatch
|
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) {
|
LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||||
| --------- --------- these two types are declared with different lifetimes...
|
| --------- --------- these two types are declared with different lifetimes...
|
||||||
|
@ -17,13 +17,13 @@ LL | a(x, y);
|
||||||
| ^ ...but data from `y` flows into `x` here
|
| ^ ...but data from `y` flows into `x` here
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
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;
|
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)`
|
= 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
|
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
|
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;
|
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)`
|
= 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
|
error: aborting due to previous error
|
||||||
--> $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
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
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.
|
// Illegal now because there is no `'b:'a` declaration.
|
||||||
*x = *y;
|
*x = *y;
|
||||||
//[base]~^ ERROR E0623
|
//[base]~^ ERROR E0623
|
||||||
//[nll]~^^ ERROR lifetime may not live long enough
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
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.
|
// related as required.
|
||||||
a(x, y);
|
a(x, y);
|
||||||
//[base]~^ ERROR lifetime mismatch [E0623]
|
//[base]~^ ERROR lifetime mismatch [E0623]
|
||||||
//[nll]~^^ ERROR lifetime may not live long enough
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn d() {
|
fn d() {
|
||||||
|
@ -27,7 +25,6 @@ fn d() {
|
||||||
// inconstraints:
|
// inconstraints:
|
||||||
let _: fn(&mut &isize, &mut &isize) = a;
|
let _: fn(&mut &isize, &mut &isize) = a;
|
||||||
//~^ ERROR mismatched types [E0308]
|
//~^ ERROR mismatched types [E0308]
|
||||||
//[nll]~^^ ERROR mismatched types [E0308]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn e() {
|
fn e() {
|
||||||
|
|
|
@ -8,7 +8,7 @@ LL | *x = *y;
|
||||||
| ^^ ...but data from `y` flows into `x` here
|
| ^^ ...but data from `y` flows into `x` here
|
||||||
|
|
||||||
error[E0623]: lifetime mismatch
|
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) {
|
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
|
| ^^ ...but data from `y` flows into `z` here
|
||||||
|
|
||||||
error[E0623]: lifetime mismatch
|
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) {
|
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...
|
| --------- --------- 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
|
| ^ ...but data from `y` flows into `x` here
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
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;
|
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)`
|
= 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
|
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
|
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;
|
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)`
|
= 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
|
error: aborting due to previous error
|
||||||
--> $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
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
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.
|
// Illegal now because there is no `'b:'a` declaration.
|
||||||
*x = *y;
|
*x = *y;
|
||||||
//[base]~^ ERROR E0623
|
//[base]~^ ERROR E0623
|
||||||
//[nll]~^^ ERROR lifetime may not live long enough
|
|
||||||
*z = *y; //[base]~ ERROR E0623
|
*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.
|
// related as required.
|
||||||
a(x, y, z);
|
a(x, y, z);
|
||||||
//[base]~^ ERROR lifetime mismatch [E0623]
|
//[base]~^ ERROR lifetime mismatch [E0623]
|
||||||
//[nll]~^^ ERROR lifetime may not live long enough
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn d() {
|
fn d() {
|
||||||
|
@ -29,8 +27,6 @@ fn d() {
|
||||||
// inconstraints:
|
// inconstraints:
|
||||||
let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
|
let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
|
||||||
//~^ ERROR E0308
|
//~^ ERROR E0308
|
||||||
//[nll]~^^ ERROR mismatched types [E0308]
|
|
||||||
//[nll]~| ERROR mismatched types [E0308]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn e() {
|
fn e() {
|
||||||
|
|
|
@ -2,10 +2,17 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/regions-fn-subtyping-return-static-fail.rs:52:12
|
--> $DIR/regions-fn-subtyping-return-static-fail.rs:52:12
|
||||||
|
|
|
|
||||||
LL | want_G(baz);
|
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`
|
= 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
error[E0308]: mismatched types
|
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);
|
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`
|
= 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ LL | *x = *y;
|
||||||
| ^^ ...but data from `y` flows into `x` here
|
| ^^ ...but data from `y` flows into `x` here
|
||||||
|
|
||||||
error[E0623]: lifetime mismatch
|
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) {
|
LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) {
|
||||||
| --------- --------- these two types are declared with different lifetimes...
|
| --------- --------- these two types are declared with different lifetimes...
|
||||||
|
@ -17,13 +17,13 @@ LL | a(x, y);
|
||||||
| ^ ...but data from `y` flows into `x` here
|
| ^ ...but data from `y` flows into `x` here
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
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;
|
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)`
|
= 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
|
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
|
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;
|
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)`
|
= 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
|
error: aborting due to previous error
|
||||||
--> $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
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
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.
|
// Illegal now because there is no `'b:'a` declaration.
|
||||||
*x = *y;
|
*x = *y;
|
||||||
//[base]~^ ERROR lifetime mismatch [E0623]
|
//[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) {
|
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.
|
// related as required.
|
||||||
a(x, y);
|
a(x, y);
|
||||||
//[base]~^ ERROR lifetime mismatch [E0623]
|
//[base]~^ ERROR lifetime mismatch [E0623]
|
||||||
//[nll]~^^ ERROR lifetime may not live long enough
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn d() {
|
fn d() {
|
||||||
|
@ -27,7 +25,6 @@ fn d() {
|
||||||
// inconstraints:
|
// inconstraints:
|
||||||
let _: fn(&mut &isize, &mut &isize) = a;
|
let _: fn(&mut &isize, &mut &isize) = a;
|
||||||
//~^ ERROR mismatched types [E0308]
|
//~^ ERROR mismatched types [E0308]
|
||||||
//[nll]~^^ ERROR mismatched types [E0308]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn e() {
|
fn e() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue