kill old-style-lub warnings
This commit is contained in:
@@ -15,7 +15,6 @@ use super::Subtype;
|
|||||||
|
|
||||||
use traits::ObligationCause;
|
use traits::ObligationCause;
|
||||||
use ty::{self, Ty, TyCtxt};
|
use ty::{self, Ty, TyCtxt};
|
||||||
use ty::error::TypeError;
|
|
||||||
use ty::relate::{Relate, RelateResult, TypeRelation};
|
use ty::relate::{Relate, RelateResult, TypeRelation};
|
||||||
|
|
||||||
/// "Greatest lower bound" (common subtype)
|
/// "Greatest lower bound" (common subtype)
|
||||||
@@ -76,31 +75,12 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
|
|||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
debug!("binders(a={:?}, b={:?})", a, b);
|
debug!("binders(a={:?}, b={:?})", a, b);
|
||||||
let was_error = self.infcx().probe(|_snapshot| {
|
|
||||||
// Subtle: use a fresh combine-fields here because we recover
|
|
||||||
// from Err. Doing otherwise could propagate obligations out
|
|
||||||
// through our `self.obligations` field.
|
|
||||||
self.infcx()
|
|
||||||
.combine_fields(self.fields.trace.clone(), self.fields.param_env)
|
|
||||||
.higher_ranked_glb(a, b, self.a_is_expected)
|
|
||||||
.is_err()
|
|
||||||
});
|
|
||||||
debug!("binders: was_error={:?}", was_error);
|
|
||||||
|
|
||||||
// When higher-ranked types are involved, computing the LUB is
|
// When higher-ranked types are involved, computing the LUB is
|
||||||
// very challenging, switch to invariance. This is obviously
|
// very challenging, switch to invariance. This is obviously
|
||||||
// overly conservative but works ok in practice.
|
// overly conservative but works ok in practice.
|
||||||
match self.relate_with_variance(ty::Variance::Invariant, a, b) {
|
self.relate_with_variance(ty::Variance::Invariant, a, b)?;
|
||||||
Ok(_) => Ok(a.clone()),
|
Ok(a.clone())
|
||||||
Err(err) => {
|
|
||||||
debug!("binders: error occurred, was_error={:?}", was_error);
|
|
||||||
if !was_error {
|
|
||||||
Err(TypeError::OldStyleLUB(Box::new(err)))
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ use super::region_constraints::{TaintDirections};
|
|||||||
use ty::{self, TyCtxt, Binder, TypeFoldable};
|
use ty::{self, TyCtxt, Binder, TypeFoldable};
|
||||||
use ty::error::TypeError;
|
use ty::error::TypeError;
|
||||||
use ty::relate::{Relate, RelateResult, TypeRelation};
|
use ty::relate::{Relate, RelateResult, TypeRelation};
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
use util::nodemap::{FxHashMap, FxHashSet};
|
use util::nodemap::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
@@ -202,261 +201,6 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
|||||||
Ok(HrMatchResult { value: a_value })
|
Ok(HrMatchResult { value: a_value })
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn higher_ranked_lub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
|
|
||||||
-> RelateResult<'tcx, Binder<T>>
|
|
||||||
where T: Relate<'tcx>
|
|
||||||
{
|
|
||||||
// Start a snapshot so we can examine "all bindings that were
|
|
||||||
// created as part of this type comparison".
|
|
||||||
return self.infcx.commit_if_ok(|snapshot| {
|
|
||||||
// Instantiate each bound region with a fresh region variable.
|
|
||||||
let span = self.trace.cause.span;
|
|
||||||
let (a_with_fresh, a_map) =
|
|
||||||
self.infcx.replace_late_bound_regions_with_fresh_var(
|
|
||||||
span, HigherRankedType, a);
|
|
||||||
let (b_with_fresh, _) =
|
|
||||||
self.infcx.replace_late_bound_regions_with_fresh_var(
|
|
||||||
span, HigherRankedType, b);
|
|
||||||
|
|
||||||
// Collect constraints.
|
|
||||||
let result0 =
|
|
||||||
self.lub(a_is_expected).relate(&a_with_fresh, &b_with_fresh)?;
|
|
||||||
let result0 =
|
|
||||||
self.infcx.resolve_type_vars_if_possible(&result0);
|
|
||||||
debug!("lub result0 = {:?}", result0);
|
|
||||||
|
|
||||||
// Generalize the regions appearing in result0 if possible
|
|
||||||
let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot);
|
|
||||||
let span = self.trace.cause.span;
|
|
||||||
let result1 =
|
|
||||||
fold_regions_in(
|
|
||||||
self.tcx(),
|
|
||||||
&result0,
|
|
||||||
|r, debruijn| generalize_region(self.infcx, span, snapshot, debruijn,
|
|
||||||
&new_vars, &a_map, r));
|
|
||||||
|
|
||||||
debug!("lub({:?},{:?}) = {:?}",
|
|
||||||
a,
|
|
||||||
b,
|
|
||||||
result1);
|
|
||||||
|
|
||||||
Ok(ty::Binder::bind(result1))
|
|
||||||
});
|
|
||||||
|
|
||||||
fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
|
||||||
span: Span,
|
|
||||||
snapshot: &CombinedSnapshot<'a, 'tcx>,
|
|
||||||
debruijn: ty::DebruijnIndex,
|
|
||||||
new_vars: &[ty::RegionVid],
|
|
||||||
a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
|
|
||||||
r0: ty::Region<'tcx>)
|
|
||||||
-> ty::Region<'tcx> {
|
|
||||||
// Regions that pre-dated the LUB computation stay as they are.
|
|
||||||
if !is_var_in_set(new_vars, r0) {
|
|
||||||
assert!(!r0.is_late_bound());
|
|
||||||
debug!("generalize_region(r0={:?}): not new variable", r0);
|
|
||||||
return r0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let tainted = infcx.tainted_regions(snapshot, r0, TaintDirections::both());
|
|
||||||
|
|
||||||
// Variables created during LUB computation which are
|
|
||||||
// *related* to regions that pre-date the LUB computation
|
|
||||||
// stay as they are.
|
|
||||||
if !tainted.iter().all(|&r| is_var_in_set(new_vars, r)) {
|
|
||||||
debug!("generalize_region(r0={:?}): \
|
|
||||||
non-new-variables found in {:?}",
|
|
||||||
r0, tainted);
|
|
||||||
assert!(!r0.is_late_bound());
|
|
||||||
return r0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, the variable must be associated with at
|
|
||||||
// least one of the variables representing bound regions
|
|
||||||
// in both A and B. Replace the variable with the "first"
|
|
||||||
// bound region from A that we find it to be associated
|
|
||||||
// with.
|
|
||||||
for (a_br, a_r) in a_map {
|
|
||||||
if tainted.iter().any(|x| x == a_r) {
|
|
||||||
debug!("generalize_region(r0={:?}): \
|
|
||||||
replacing with {:?}, tainted={:?}",
|
|
||||||
r0, *a_br, tainted);
|
|
||||||
return infcx.tcx.mk_region(ty::ReLateBound(debruijn, *a_br));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
span_bug!(
|
|
||||||
span,
|
|
||||||
"region {:?} is not associated with any bound region from A!",
|
|
||||||
r0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn higher_ranked_glb<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
|
|
||||||
-> RelateResult<'tcx, Binder<T>>
|
|
||||||
where T: Relate<'tcx>
|
|
||||||
{
|
|
||||||
debug!("higher_ranked_glb({:?}, {:?})",
|
|
||||||
a, b);
|
|
||||||
|
|
||||||
// Make a snapshot so we can examine "all bindings that were
|
|
||||||
// created as part of this type comparison".
|
|
||||||
return self.infcx.commit_if_ok(|snapshot| {
|
|
||||||
// Instantiate each bound region with a fresh region variable.
|
|
||||||
let (a_with_fresh, a_map) =
|
|
||||||
self.infcx.replace_late_bound_regions_with_fresh_var(
|
|
||||||
self.trace.cause.span, HigherRankedType, a);
|
|
||||||
let (b_with_fresh, b_map) =
|
|
||||||
self.infcx.replace_late_bound_regions_with_fresh_var(
|
|
||||||
self.trace.cause.span, HigherRankedType, b);
|
|
||||||
let a_vars = var_ids(self, &a_map);
|
|
||||||
let b_vars = var_ids(self, &b_map);
|
|
||||||
|
|
||||||
// Collect constraints.
|
|
||||||
let result0 =
|
|
||||||
self.glb(a_is_expected).relate(&a_with_fresh, &b_with_fresh)?;
|
|
||||||
let result0 =
|
|
||||||
self.infcx.resolve_type_vars_if_possible(&result0);
|
|
||||||
debug!("glb result0 = {:?}", result0);
|
|
||||||
|
|
||||||
// Generalize the regions appearing in result0 if possible
|
|
||||||
let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot);
|
|
||||||
let span = self.trace.cause.span;
|
|
||||||
let result1 =
|
|
||||||
fold_regions_in(
|
|
||||||
self.tcx(),
|
|
||||||
&result0,
|
|
||||||
|r, debruijn| generalize_region(self.infcx, span, snapshot, debruijn,
|
|
||||||
&new_vars,
|
|
||||||
&a_map, &a_vars, &b_vars,
|
|
||||||
r));
|
|
||||||
|
|
||||||
debug!("glb({:?},{:?}) = {:?}",
|
|
||||||
a,
|
|
||||||
b,
|
|
||||||
result1);
|
|
||||||
|
|
||||||
Ok(ty::Binder::bind(result1))
|
|
||||||
});
|
|
||||||
|
|
||||||
fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
|
||||||
span: Span,
|
|
||||||
snapshot: &CombinedSnapshot<'a, 'tcx>,
|
|
||||||
debruijn: ty::DebruijnIndex,
|
|
||||||
new_vars: &[ty::RegionVid],
|
|
||||||
a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
|
|
||||||
a_vars: &[ty::RegionVid],
|
|
||||||
b_vars: &[ty::RegionVid],
|
|
||||||
r0: ty::Region<'tcx>)
|
|
||||||
-> ty::Region<'tcx> {
|
|
||||||
if !is_var_in_set(new_vars, r0) {
|
|
||||||
assert!(!r0.is_late_bound());
|
|
||||||
return r0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let tainted = infcx.tainted_regions(snapshot, r0, TaintDirections::both());
|
|
||||||
|
|
||||||
let mut a_r = None;
|
|
||||||
let mut b_r = None;
|
|
||||||
let mut only_new_vars = true;
|
|
||||||
for r in &tainted {
|
|
||||||
if is_var_in_set(a_vars, *r) {
|
|
||||||
if a_r.is_some() {
|
|
||||||
return fresh_bound_variable(infcx, debruijn);
|
|
||||||
} else {
|
|
||||||
a_r = Some(*r);
|
|
||||||
}
|
|
||||||
} else if is_var_in_set(b_vars, *r) {
|
|
||||||
if b_r.is_some() {
|
|
||||||
return fresh_bound_variable(infcx, debruijn);
|
|
||||||
} else {
|
|
||||||
b_r = Some(*r);
|
|
||||||
}
|
|
||||||
} else if !is_var_in_set(new_vars, *r) {
|
|
||||||
only_new_vars = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NB---I do not believe this algorithm computes
|
|
||||||
// (necessarily) the GLB. As written it can
|
|
||||||
// spuriously fail. In particular, if there is a case
|
|
||||||
// like: |fn(&a)| and fn(fn(&b)), where a and b are
|
|
||||||
// free, it will return fn(&c) where c = GLB(a,b). If
|
|
||||||
// however this GLB is not defined, then the result is
|
|
||||||
// an error, even though something like
|
|
||||||
// "fn<X>(fn(&X))" where X is bound would be a
|
|
||||||
// subtype of both of those.
|
|
||||||
//
|
|
||||||
// The problem is that if we were to return a bound
|
|
||||||
// variable, we'd be computing a lower-bound, but not
|
|
||||||
// necessarily the *greatest* lower-bound.
|
|
||||||
//
|
|
||||||
// Unfortunately, this problem is non-trivial to solve,
|
|
||||||
// because we do not know at the time of computing the GLB
|
|
||||||
// whether a GLB(a,b) exists or not, because we haven't
|
|
||||||
// run region inference (or indeed, even fully computed
|
|
||||||
// the region hierarchy!). The current algorithm seems to
|
|
||||||
// works ok in practice.
|
|
||||||
|
|
||||||
if a_r.is_some() && b_r.is_some() && only_new_vars {
|
|
||||||
// Related to exactly one bound variable from each fn:
|
|
||||||
return rev_lookup(infcx, span, a_map, a_r.unwrap());
|
|
||||||
} else if a_r.is_none() && b_r.is_none() {
|
|
||||||
// Not related to bound variables from either fn:
|
|
||||||
assert!(!r0.is_late_bound());
|
|
||||||
return r0;
|
|
||||||
} else {
|
|
||||||
// Other:
|
|
||||||
return fresh_bound_variable(infcx, debruijn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rev_lookup<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
|
||||||
span: Span,
|
|
||||||
a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
|
|
||||||
r: ty::Region<'tcx>) -> ty::Region<'tcx>
|
|
||||||
{
|
|
||||||
for (a_br, a_r) in a_map {
|
|
||||||
if *a_r == r {
|
|
||||||
return infcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, *a_br));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span_bug!(
|
|
||||||
span,
|
|
||||||
"could not find original bound region for {:?}",
|
|
||||||
r);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fresh_bound_variable<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
|
||||||
debruijn: ty::DebruijnIndex)
|
|
||||||
-> ty::Region<'tcx> {
|
|
||||||
infcx.borrow_region_constraints().new_bound(infcx.tcx, debruijn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn var_ids<'a, 'gcx, 'tcx>(fields: &CombineFields<'a, 'gcx, 'tcx>,
|
|
||||||
map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
|
|
||||||
-> Vec<ty::RegionVid> {
|
|
||||||
map.iter()
|
|
||||||
.map(|(_, &r)| match *r {
|
|
||||||
ty::ReVar(r) => { r }
|
|
||||||
_ => {
|
|
||||||
span_bug!(
|
|
||||||
fields.trace.cause.span,
|
|
||||||
"found non-region-vid: {:?}",
|
|
||||||
r);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_var_in_set(new_vars: &[ty::RegionVid], r: ty::Region<'_>) -> bool {
|
|
||||||
match *r {
|
|
||||||
ty::ReVar(ref v) => new_vars.iter().any(|x| x == v),
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_regions_in<'a, 'gcx, 'tcx, T, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
fn fold_regions_in<'a, 'gcx, 'tcx, T, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ use super::Subtype;
|
|||||||
|
|
||||||
use traits::ObligationCause;
|
use traits::ObligationCause;
|
||||||
use ty::{self, Ty, TyCtxt};
|
use ty::{self, Ty, TyCtxt};
|
||||||
use ty::error::TypeError;
|
|
||||||
use ty::relate::{Relate, RelateResult, TypeRelation};
|
use ty::relate::{Relate, RelateResult, TypeRelation};
|
||||||
|
|
||||||
/// "Least upper bound" (common supertype)
|
/// "Least upper bound" (common supertype)
|
||||||
@@ -76,31 +75,12 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
|
|||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
debug!("binders(a={:?}, b={:?})", a, b);
|
debug!("binders(a={:?}, b={:?})", a, b);
|
||||||
let was_error = self.infcx().probe(|_snapshot| {
|
|
||||||
// Subtle: use a fresh combine-fields here because we recover
|
|
||||||
// from Err. Doing otherwise could propagate obligations out
|
|
||||||
// through our `self.obligations` field.
|
|
||||||
self.infcx()
|
|
||||||
.combine_fields(self.fields.trace.clone(), self.fields.param_env)
|
|
||||||
.higher_ranked_lub(a, b, self.a_is_expected)
|
|
||||||
.is_err()
|
|
||||||
});
|
|
||||||
debug!("binders: was_error={:?}", was_error);
|
|
||||||
|
|
||||||
// When higher-ranked types are involved, computing the LUB is
|
// When higher-ranked types are involved, computing the LUB is
|
||||||
// very challenging, switch to invariance. This is obviously
|
// very challenging, switch to invariance. This is obviously
|
||||||
// overly conservative but works ok in practice.
|
// overly conservative but works ok in practice.
|
||||||
match self.relate_with_variance(ty::Variance::Invariant, a, b) {
|
self.relate_with_variance(ty::Variance::Invariant, a, b)?;
|
||||||
Ok(_) => Ok(a.clone()),
|
Ok(a.clone())
|
||||||
Err(err) => {
|
|
||||||
debug!("binders: error occurred, was_error={:?}", was_error);
|
|
||||||
if !was_error {
|
|
||||||
Err(TypeError::OldStyleLUB(Box::new(err)))
|
|
||||||
} else {
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,8 +53,6 @@ pub enum TypeError<'tcx> {
|
|||||||
ProjectionMismatched(ExpectedFound<DefId>),
|
ProjectionMismatched(ExpectedFound<DefId>),
|
||||||
ProjectionBoundsLength(ExpectedFound<usize>),
|
ProjectionBoundsLength(ExpectedFound<usize>),
|
||||||
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
|
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
|
||||||
|
|
||||||
OldStyleLUB(Box<TypeError<'tcx>>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
|
||||||
@@ -166,9 +164,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
|
|||||||
report_maybe_different(f, &format!("trait `{}`", values.expected),
|
report_maybe_different(f, &format!("trait `{}`", values.expected),
|
||||||
&format!("trait `{}`", values.found))
|
&format!("trait `{}`", values.found))
|
||||||
}
|
}
|
||||||
OldStyleLUB(ref err) => {
|
|
||||||
write!(f, "{}", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,12 +261,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
OldStyleLUB(err) => {
|
|
||||||
db.note("this was previously accepted by the compiler but has been phased out");
|
|
||||||
db.note("for more information, see https://github.com/rust-lang/rust/issues/45852");
|
|
||||||
|
|
||||||
self.note_and_explain_type_err(db, &err, sp);
|
|
||||||
}
|
|
||||||
CyclicTy(ty) => {
|
CyclicTy(ty) => {
|
||||||
// Watch out for various cases of cyclic types and try to explain.
|
// Watch out for various cases of cyclic types and try to explain.
|
||||||
if ty.is_closure() || ty.is_generator() {
|
if ty.is_closure() || ty.is_generator() {
|
||||||
|
|||||||
@@ -455,7 +455,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
|
|||||||
ProjectionMismatched(x) => ProjectionMismatched(x),
|
ProjectionMismatched(x) => ProjectionMismatched(x),
|
||||||
ProjectionBoundsLength(x) => ProjectionBoundsLength(x),
|
ProjectionBoundsLength(x) => ProjectionBoundsLength(x),
|
||||||
Sorts(ref x) => return tcx.lift(x).map(Sorts),
|
Sorts(ref x) => return tcx.lift(x).map(Sorts),
|
||||||
OldStyleLUB(ref x) => return tcx.lift(x).map(OldStyleLUB),
|
|
||||||
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch)
|
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1000,7 +999,6 @@ EnumTypeFoldableImpl! {
|
|||||||
(ty::error::TypeError::ProjectionBoundsLength)(x),
|
(ty::error::TypeError::ProjectionBoundsLength)(x),
|
||||||
(ty::error::TypeError::Sorts)(x),
|
(ty::error::TypeError::Sorts)(x),
|
||||||
(ty::error::TypeError::ExistentialMismatch)(x),
|
(ty::error::TypeError::ExistentialMismatch)(x),
|
||||||
(ty::error::TypeError::OldStyleLUB)(x),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ LL | | };
|
|||||||
|
|
|
|
||||||
= note: expected type `for<'r, 's> fn(&'r u8, &'s u8)`
|
= note: expected type `for<'r, 's> fn(&'r u8, &'s u8)`
|
||||||
found type `for<'a> fn(&'a u8, &'a u8)`
|
found type `for<'a> fn(&'a u8, &'a u8)`
|
||||||
= note: this was previously accepted by the compiler but has been phased out
|
|
||||||
= note: for more information, see https://github.com/rust-lang/rust/issues/45852
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ LL | | };
|
|||||||
|
|
|
|
||||||
= note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
|
= note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
|
||||||
found type `&dyn for<'a> Foo<&'a u8, &'a u8>`
|
found type `&dyn for<'a> Foo<&'a u8, &'a u8>`
|
||||||
= note: this was previously accepted by the compiler but has been phased out
|
|
||||||
= note: for more information, see https://github.com/rust-lang/rust/issues/45852
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user