propagate user-ascribes types down onto resulting bindings
But only in very simple cases.
This commit is contained in:
parent
a8710539cb
commit
e87bf30f5f
14 changed files with 171 additions and 35 deletions
|
|
@ -24,6 +24,7 @@ impl_stable_hash_for!(enum mir::LocalKind { Var, Temp, Arg, ReturnPointer });
|
|||
impl_stable_hash_for!(struct mir::LocalDecl<'tcx> {
|
||||
mutability,
|
||||
ty,
|
||||
user_ty,
|
||||
name,
|
||||
source_info,
|
||||
visibility_scope,
|
||||
|
|
|
|||
|
|
@ -640,6 +640,12 @@ pub struct LocalDecl<'tcx> {
|
|||
/// Type of this local.
|
||||
pub ty: Ty<'tcx>,
|
||||
|
||||
/// If the user manually ascribed a type to this variable,
|
||||
/// e.g. via `let x: T`, then we carry that type here. The MIR
|
||||
/// borrow checker needs this information since it can affect
|
||||
/// region inference.
|
||||
pub user_ty: Option<CanonicalTy<'tcx>>,
|
||||
|
||||
/// Name of the local, used in debuginfo and pretty-printing.
|
||||
///
|
||||
/// Note that function arguments can also have this set to `Some(_)`
|
||||
|
|
@ -802,6 +808,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
|||
LocalDecl {
|
||||
mutability,
|
||||
ty,
|
||||
user_ty: None,
|
||||
name: None,
|
||||
source_info: SourceInfo {
|
||||
span,
|
||||
|
|
@ -821,6 +828,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
|||
LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: return_ty,
|
||||
user_ty: None,
|
||||
source_info: SourceInfo {
|
||||
span,
|
||||
scope: OUTERMOST_SOURCE_SCOPE,
|
||||
|
|
@ -2613,6 +2621,7 @@ BraceStructTypeFoldableImpl! {
|
|||
is_user_variable,
|
||||
internal,
|
||||
ty,
|
||||
user_ty,
|
||||
name,
|
||||
source_info,
|
||||
visibility_scope,
|
||||
|
|
|
|||
|
|
@ -721,6 +721,7 @@ macro_rules! make_mir_visitor {
|
|||
let LocalDecl {
|
||||
mutability: _,
|
||||
ref $($mutability)* ty,
|
||||
ref $($mutability)* user_ty,
|
||||
name: _,
|
||||
ref $($mutability)* source_info,
|
||||
ref $($mutability)* visibility_scope,
|
||||
|
|
@ -732,6 +733,9 @@ macro_rules! make_mir_visitor {
|
|||
local,
|
||||
source_info: *source_info,
|
||||
});
|
||||
if let Some(user_ty) = user_ty {
|
||||
self.visit_canonical_ty(user_ty);
|
||||
}
|
||||
self.visit_source_info(source_info);
|
||||
self.visit_source_scope(visibility_scope);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,6 +275,25 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
|
||||
self.super_local_decl(local, local_decl);
|
||||
self.sanitize_type(local_decl, local_decl.ty);
|
||||
|
||||
if let Some(user_ty) = local_decl.user_ty {
|
||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||
local_decl.ty,
|
||||
ty::Variance::Invariant,
|
||||
user_ty,
|
||||
Locations::All,
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
local,
|
||||
"bad user type on variable {:?}: {:?} != {:?} ({:?})",
|
||||
local,
|
||||
local_decl.ty,
|
||||
local_decl.user_ty,
|
||||
terr,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mir(&mut self, mir: &Mir<'tcx>) {
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
None, remainder_span, lint_level, slice::from_ref(&pattern),
|
||||
ArmHasGuard(false), None);
|
||||
|
||||
this.visit_bindings(&pattern, &mut |this, _, _, _, node, span, _| {
|
||||
this.visit_bindings(&pattern, None, &mut |this, _, _, _, node, span, _, _| {
|
||||
this.storage_live_binding(block, node, span, OutsideGuard);
|
||||
this.schedule_drop_for_binding(node, span, OutsideGuard);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -296,6 +296,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
let ptr_temp = this.local_decls.push(LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: ptr_ty,
|
||||
user_ty: None,
|
||||
name: None,
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
|
|
|
|||
|
|
@ -399,7 +399,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
let num_patterns = patterns.len();
|
||||
self.visit_bindings(
|
||||
&patterns[0],
|
||||
&mut |this, mutability, name, mode, var, span, ty| {
|
||||
None,
|
||||
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
|
||||
if visibility_scope.is_none() {
|
||||
visibility_scope =
|
||||
Some(this.new_source_scope(scope_span, LintLevel::Inherited, None));
|
||||
|
|
@ -421,6 +422,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
num_patterns,
|
||||
var,
|
||||
ty,
|
||||
user_ty,
|
||||
has_guard,
|
||||
opt_match_place.map(|(x, y)| (x.cloned(), y)),
|
||||
patterns[0].span,
|
||||
|
|
@ -470,10 +472,21 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, f: &mut F)
|
||||
where
|
||||
F: FnMut(&mut Self, Mutability, Name, BindingMode, NodeId, Span, Ty<'tcx>),
|
||||
{
|
||||
pub fn visit_bindings(
|
||||
&mut self,
|
||||
pattern: &Pattern<'tcx>,
|
||||
pattern_user_ty: Option<CanonicalTy<'tcx>>,
|
||||
f: &mut impl FnMut(
|
||||
&mut Self,
|
||||
Mutability,
|
||||
Name,
|
||||
BindingMode,
|
||||
NodeId,
|
||||
Span,
|
||||
Ty<'tcx>,
|
||||
Option<CanonicalTy<'tcx>>,
|
||||
),
|
||||
) {
|
||||
match *pattern.kind {
|
||||
PatternKind::Binding {
|
||||
mutability,
|
||||
|
|
@ -484,9 +497,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
ref subpattern,
|
||||
..
|
||||
} => {
|
||||
f(self, mutability, name, mode, var, pattern.span, ty);
|
||||
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty);
|
||||
if let Some(subpattern) = subpattern.as_ref() {
|
||||
self.visit_bindings(subpattern, f);
|
||||
self.visit_bindings(subpattern, pattern_user_ty, f);
|
||||
}
|
||||
}
|
||||
PatternKind::Array {
|
||||
|
|
@ -499,21 +512,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
ref slice,
|
||||
ref suffix,
|
||||
} => {
|
||||
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
|
||||
for subpattern in prefix.iter().chain(slice).chain(suffix) {
|
||||
self.visit_bindings(subpattern, f);
|
||||
self.visit_bindings(subpattern, None, f);
|
||||
}
|
||||
}
|
||||
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {}
|
||||
PatternKind::AscribeUserType { ref subpattern, .. }
|
||||
| PatternKind::Deref { ref subpattern } => {
|
||||
self.visit_bindings(subpattern, f);
|
||||
PatternKind::Deref { ref subpattern } => {
|
||||
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
|
||||
self.visit_bindings(subpattern, None, f);
|
||||
}
|
||||
PatternKind::AscribeUserType { ref subpattern, user_ty } => {
|
||||
// This corresponds to something like
|
||||
//
|
||||
// ```
|
||||
// let (p1: T1): T2 = ...;
|
||||
// ```
|
||||
//
|
||||
// Not presently possible, though maybe someday.
|
||||
assert!(pattern_user_ty.is_none());
|
||||
self.visit_bindings(subpattern, Some(user_ty), f)
|
||||
}
|
||||
PatternKind::Leaf { ref subpatterns }
|
||||
| PatternKind::Variant {
|
||||
ref subpatterns, ..
|
||||
} => {
|
||||
// FIXME(#47184): extract or handle `pattern_user_ty` somehow
|
||||
for subpattern in subpatterns {
|
||||
self.visit_bindings(&subpattern.pattern, f);
|
||||
self.visit_bindings(&subpattern.pattern, None, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1375,6 +1401,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
num_patterns: usize,
|
||||
var_id: NodeId,
|
||||
var_ty: Ty<'tcx>,
|
||||
user_var_ty: Option<CanonicalTy<'tcx>>,
|
||||
has_guard: ArmHasGuard,
|
||||
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
|
||||
pat_span: Span,
|
||||
|
|
@ -1392,7 +1419,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
};
|
||||
let local = LocalDecl::<'tcx> {
|
||||
mutability,
|
||||
ty: var_ty.clone(),
|
||||
ty: var_ty,
|
||||
user_ty: user_var_ty,
|
||||
name: Some(name),
|
||||
source_info,
|
||||
visibility_scope,
|
||||
|
|
@ -1424,6 +1452,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
// See previous comment.
|
||||
mutability: Mutability::Not,
|
||||
ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty),
|
||||
user_ty: None,
|
||||
name: Some(name),
|
||||
source_info,
|
||||
visibility_scope,
|
||||
|
|
|
|||
|
|
@ -730,6 +730,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
self.local_decls.push(LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty,
|
||||
user_ty: None,
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
name,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
|
|||
#![feature(if_while_or_patterns)]
|
||||
#![feature(try_from)]
|
||||
#![feature(reverse_bits)]
|
||||
#![feature(underscore_imports)]
|
||||
|
||||
#![recursion_limit="256"]
|
||||
|
||||
|
|
|
|||
|
|
@ -140,7 +140,9 @@ enum CallKind {
|
|||
fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
|
||||
let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span };
|
||||
LocalDecl {
|
||||
mutability, ty, name: None,
|
||||
mutability, ty,
|
||||
user_ty: None,
|
||||
name: None,
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
internal: false,
|
||||
|
|
|
|||
|
|
@ -303,6 +303,7 @@ fn replace_result_variable<'tcx>(
|
|||
let new_ret = LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: ret_ty,
|
||||
user_ty: None,
|
||||
name: None,
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
|
|
@ -656,6 +657,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
|
|||
mir.local_decls[RETURN_PLACE] = LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: tcx.mk_nil(),
|
||||
user_ty: None,
|
||||
name: None,
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
|
|
@ -672,6 +674,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
|
|||
ty: gen_ty,
|
||||
mutbl: hir::Mutability::MutMutable,
|
||||
}),
|
||||
user_ty: None,
|
||||
name: None,
|
||||
source_info,
|
||||
visibility_scope: source_info.scope,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use rustc::ty::item_path;
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use std::fmt::Display;
|
||||
use std::fmt::Write as _;
|
||||
use std::fs;
|
||||
use std::io::{self, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
|
@ -493,14 +494,18 @@ fn write_scope_tree(
|
|||
};
|
||||
|
||||
let indent = indent + INDENT.len();
|
||||
let indented_var = format!(
|
||||
"{0:1$}let {2}{3:?}: {4:?};",
|
||||
let mut indented_var = format!(
|
||||
"{0:1$}let {2}{3:?}: {4:?}",
|
||||
INDENT,
|
||||
indent,
|
||||
mut_str,
|
||||
local,
|
||||
var.ty
|
||||
);
|
||||
if let Some(user_ty) = var.user_ty {
|
||||
write!(indented_var, " as {:?}", user_ty).unwrap();
|
||||
}
|
||||
indented_var.push_str(";");
|
||||
writeln!(
|
||||
w,
|
||||
"{0:1$} // \"{2}\" in {3}",
|
||||
|
|
|
|||
|
|
@ -3,10 +3,41 @@
|
|||
#![feature(nll)]
|
||||
|
||||
fn variable_no_initializer() {
|
||||
// FIXME: It is unclear to me whether this should be an error or not.
|
||||
|
||||
let x = 22;
|
||||
let y: &'static u32;
|
||||
y = &x; //~ ERROR
|
||||
}
|
||||
|
||||
fn tuple_no_initializer() {
|
||||
// FIXME(#47187): We are not propagating ascribed type through tuples.
|
||||
|
||||
let x = 22;
|
||||
let (y, z): (&'static u32, &'static u32);
|
||||
y = &x;
|
||||
}
|
||||
|
||||
fn ref_with_ascribed_static_type() -> u32 {
|
||||
// Check the behavior in some wacky cases.
|
||||
let x = 22;
|
||||
let y = &x; //~ ERROR
|
||||
let ref z: &'static u32 = y; //~ ERROR
|
||||
**z
|
||||
}
|
||||
|
||||
fn ref_with_ascribed_any_type() -> u32 {
|
||||
let x = 22;
|
||||
let y = &x;
|
||||
let ref z: &u32 = y;
|
||||
**z
|
||||
}
|
||||
|
||||
struct Single<T> { value: T }
|
||||
|
||||
fn struct_no_initializer() {
|
||||
// FIXME(#47187): We are not propagating ascribed type through patterns.
|
||||
|
||||
let x = 22;
|
||||
let Single { value: y }: Single<&'static u32>;
|
||||
y = &x;
|
||||
}
|
||||
|
||||
|
|
@ -39,8 +70,6 @@ fn pair_variable_with_initializer() {
|
|||
let (y, _): (&'static u32, u32) = (&x, 44); //~ ERROR
|
||||
}
|
||||
|
||||
struct Single<T> { value: T }
|
||||
|
||||
fn struct_single_field_variable_with_initializer() {
|
||||
let x = 22;
|
||||
let Single { value: y }: Single<&'static u32> = Single { value: &x }; //~ ERROR
|
||||
|
|
@ -73,7 +102,7 @@ fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
|
|||
}
|
||||
|
||||
fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
|
||||
// FIXME: The fact that this type-checks is perhaps surprising.
|
||||
// FIXME(#47187): The fact that this type-checks is perhaps surprising.
|
||||
// What happens is that the right-hand side is constrained to have
|
||||
// type `&'a u32`, which is possible, because it has type
|
||||
// `&'static u32`. The variable `y` is then forced to have type
|
||||
|
|
|
|||
|
|
@ -1,5 +1,37 @@
|
|||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:15:27
|
||||
--> $DIR/patterns.rs:8:9
|
||||
|
|
||||
LL | y = &x; //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL | }
|
||||
| - `x` dropped here while still borrowed
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:22:13
|
||||
|
|
||||
LL | let y = &x; //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
...
|
||||
LL | }
|
||||
| - `x` dropped here while still borrowed
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: `y` does not live long enough
|
||||
--> $DIR/patterns.rs:23:9
|
||||
|
|
||||
LL | let ref z: &'static u32 = y; //~ ERROR
|
||||
| ^^^^^ borrowed value does not live long enough
|
||||
LL | **z
|
||||
LL | }
|
||||
| - `y` dropped here while still borrowed
|
||||
|
|
||||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:46:27
|
||||
|
|
||||
LL | let y: &'static u32 = &x; //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
|
|
@ -9,7 +41,7 @@ LL | }
|
|||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:20:27
|
||||
--> $DIR/patterns.rs:51:27
|
||||
|
|
||||
LL | let _: &'static u32 = &x; //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
|
|
@ -20,7 +52,7 @@ LL | }
|
|||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/patterns.rs:22:41
|
||||
--> $DIR/patterns.rs:53:41
|
||||
|
|
||||
LL | let _: Vec<&'static String> = vec![&String::new()];
|
||||
| ^^^^^^^^^^^^^ - temporary value only lives until here
|
||||
|
|
@ -30,7 +62,7 @@ LL | let _: Vec<&'static String> = vec![&String::new()];
|
|||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/patterns.rs:25:52
|
||||
--> $DIR/patterns.rs:56:52
|
||||
|
|
||||
LL | let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44);
|
||||
| ^^^^^^^^^^^^^ - temporary value only lives until here
|
||||
|
|
@ -40,7 +72,7 @@ LL | let (_, a): (Vec<&'static String>, _) = (vec![&String::new()], 44);
|
|||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/patterns.rs:28:53
|
||||
--> $DIR/patterns.rs:59:53
|
||||
|
|
||||
LL | let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44);
|
||||
| ^^^^^^^^^^^^^ - temporary value only lives until here
|
||||
|
|
@ -50,7 +82,7 @@ LL | let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44);
|
|||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:34:40
|
||||
--> $DIR/patterns.rs:65:40
|
||||
|
|
||||
LL | let (_, _): (&'static u32, u32) = (&x, 44); //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
|
|
@ -60,7 +92,7 @@ LL | }
|
|||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:39:40
|
||||
--> $DIR/patterns.rs:70:40
|
||||
|
|
||||
LL | let (y, _): (&'static u32, u32) = (&x, 44); //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
|
|
@ -70,7 +102,7 @@ LL | }
|
|||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:46:69
|
||||
--> $DIR/patterns.rs:75:69
|
||||
|
|
||||
LL | let Single { value: y }: Single<&'static u32> = Single { value: &x }; //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
|
|
@ -80,7 +112,7 @@ LL | }
|
|||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:51:69
|
||||
--> $DIR/patterns.rs:80:69
|
||||
|
|
||||
LL | let Single { value: _ }: Single<&'static u32> = Single { value: &x }; //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
|
|
@ -90,7 +122,7 @@ LL | }
|
|||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error[E0597]: `x` does not live long enough
|
||||
--> $DIR/patterns.rs:59:17
|
||||
--> $DIR/patterns.rs:88:17
|
||||
|
|
||||
LL | value1: &x, //~ ERROR
|
||||
| ^^ borrowed value does not live long enough
|
||||
|
|
@ -101,7 +133,7 @@ LL | }
|
|||
= note: borrowed value must be valid for the static lifetime...
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/patterns.rs:72:5
|
||||
--> $DIR/patterns.rs:101:5
|
||||
|
|
||||
LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
|
||||
| -- lifetime `'a` defined here
|
||||
|
|
@ -110,13 +142,13 @@ LL | y //~ ERROR
|
|||
| ^ returning this value requires that `'a` must outlive `'static`
|
||||
|
||||
error: unsatisfied lifetime constraints
|
||||
--> $DIR/patterns.rs:88:40
|
||||
--> $DIR/patterns.rs:117:40
|
||||
|
|
||||
LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | let (y, _z): (&'static u32, u32) = (x, 44); //~ ERROR
|
||||
| ^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0597`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue