Rollup merge of #72493 - nikomatsakis:move-leak-check, r=matthewjasper
move leak-check to during coherence, candidate eval Implementation of MCP https://github.com/rust-lang/compiler-team/issues/295. I'd like to do a crater run on this. Note to @rust-lang/lang: This PR is a breaking change (bugfix). It causes tests like the following to go from a future-compatibility warning #56105 to a hard error: ```rust trait Trait {} impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} impl Trait for for<'c> fn(&'c u32, &'c u32) {} // now rejected, used to warn ``` I am not aware of any instances of this code in the wild, but that is why we are doing a crater run. The reason for this change is that those two types are, in fact, the same type, and hence the two impls are overlapping. There will still be impls that trigger #56105 after this lands, however -- I hope that we will eventually just accept those impls without warning, for the most part. One example of such an impl is this pattern, which is used by wasm-bindgen and other crates as well: ```rust trait Trait {} impl<T> Trait for fn(&T) { } impl<T> Trait for fn(T) { } // still accepted, but warns ```
This commit is contained in:
commit
903823c59b
135 changed files with 2143 additions and 1250 deletions
|
|
@ -30,10 +30,10 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
|
|||
|
||||
let span = self.trace.cause.span;
|
||||
|
||||
self.infcx.commit_if_ok(|snapshot| {
|
||||
self.infcx.commit_if_ok(|_| {
|
||||
// First, we instantiate each bound region in the supertype with a
|
||||
// fresh placeholder region.
|
||||
let (b_prime, placeholder_map) = self.infcx.replace_bound_vars_with_placeholders(b);
|
||||
let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b);
|
||||
|
||||
// Next, we instantiate each bound region in the subtype
|
||||
// with a fresh region variable. These region variables --
|
||||
|
|
@ -48,8 +48,6 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
|
|||
// Compare types now that bound regions have been replaced.
|
||||
let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?;
|
||||
|
||||
self.infcx.leak_check(!a_is_expected, &placeholder_map, snapshot)?;
|
||||
|
||||
debug!("higher_ranked_sub: OK result={:?}", result);
|
||||
|
||||
Ok(ty::Binder::bind(result))
|
||||
|
|
@ -75,7 +73,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
let next_universe = self.create_next_universe();
|
||||
// Figure out what the next universe will be, but don't actually create
|
||||
// it until after we've done the substitution (in particular there may
|
||||
// be no bound variables). This is a performance optimization, since the
|
||||
// leak check for example can be skipped if no new universes are created
|
||||
// (i.e., if there are no placeholders).
|
||||
let next_universe = self.universe().next_universe();
|
||||
|
||||
let fld_r = |br| {
|
||||
self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion {
|
||||
|
|
@ -103,6 +106,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
|
||||
let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t, fld_c);
|
||||
|
||||
// If there were higher-ranked regions to replace, then actually create
|
||||
// the next universe (this avoids needlessly creating universes).
|
||||
if !map.is_empty() {
|
||||
let n_u = self.create_next_universe();
|
||||
assert_eq!(n_u, next_universe);
|
||||
}
|
||||
|
||||
debug!(
|
||||
"replace_bound_vars_with_placeholders(\
|
||||
next_universe={:?}, \
|
||||
|
|
@ -119,7 +129,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
pub fn leak_check(
|
||||
&self,
|
||||
overly_polymorphic: bool,
|
||||
placeholder_map: &PlaceholderMap<'tcx>,
|
||||
snapshot: &CombinedSnapshot<'_, 'tcx>,
|
||||
) -> RelateResult<'tcx, ()> {
|
||||
// If the user gave `-Zno-leak-check`, or we have been
|
||||
|
|
@ -135,7 +144,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
self.inner.borrow_mut().unwrap_region_constraints().leak_check(
|
||||
self.tcx,
|
||||
overly_polymorphic,
|
||||
placeholder_map,
|
||||
self.universe(),
|
||||
snapshot,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -991,14 +991,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
return None;
|
||||
}
|
||||
|
||||
Some(self.commit_if_ok(|snapshot| {
|
||||
let (ty::SubtypePredicate { a_is_expected, a, b }, placeholder_map) =
|
||||
Some(self.commit_if_ok(|_snapshot| {
|
||||
let (ty::SubtypePredicate { a_is_expected, a, b }, _) =
|
||||
self.replace_bound_vars_with_placeholders(&predicate);
|
||||
|
||||
let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
|
||||
|
||||
self.leak_check(false, &placeholder_map, snapshot)?;
|
||||
|
||||
Ok(ok.unit())
|
||||
}))
|
||||
}
|
||||
|
|
@ -1008,14 +1006,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
cause: &traits::ObligationCause<'tcx>,
|
||||
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
|
||||
) -> UnitResult<'tcx> {
|
||||
self.commit_if_ok(|snapshot| {
|
||||
let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) =
|
||||
self.commit_if_ok(|_snapshot| {
|
||||
let (ty::OutlivesPredicate(r_a, r_b), _) =
|
||||
self.replace_bound_vars_with_placeholders(&predicate);
|
||||
let origin = SubregionOrigin::from_obligation_cause(cause, || {
|
||||
RelateRegionParamBound(cause.span)
|
||||
});
|
||||
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
|
||||
self.leak_check(false, &placeholder_map, snapshot)?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -522,7 +522,13 @@ where
|
|||
}
|
||||
|
||||
if a == b {
|
||||
return Ok(a);
|
||||
// Subtle: if a or b has a bound variable that we are lazilly
|
||||
// substituting, then even if a == b, it could be that the values we
|
||||
// will substitute for those bound variables are *not* the same, and
|
||||
// hence returning `Ok(a)` is incorrect.
|
||||
if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
|
||||
return Ok(a);
|
||||
}
|
||||
}
|
||||
|
||||
match (&a.kind, &b.kind) {
|
||||
|
|
|
|||
|
|
@ -1,158 +1,446 @@
|
|||
use super::*;
|
||||
use crate::infer::{CombinedSnapshot, PlaceholderMap};
|
||||
use rustc_data_structures::undo_log::UndoLogs;
|
||||
use crate::infer::CombinedSnapshot;
|
||||
use rustc_data_structures::{
|
||||
graph::{scc::Sccs, vec_graph::VecGraph},
|
||||
undo_log::UndoLogs,
|
||||
};
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::relate::RelateResult;
|
||||
|
||||
impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
/// Searches region constraints created since `snapshot` that
|
||||
/// affect one of the placeholders in `placeholder_map`, returning
|
||||
/// an error if any of the placeholders are related to another
|
||||
/// placeholder or would have to escape into some parent universe
|
||||
/// that cannot name them.
|
||||
/// Searches new universes created during `snapshot`, looking for
|
||||
/// placeholders that may "leak" out from the universes they are contained
|
||||
/// in. If any leaking placeholders are found, then an `Err` is returned
|
||||
/// (typically leading to the snapshot being reversed).
|
||||
///
|
||||
/// This is a temporary backwards compatibility measure to try and
|
||||
/// retain the older (arguably incorrect) behavior of the
|
||||
/// compiler.
|
||||
/// The leak check *used* to be the only way we had to handle higher-ranked
|
||||
/// obligations. Now that we have integrated universes into the region
|
||||
/// solvers, this is no longer the case, but we retain the leak check for
|
||||
/// backwards compatibility purposes. In particular, it lets us make "early"
|
||||
/// decisions about whether a region error will be reported that are used in
|
||||
/// coherence and elsewhere -- see #56105 and #59490 for more details. The
|
||||
/// eventual fate of the leak checker is not yet settled.
|
||||
///
|
||||
/// NB. Although `_snapshot` isn't used, it's passed in to prove
|
||||
/// that we are in a snapshot, which guarantees that we can just
|
||||
/// search the "undo log" for edges. This is mostly an efficiency
|
||||
/// thing -- we could search *all* region constraints, but that'd be
|
||||
/// a bigger set and the data structures are not setup for that. If
|
||||
/// we wind up keeping some form of this check long term, it would
|
||||
/// probably be better to remove the snapshot parameter and to
|
||||
/// refactor the constraint set.
|
||||
/// The leak checker works by searching for the following error patterns:
|
||||
///
|
||||
/// * P1: P2, where P1 != P2
|
||||
/// * P1: R, where R is in some universe that cannot name P1
|
||||
///
|
||||
/// The idea here is that each of these patterns represents something that
|
||||
/// the region solver would eventually report as an error, so we can detect
|
||||
/// the error early. There is a fly in the ointment, though, in that this is
|
||||
/// not entirely true. In particular, in the future, we may extend the
|
||||
/// environment with implied bounds or other info about how placeholders
|
||||
/// relate to regions in outer universes. In that case, `P1: R` for example
|
||||
/// might become solveable.
|
||||
///
|
||||
/// # Summary of the implementation
|
||||
///
|
||||
/// The leak checks as follows. First, we construct a graph where `R2: R1`
|
||||
/// implies `R2 -> R1`, and we compute the SCCs.
|
||||
///
|
||||
/// For each SCC S, we compute:
|
||||
///
|
||||
/// * what placeholder P it must be equal to, if any
|
||||
/// * if there are multiple placeholders that must be equal, report an error because `P1: P2`
|
||||
/// * the minimum universe of its constituents
|
||||
///
|
||||
/// Then we walk the SCCs in dependency order and compute
|
||||
///
|
||||
/// * what placeholder they must outlive transitively
|
||||
/// * if they must also be equal to a placeholder, report an error because `P1: P2`
|
||||
/// * minimum universe U of all SCCs they must outlive
|
||||
/// * if they must also be equal to a placeholder P, and U cannot name P, report an error, as that
|
||||
/// indicates `P: R` and `R` is in an incompatible universe
|
||||
///
|
||||
/// # Historical note
|
||||
///
|
||||
/// Older variants of the leak check used to report errors for these
|
||||
/// patterns, but we no longer do:
|
||||
///
|
||||
/// * R: P1, even if R cannot name P1, because R = 'static is a valid sol'n
|
||||
/// * R: P1, R: P2, as above
|
||||
pub fn leak_check(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
overly_polymorphic: bool,
|
||||
placeholder_map: &PlaceholderMap<'tcx>,
|
||||
_snapshot: &CombinedSnapshot<'_, 'tcx>,
|
||||
max_universe: ty::UniverseIndex,
|
||||
snapshot: &CombinedSnapshot<'_, 'tcx>,
|
||||
) -> RelateResult<'tcx, ()> {
|
||||
debug!("leak_check(placeholders={:?})", placeholder_map);
|
||||
debug!(
|
||||
"leak_check(max_universe={:?}, snapshot.universe={:?}, overly_polymorphic={:?})",
|
||||
max_universe, snapshot.universe, overly_polymorphic
|
||||
);
|
||||
|
||||
assert!(UndoLogs::<super::UndoLog<'_>>::in_snapshot(&self.undo_log));
|
||||
|
||||
// Go through each placeholder that we created.
|
||||
for &placeholder_region in placeholder_map.values() {
|
||||
// Find the universe this placeholder inhabits.
|
||||
let placeholder = match placeholder_region {
|
||||
ty::RePlaceholder(p) => p,
|
||||
_ => bug!("leak_check: expected placeholder found {:?}", placeholder_region,),
|
||||
};
|
||||
let universe_at_start_of_snapshot = snapshot.universe;
|
||||
if universe_at_start_of_snapshot == max_universe {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Find all regions that are related to this placeholder
|
||||
// in some way. This means any region that either outlives
|
||||
// or is outlived by a placeholder.
|
||||
let mut taint_set = TaintSet::new(TaintDirections::both(), placeholder_region);
|
||||
taint_set.fixed_point(
|
||||
tcx,
|
||||
self.undo_log.region_constraints(),
|
||||
&self.storage.data.verifys,
|
||||
let mini_graph =
|
||||
&MiniGraph::new(tcx, self.undo_log.region_constraints(), &self.storage.data.verifys);
|
||||
|
||||
let mut leak_check = LeakCheck::new(
|
||||
tcx,
|
||||
universe_at_start_of_snapshot,
|
||||
max_universe,
|
||||
overly_polymorphic,
|
||||
mini_graph,
|
||||
self,
|
||||
);
|
||||
leak_check.assign_placeholder_values()?;
|
||||
leak_check.propagate_scc_value()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct LeakCheck<'me, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
universe_at_start_of_snapshot: ty::UniverseIndex,
|
||||
overly_polymorphic: bool,
|
||||
mini_graph: &'me MiniGraph<'tcx>,
|
||||
rcc: &'me RegionConstraintCollector<'me, 'tcx>,
|
||||
|
||||
// Initially, for each SCC S, stores a placeholder `P` such that `S = P`
|
||||
// must hold.
|
||||
//
|
||||
// Later, during the [`LeakCheck::propagate_scc_value`] function, this array
|
||||
// is repurposed to store some placeholder `P` such that the weaker
|
||||
// condition `S: P` must hold. (This is true if `S: S1` transitively and `S1
|
||||
// = P`.)
|
||||
scc_placeholders: IndexVec<LeakCheckScc, Option<ty::PlaceholderRegion>>,
|
||||
|
||||
// For each SCC S, track the minimum universe that flows into it. Note that
|
||||
// this is both the minimum of the universes for every region that is a
|
||||
// member of the SCC, but also if you have `R1: R2`, then the universe of
|
||||
// `R2` must be less than the universe of `R1` (i.e., `R1` flows `R2`). To
|
||||
// see that, imagine that you have `P1: R` -- in that case, `R` must be
|
||||
// either the placeholder `P1` or the empty region in that same universe.
|
||||
//
|
||||
// To detect errors, we look for an SCC S where the values in
|
||||
// `scc_values[S]` (if any) cannot be stored into `scc_universes[S]`.
|
||||
scc_universes: IndexVec<LeakCheckScc, SccUniverse<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
|
||||
fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
universe_at_start_of_snapshot: ty::UniverseIndex,
|
||||
max_universe: ty::UniverseIndex,
|
||||
overly_polymorphic: bool,
|
||||
mini_graph: &'me MiniGraph<'tcx>,
|
||||
rcc: &'me RegionConstraintCollector<'me, 'tcx>,
|
||||
) -> Self {
|
||||
let dummy_scc_universe = SccUniverse { universe: max_universe, region: None };
|
||||
Self {
|
||||
tcx,
|
||||
universe_at_start_of_snapshot,
|
||||
overly_polymorphic,
|
||||
mini_graph,
|
||||
rcc,
|
||||
scc_placeholders: IndexVec::from_elem_n(None, mini_graph.sccs.num_sccs()),
|
||||
scc_universes: IndexVec::from_elem_n(dummy_scc_universe, mini_graph.sccs.num_sccs()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute what placeholders (if any) each SCC must be equal to.
|
||||
/// Also compute the minimum universe of all the regions in each SCC.
|
||||
fn assign_placeholder_values(&mut self) -> RelateResult<'tcx, ()> {
|
||||
// First walk: find each placeholder that is from a newly created universe.
|
||||
for (region, leak_check_node) in &self.mini_graph.nodes {
|
||||
let scc = self.mini_graph.sccs.scc(*leak_check_node);
|
||||
|
||||
// Set the universe of each SCC to be the minimum of its constituent universes
|
||||
let universe = self.rcc.universe(region);
|
||||
debug!(
|
||||
"assign_placeholder_values: scc={:?} universe={:?} region={:?}",
|
||||
scc, universe, region
|
||||
);
|
||||
let tainted_regions = taint_set.into_set();
|
||||
self.scc_universes[scc].take_min(universe, region);
|
||||
|
||||
// Report an error if two placeholders in the same universe
|
||||
// are related to one another, or if a placeholder is related
|
||||
// to something from a parent universe.
|
||||
for &tainted_region in &tainted_regions {
|
||||
if let ty::RePlaceholder(_) = tainted_region {
|
||||
// Two placeholders cannot be related:
|
||||
if tainted_region == placeholder_region {
|
||||
continue;
|
||||
}
|
||||
} else if self.universe(tainted_region).can_name(placeholder.universe) {
|
||||
continue;
|
||||
// Detect those SCCs that directly contain a placeholder
|
||||
if let ty::RePlaceholder(placeholder) = region {
|
||||
if self.universe_at_start_of_snapshot.cannot_name(placeholder.universe) {
|
||||
self.assign_scc_value(scc, *placeholder)?;
|
||||
}
|
||||
|
||||
return Err(if overly_polymorphic {
|
||||
debug!("overly polymorphic!");
|
||||
TypeError::RegionsOverlyPolymorphic(placeholder.name, tainted_region)
|
||||
} else {
|
||||
debug!("not as polymorphic!");
|
||||
TypeError::RegionsInsufficientlyPolymorphic(placeholder.name, tainted_region)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TaintSet<'tcx> {
|
||||
directions: TaintDirections,
|
||||
regions: FxHashSet<ty::Region<'tcx>>,
|
||||
}
|
||||
// assign_scc_value(S, P): Update `scc_values` to account for the fact that `P: S` must hold.
|
||||
// This may create an error.
|
||||
fn assign_scc_value(
|
||||
&mut self,
|
||||
scc: LeakCheckScc,
|
||||
placeholder: ty::PlaceholderRegion,
|
||||
) -> RelateResult<'tcx, ()> {
|
||||
match self.scc_placeholders[scc] {
|
||||
Some(p) => {
|
||||
assert_ne!(p, placeholder);
|
||||
return Err(self.placeholder_error(p, placeholder));
|
||||
}
|
||||
None => {
|
||||
self.scc_placeholders[scc] = Some(placeholder);
|
||||
}
|
||||
};
|
||||
|
||||
impl<'tcx> TaintSet<'tcx> {
|
||||
fn new(directions: TaintDirections, initial_region: ty::Region<'tcx>) -> Self {
|
||||
let mut regions = FxHashSet::default();
|
||||
regions.insert(initial_region);
|
||||
TaintSet { directions, regions }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fixed_point<'a>(
|
||||
&mut self,
|
||||
/// For each SCC S, iterate over each successor S1 where `S: S1`:
|
||||
///
|
||||
/// * Compute
|
||||
/// Iterate over each SCC `S` and ensure that, for each `S1` where `S1: S`,
|
||||
/// `universe(S) <= universe(S1)`. This executes after
|
||||
/// `assign_placeholder_values`, so `universe(S)` is already the minimum
|
||||
/// universe of any of its direct constituents.
|
||||
fn propagate_scc_value(&mut self) -> RelateResult<'tcx, ()> {
|
||||
// Loop invariants:
|
||||
//
|
||||
// On start of the loop iteration for `scc1`:
|
||||
//
|
||||
// * `scc_universes[scc1]` contains the minimum universe of the
|
||||
// constituents of `scc1`
|
||||
// * `scc_placeholder[scc1]` stores the placeholder that `scc1` must
|
||||
// be equal to (if any)
|
||||
//
|
||||
// For each succssor `scc2` where `scc1: scc2`:
|
||||
//
|
||||
// * `scc_placeholder[scc2]` stores some placeholder `P` where
|
||||
// `scc2: P` (if any)
|
||||
// * `scc_universes[scc2]` contains the minimum universe of the
|
||||
// constituents of `scc2` and any of its successors
|
||||
for scc1 in self.mini_graph.sccs.all_sccs() {
|
||||
debug!(
|
||||
"propagate_scc_value: scc={:?} with universe {:?}",
|
||||
scc1, self.scc_universes[scc1]
|
||||
);
|
||||
|
||||
// Walk over each `scc2` such that `scc1: scc2` and compute:
|
||||
//
|
||||
// * `scc1_universe`: the minimum universe of `scc2` and the constituents of `scc1`
|
||||
// * `succ_bound`: placeholder `P` that the successors must outlive, if any (if there are multiple,
|
||||
// we pick one arbitrarily)
|
||||
let mut scc1_universe = self.scc_universes[scc1];
|
||||
let mut succ_bound = None;
|
||||
for &scc2 in self.mini_graph.sccs.successors(scc1) {
|
||||
let SccUniverse { universe: scc2_universe, region: scc2_region } =
|
||||
self.scc_universes[scc2];
|
||||
|
||||
scc1_universe.take_min(scc2_universe, scc2_region.unwrap());
|
||||
|
||||
if let Some(b) = self.scc_placeholders[scc2] {
|
||||
succ_bound = Some(b);
|
||||
}
|
||||
}
|
||||
|
||||
// Update minimum universe of scc1.
|
||||
self.scc_universes[scc1] = scc1_universe;
|
||||
|
||||
// At this point, `scc_placholder[scc1]` stores the placeholder that
|
||||
// `scc1` must be equal to, if any.
|
||||
if let Some(scc1_placeholder) = self.scc_placeholders[scc1] {
|
||||
debug!(
|
||||
"propagate_scc_value: scc1={:?} placeholder={:?} scc1_universe={:?}",
|
||||
scc1, scc1_placeholder, scc1_universe
|
||||
);
|
||||
|
||||
// Check if `P1: R` for some `R` in a universe that cannot name
|
||||
// P1. That's an error.
|
||||
if scc1_universe.universe.cannot_name(scc1_placeholder.universe) {
|
||||
return Err(self.error(scc1_placeholder, scc1_universe.region.unwrap()));
|
||||
}
|
||||
|
||||
// Check if we have some placeholder where `S: P2`
|
||||
// (transitively). In that case, since `S = P1`, that implies
|
||||
// `P1: P2`, which is an error condition.
|
||||
if let Some(scc2_placeholder) = succ_bound {
|
||||
assert_ne!(scc1_placeholder, scc2_placeholder);
|
||||
return Err(self.placeholder_error(scc1_placeholder, scc2_placeholder));
|
||||
}
|
||||
} else {
|
||||
// Otherwise, we can reach a placeholder if some successor can.
|
||||
self.scc_placeholders[scc1] = succ_bound;
|
||||
}
|
||||
|
||||
// At this point, `scc_placeholder[scc1]` stores some placeholder that `scc1` must outlive (if any).
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn placeholder_error(
|
||||
&self,
|
||||
placeholder1: ty::PlaceholderRegion,
|
||||
placeholder2: ty::PlaceholderRegion,
|
||||
) -> TypeError<'tcx> {
|
||||
self.error(placeholder1, self.tcx.mk_region(ty::RePlaceholder(placeholder2)))
|
||||
}
|
||||
|
||||
fn error(
|
||||
&self,
|
||||
placeholder: ty::PlaceholderRegion,
|
||||
other_region: ty::Region<'tcx>,
|
||||
) -> TypeError<'tcx> {
|
||||
debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region);
|
||||
if self.overly_polymorphic {
|
||||
return TypeError::RegionsOverlyPolymorphic(placeholder.name, other_region);
|
||||
} else {
|
||||
return TypeError::RegionsInsufficientlyPolymorphic(placeholder.name, other_region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// States we need to distinguish:
|
||||
//
|
||||
// * must be equal to a placeholder (i.e., a placeholder is in the SCC)
|
||||
// * it could conflict with some other regions in the SCC in different universes
|
||||
// * or a different placeholder
|
||||
// * `P1: S` and `S` must be equal to a placeholder
|
||||
// * `P1: S` and `S` is in an incompatible universe
|
||||
//
|
||||
// So if we
|
||||
//
|
||||
// (a) compute which placeholder (if any) each SCC must be equal to
|
||||
// (b) compute its minimum universe
|
||||
// (c) compute *some* placeholder where `S: P1` (any one will do)
|
||||
//
|
||||
// then we get an error if:
|
||||
//
|
||||
// - it must be equal to a placeholder `P1` and minimum universe cannot name `P1`
|
||||
// - `S: P1` and minimum universe cannot name `P1`
|
||||
// - `S: P1` and we must be equal to `P2`
|
||||
//
|
||||
// So we want to track:
|
||||
//
|
||||
// * Equal placeholder (if any)
|
||||
// * Some bounding placeholder (if any)
|
||||
// * Minimum universe
|
||||
//
|
||||
// * We compute equal placeholder + minimum universe of constituents in first pass
|
||||
// * Then we walk in order and compute from our dependencies `S1` where `S: S1` (`S -> S1`)
|
||||
// * bounding placeholder (if any)
|
||||
// * minimum universe
|
||||
// * And if we must be equal to a placeholder then we check it against
|
||||
// * minimum universe
|
||||
// * no bounding placeholder
|
||||
|
||||
/// Tracks the "minimum universe" for each SCC, along with some region that
|
||||
/// caused it to change.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct SccUniverse<'tcx> {
|
||||
/// For some SCC S, the minimum universe of:
|
||||
///
|
||||
/// * each region R in S
|
||||
/// * each SCC S1 such that S: S1
|
||||
universe: ty::UniverseIndex,
|
||||
|
||||
/// Some region that caused `universe` to be what it is.
|
||||
region: Option<ty::Region<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> SccUniverse<'tcx> {
|
||||
/// If `universe` is less than our current universe, then update
|
||||
/// `self.universe` and `self.region`.
|
||||
fn take_min(&mut self, universe: ty::UniverseIndex, region: ty::Region<'tcx>) {
|
||||
if universe < self.universe || self.region.is_none() {
|
||||
self.universe = universe;
|
||||
self.region = Some(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
struct LeakCheckNode {
|
||||
DEBUG_FORMAT = "LeakCheckNode({})"
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
struct LeakCheckScc {
|
||||
DEBUG_FORMAT = "LeakCheckScc({})"
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the graph of constraints. For each `R1: R2` constraint we create
|
||||
/// an edge `R1 -> R2` in the graph.
|
||||
struct MiniGraph<'tcx> {
|
||||
/// Map from a region to the index of the node in the graph.
|
||||
nodes: FxHashMap<ty::Region<'tcx>, LeakCheckNode>,
|
||||
|
||||
/// Map from node index to SCC, and stores the successors of each SCC. All
|
||||
/// the regions in the same SCC are equal to one another, and if `S1 -> S2`,
|
||||
/// then `S1: S2`.
|
||||
sccs: Sccs<LeakCheckNode, LeakCheckScc>,
|
||||
}
|
||||
|
||||
impl<'tcx> MiniGraph<'tcx> {
|
||||
fn new<'a>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
undo_log: impl IntoIterator<Item = &'a UndoLog<'tcx>> + Clone,
|
||||
undo_log: impl Iterator<Item = &'a UndoLog<'tcx>>,
|
||||
verifys: &[Verify<'tcx>],
|
||||
) -> Self
|
||||
where
|
||||
'tcx: 'a,
|
||||
{
|
||||
let mut nodes = FxHashMap::default();
|
||||
let mut edges = Vec::new();
|
||||
|
||||
// Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter.
|
||||
Self::iterate_undo_log(tcx, undo_log, verifys, |target, source| {
|
||||
let source_node = Self::add_node(&mut nodes, source);
|
||||
let target_node = Self::add_node(&mut nodes, target);
|
||||
edges.push((source_node, target_node));
|
||||
});
|
||||
let graph = VecGraph::new(nodes.len(), edges);
|
||||
let sccs = Sccs::new(&graph);
|
||||
Self { nodes, sccs }
|
||||
}
|
||||
|
||||
/// Invokes `each_edge(R1, R2)` for each edge where `R2: R1`
|
||||
fn iterate_undo_log<'a>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
undo_log: impl Iterator<Item = &'a UndoLog<'tcx>>,
|
||||
verifys: &[Verify<'tcx>],
|
||||
mut each_edge: impl FnMut(ty::Region<'tcx>, ty::Region<'tcx>),
|
||||
) where
|
||||
'tcx: 'a,
|
||||
{
|
||||
let mut prev_len = 0;
|
||||
while prev_len < self.len() {
|
||||
debug!("tainted: prev_len = {:?} new_len = {:?}", prev_len, self.len());
|
||||
|
||||
prev_len = self.len();
|
||||
|
||||
for undo_entry in undo_log.clone() {
|
||||
match undo_entry {
|
||||
&AddConstraint(Constraint::VarSubVar(a, b)) => {
|
||||
self.add_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b)));
|
||||
}
|
||||
&AddConstraint(Constraint::RegSubVar(a, b)) => {
|
||||
self.add_edge(a, tcx.mk_region(ReVar(b)));
|
||||
}
|
||||
&AddConstraint(Constraint::VarSubReg(a, b)) => {
|
||||
self.add_edge(tcx.mk_region(ReVar(a)), b);
|
||||
}
|
||||
&AddConstraint(Constraint::RegSubReg(a, b)) => {
|
||||
self.add_edge(a, b);
|
||||
}
|
||||
&AddGiven(a, b) => {
|
||||
self.add_edge(a, tcx.mk_region(ReVar(b)));
|
||||
}
|
||||
&AddVerify(i) => span_bug!(
|
||||
verifys[i].origin.span(),
|
||||
"we never add verifications while doing higher-ranked things",
|
||||
),
|
||||
&AddCombination(..) | &AddVar(..) => {}
|
||||
for undo_entry in undo_log {
|
||||
match undo_entry {
|
||||
&AddConstraint(Constraint::VarSubVar(a, b)) => {
|
||||
each_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b)));
|
||||
}
|
||||
&AddConstraint(Constraint::RegSubVar(a, b)) => {
|
||||
each_edge(a, tcx.mk_region(ReVar(b)));
|
||||
}
|
||||
&AddConstraint(Constraint::VarSubReg(a, b)) => {
|
||||
each_edge(tcx.mk_region(ReVar(a)), b);
|
||||
}
|
||||
&AddConstraint(Constraint::RegSubReg(a, b)) => {
|
||||
each_edge(a, b);
|
||||
}
|
||||
&AddGiven(a, b) => {
|
||||
each_edge(a, tcx.mk_region(ReVar(b)));
|
||||
}
|
||||
&AddVerify(i) => span_bug!(
|
||||
verifys[i].origin.span(),
|
||||
"we never add verifications while doing higher-ranked things",
|
||||
),
|
||||
&AddCombination(..) | &AddVar(..) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn into_set(self) -> FxHashSet<ty::Region<'tcx>> {
|
||||
self.regions
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.regions.len()
|
||||
}
|
||||
|
||||
fn add_edge(&mut self, source: ty::Region<'tcx>, target: ty::Region<'tcx>) {
|
||||
if self.directions.incoming {
|
||||
if self.regions.contains(&target) {
|
||||
self.regions.insert(source);
|
||||
}
|
||||
}
|
||||
|
||||
if self.directions.outgoing {
|
||||
if self.regions.contains(&source) {
|
||||
self.regions.insert(target);
|
||||
}
|
||||
}
|
||||
fn add_node(
|
||||
nodes: &mut FxHashMap<ty::Region<'tcx>, LeakCheckNode>,
|
||||
r: ty::Region<'tcx>,
|
||||
) -> LeakCheckNode {
|
||||
let l = nodes.len();
|
||||
*nodes.entry(r).or_insert(LeakCheckNode::new(l))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
#![feature(bool_to_option)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_if_match)]
|
||||
#![feature(const_panic)]
|
||||
#![feature(extend_one)]
|
||||
#![feature(never_type)]
|
||||
#![feature(or_patterns)]
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub(super) fn relate_types<'tcx>(
|
|||
category: ConstraintCategory,
|
||||
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
|
||||
) -> Fallible<()> {
|
||||
debug!("eq_types(a={:?}, b={:?}, locations={:?})", a, b, locations);
|
||||
debug!("relate_types(a={:?}, v={:?}, b={:?}, locations={:?})", a, v, b, locations);
|
||||
TypeRelating::new(
|
||||
infcx,
|
||||
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
|
||||
|
|
|
|||
|
|
@ -120,12 +120,13 @@ fn overlap<'cx, 'tcx>(
|
|||
debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id);
|
||||
|
||||
selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| {
|
||||
overlap_within_probe(selcx, a_def_id, b_def_id, snapshot)
|
||||
overlap_within_probe(selcx, skip_leak_check, a_def_id, b_def_id, snapshot)
|
||||
})
|
||||
}
|
||||
|
||||
fn overlap_within_probe(
|
||||
selcx: &mut SelectionContext<'cx, 'tcx>,
|
||||
skip_leak_check: SkipLeakCheck,
|
||||
a_def_id: DefId,
|
||||
b_def_id: DefId,
|
||||
snapshot: &CombinedSnapshot<'_, 'tcx>,
|
||||
|
|
@ -180,6 +181,13 @@ fn overlap_within_probe(
|
|||
return None;
|
||||
}
|
||||
|
||||
if !skip_leak_check.is_yes() {
|
||||
if let Err(_) = infcx.leak_check(true, snapshot) {
|
||||
debug!("overlap: leak check failed");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let impl_header = selcx.infcx().resolve_vars_if_possible(&a_impl_header);
|
||||
let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
|
||||
debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
|
||||
|
|
|
|||
|
|
@ -149,15 +149,12 @@ pub fn poly_project_and_unify_type<'cx, 'tcx>(
|
|||
debug!("poly_project_and_unify_type(obligation={:?})", obligation);
|
||||
|
||||
let infcx = selcx.infcx();
|
||||
infcx.commit_if_ok(|snapshot| {
|
||||
let (placeholder_predicate, placeholder_map) =
|
||||
infcx.commit_if_ok(|_snapshot| {
|
||||
let (placeholder_predicate, _) =
|
||||
infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
|
||||
|
||||
let placeholder_obligation = obligation.with(placeholder_predicate);
|
||||
let result = project_and_unify_type(selcx, &placeholder_obligation)?;
|
||||
infcx
|
||||
.leak_check(false, &placeholder_map, snapshot)
|
||||
.map_err(|err| MismatchedProjectionTypes { err })?;
|
||||
Ok(result)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,9 +163,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
_ => return,
|
||||
}
|
||||
|
||||
let result = self.infcx.probe(|snapshot| {
|
||||
self.match_projection_obligation_against_definition_bounds(obligation, snapshot)
|
||||
});
|
||||
let result = self
|
||||
.infcx
|
||||
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));
|
||||
|
||||
if result {
|
||||
candidates.vec.push(ProjectionCandidate);
|
||||
|
|
@ -345,8 +345,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
obligation.predicate.def_id(),
|
||||
obligation.predicate.skip_binder().trait_ref.self_ty(),
|
||||
|impl_def_id| {
|
||||
self.infcx.probe(|snapshot| {
|
||||
if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot) {
|
||||
self.infcx.probe(|_| {
|
||||
if let Ok(_substs) = self.match_impl(impl_def_id, obligation) {
|
||||
candidates.vec.push(ImplCandidate(impl_def_id));
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -121,9 +121,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
|
||||
self.infcx.commit_unconditionally(|snapshot| {
|
||||
let result =
|
||||
self.match_projection_obligation_against_definition_bounds(obligation, snapshot);
|
||||
self.infcx.commit_unconditionally(|_| {
|
||||
let result = self.match_projection_obligation_against_definition_bounds(obligation);
|
||||
assert!(result);
|
||||
})
|
||||
}
|
||||
|
|
@ -265,8 +264,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
// First, create the substitutions by matching the impl again,
|
||||
// this time not in a probe.
|
||||
self.infcx.commit_unconditionally(|snapshot| {
|
||||
let substs = self.rematch_impl(impl_def_id, obligation, snapshot);
|
||||
self.infcx.commit_unconditionally(|_| {
|
||||
let substs = self.rematch_impl(impl_def_id, obligation);
|
||||
debug!("confirm_impl_candidate: substs={:?}", substs);
|
||||
let cause = obligation.derived_cause(ImplDerivedObligation);
|
||||
ensure_sufficient_stack(|| {
|
||||
|
|
@ -612,24 +611,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
// Require that the traits involved in this upcast are **equal**;
|
||||
// only the **lifetime bound** is changed.
|
||||
//
|
||||
// FIXME: This condition is arguably too strong -- it would
|
||||
// suffice for the source trait to be a *subtype* of the target
|
||||
// trait. In particular, changing from something like
|
||||
// `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be
|
||||
// permitted. And, indeed, in the in commit
|
||||
// 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this
|
||||
// condition was loosened. However, when the leak check was
|
||||
// added back, using subtype here actually guides the coercion
|
||||
// code in such a way that it accepts `old-lub-glb-object.rs`.
|
||||
// This is probably a good thing, but I've modified this to `.eq`
|
||||
// because I want to continue rejecting that test (as we have
|
||||
// done for quite some time) before we are firmly comfortable
|
||||
// with what our behavior should be there. -nikomatsakis
|
||||
let InferOk { obligations, .. } = self
|
||||
.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(target, source_trait) // FIXME -- see below
|
||||
.sup(target, source_trait)
|
||||
.map_err(|_| Unimplemented)?;
|
||||
nested.extend(obligations);
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use super::{Normalized, ProjectionCacheKey};
|
|||
use super::{ObligationCause, PredicateObligation, TraitObligation};
|
||||
use super::{Overflow, SelectionError, Unimplemented};
|
||||
|
||||
use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener};
|
||||
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
|
||||
use crate::traits::error_reporting::InferCtxtExt;
|
||||
use crate::traits::project::ProjectionCacheKeyExt;
|
||||
use rustc_ast::attr;
|
||||
|
|
@ -347,6 +347,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
) -> Result<EvaluationResult, OverflowError> {
|
||||
self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> {
|
||||
let result = op(self)?;
|
||||
|
||||
match self.infcx.leak_check(true, snapshot) {
|
||||
Ok(()) => {}
|
||||
Err(_) => return Ok(EvaluatedToErr),
|
||||
}
|
||||
|
||||
match self.infcx.region_constraints_added_in_snapshot(snapshot) {
|
||||
None => Ok(result),
|
||||
Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)),
|
||||
|
|
@ -1262,10 +1268,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
fn match_projection_obligation_against_definition_bounds(
|
||||
&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
snapshot: &CombinedSnapshot<'_, 'tcx>,
|
||||
) -> bool {
|
||||
let poly_trait_predicate = self.infcx().resolve_vars_if_possible(&obligation.predicate);
|
||||
let (placeholder_trait_predicate, placeholder_map) =
|
||||
let (placeholder_trait_predicate, _) =
|
||||
self.infcx().replace_bound_vars_with_placeholders(&poly_trait_predicate);
|
||||
debug!(
|
||||
"match_projection_obligation_against_definition_bounds: \
|
||||
|
|
@ -1293,13 +1298,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
if let ty::PredicateKind::Trait(bound, _) = bound.kind() {
|
||||
let bound = bound.to_poly_trait_ref();
|
||||
if self.infcx.probe(|_| {
|
||||
self.match_projection(
|
||||
obligation,
|
||||
bound,
|
||||
placeholder_trait_predicate.trait_ref,
|
||||
&placeholder_map,
|
||||
snapshot,
|
||||
)
|
||||
self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref)
|
||||
}) {
|
||||
return Some(bound);
|
||||
}
|
||||
|
|
@ -1316,13 +1315,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
None => false,
|
||||
Some(bound) => {
|
||||
// Repeat the successful match, if any, this time outside of a probe.
|
||||
let result = self.match_projection(
|
||||
obligation,
|
||||
bound,
|
||||
placeholder_trait_predicate.trait_ref,
|
||||
&placeholder_map,
|
||||
snapshot,
|
||||
);
|
||||
let result =
|
||||
self.match_projection(obligation, bound, placeholder_trait_predicate.trait_ref);
|
||||
|
||||
assert!(result);
|
||||
true
|
||||
|
|
@ -1335,15 +1329,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
obligation: &TraitObligation<'tcx>,
|
||||
trait_bound: ty::PolyTraitRef<'tcx>,
|
||||
placeholder_trait_ref: ty::TraitRef<'tcx>,
|
||||
placeholder_map: &PlaceholderMap<'tcx>,
|
||||
snapshot: &CombinedSnapshot<'_, 'tcx>,
|
||||
) -> bool {
|
||||
debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
|
||||
self.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
|
||||
.is_ok()
|
||||
&& self.infcx.leak_check(false, placeholder_map, snapshot).is_ok()
|
||||
}
|
||||
|
||||
fn evaluate_where_clause<'o>(
|
||||
|
|
@ -1808,9 +1799,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
&mut self,
|
||||
impl_def_id: DefId,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
snapshot: &CombinedSnapshot<'_, 'tcx>,
|
||||
) -> Normalized<'tcx, SubstsRef<'tcx>> {
|
||||
match self.match_impl(impl_def_id, obligation, snapshot) {
|
||||
match self.match_impl(impl_def_id, obligation) {
|
||||
Ok(substs) => substs,
|
||||
Err(()) => {
|
||||
bug!(
|
||||
|
|
@ -1826,7 +1816,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
&mut self,
|
||||
impl_def_id: DefId,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
snapshot: &CombinedSnapshot<'_, 'tcx>,
|
||||
) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
|
||||
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
|
||||
|
||||
|
|
@ -1837,7 +1826,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
return Err(());
|
||||
}
|
||||
|
||||
let (placeholder_obligation, placeholder_map) =
|
||||
let (placeholder_obligation, _) =
|
||||
self.infcx().replace_bound_vars_with_placeholders(&obligation.predicate);
|
||||
let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
|
||||
|
||||
|
|
@ -1869,11 +1858,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
.map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
|
||||
nested_obligations.extend(obligations);
|
||||
|
||||
if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) {
|
||||
debug!("match_impl: failed leak check due to `{}`", e);
|
||||
return Err(());
|
||||
}
|
||||
|
||||
if !self.intercrate
|
||||
&& self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
|
||||
{
|
||||
|
|
|
|||
|
|
@ -895,7 +895,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
{
|
||||
let prev_ty = self.resolve_vars_with_obligations(prev_ty);
|
||||
let new_ty = self.resolve_vars_with_obligations(new_ty);
|
||||
debug!("coercion::try_find_coercion_lub({:?}, {:?})", prev_ty, new_ty);
|
||||
debug!(
|
||||
"coercion::try_find_coercion_lub({:?}, {:?}, exprs={:?} exprs)",
|
||||
prev_ty,
|
||||
new_ty,
|
||||
exprs.len()
|
||||
);
|
||||
|
||||
// Special-case that coercion alone cannot handle:
|
||||
// Function items or non-capturing closures of differing IDs or InternalSubsts.
|
||||
|
|
@ -1001,6 +1006,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Ok(ok) => {
|
||||
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,
|
||||
);
|
||||
return Ok(target);
|
||||
}
|
||||
Err(e) => first_error = Some(e),
|
||||
|
|
@ -1031,6 +1040,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
if !noop {
|
||||
debug!(
|
||||
"coercion::try_find_coercion_lub: older expression {:?} had adjustments, requiring LUB",
|
||||
expr,
|
||||
);
|
||||
|
||||
return self
|
||||
.commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty))
|
||||
.map(|ok| self.register_infer_ok_obligations(ok));
|
||||
|
|
@ -1048,6 +1062,10 @@ 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();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
| 8: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:16:12: 16:24
|
||||
| 9: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:16:12: 16:24
|
||||
| 10: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:18:5: 18:18
|
||||
| 11: Canonical { max_universe: U3, variables: [CanonicalVarInfo { kind: Region(U3) }], value: Ty(*const dyn std::marker::Send) } at $DIR/address-of.rs:20:5: 20:25
|
||||
| 11: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*const dyn std::marker::Send) } at $DIR/address-of.rs:20:5: 20:25
|
||||
| 12: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:23:12: 23:20
|
||||
| 13: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*const ^0) } at $DIR/address-of.rs:23:12: 23:20
|
||||
| 14: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32; 10]) } at $DIR/address-of.rs:24:12: 24:28
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
| 18: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:26:12: 26:24
|
||||
| 19: Canonical { max_universe: U0, variables: [], value: Ty(*const [i32]) } at $DIR/address-of.rs:26:12: 26:24
|
||||
| 20: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:28:5: 28:16
|
||||
| 21: Canonical { max_universe: U6, variables: [CanonicalVarInfo { kind: Region(U6) }], value: Ty(*mut dyn std::marker::Send) } at $DIR/address-of.rs:30:5: 30:23
|
||||
| 21: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }], value: Ty(*mut dyn std::marker::Send) } at $DIR/address-of.rs:30:5: 30:23
|
||||
| 22: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:33:12: 33:18
|
||||
| 23: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }], value: Ty(*mut ^0) } at $DIR/address-of.rs:33:12: 33:18
|
||||
| 24: Canonical { max_universe: U0, variables: [], value: Ty(*mut [i32; 10]) } at $DIR/address-of.rs:34:12: 34:26
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
error[E0271]: type mismatch resolving `for<'x> <UintStruct as TheTrait<&'x isize>>::A == &'x isize`
|
||||
--> $DIR/associated-types-eq-hr.rs:87:5
|
||||
|
|
||||
LL | fn foo<T>()
|
||||
| --- required by a bound in this
|
||||
LL | where
|
||||
LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>,
|
||||
| ------------- required by this bound in `foo`
|
||||
...
|
||||
LL | foo::<UintStruct>();
|
||||
| ^^^^^^^^^^^^^^^^^ expected `isize`, found `usize`
|
||||
|
|
||||
= note: expected reference `&isize`
|
||||
found reference `&usize`
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize`
|
||||
--> $DIR/associated-types-eq-hr.rs:91:5
|
||||
|
|
||||
LL | fn bar<T>()
|
||||
| --- required by a bound in this
|
||||
LL | where
|
||||
LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>,
|
||||
| ------------- required by this bound in `bar`
|
||||
...
|
||||
LL | bar::<IntStruct>();
|
||||
| ^^^^^^^^^^^^^^^^ expected `usize`, found `isize`
|
||||
|
|
||||
= note: expected reference `&usize`
|
||||
found reference `&isize`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
|
|
@ -7,7 +7,7 @@ pub trait TheTrait<T> {
|
|||
}
|
||||
|
||||
struct IntStruct {
|
||||
x: isize
|
||||
x: isize,
|
||||
}
|
||||
|
||||
impl<'a> TheTrait<&'a isize> for IntStruct {
|
||||
|
|
@ -19,7 +19,7 @@ impl<'a> TheTrait<&'a isize> for IntStruct {
|
|||
}
|
||||
|
||||
struct UintStruct {
|
||||
x: isize
|
||||
x: isize,
|
||||
}
|
||||
|
||||
impl<'a> TheTrait<&'a isize> for UintStruct {
|
||||
|
|
@ -30,8 +30,7 @@ impl<'a> TheTrait<&'a isize> for UintStruct {
|
|||
}
|
||||
}
|
||||
|
||||
struct Tuple {
|
||||
}
|
||||
struct Tuple {}
|
||||
|
||||
impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple {
|
||||
type A = &'a isize;
|
||||
|
|
@ -42,37 +41,43 @@ impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple {
|
|||
}
|
||||
|
||||
fn foo<T>()
|
||||
where T : for<'x> TheTrait<&'x isize, A = &'x isize>
|
||||
where
|
||||
T: for<'x> TheTrait<&'x isize, A = &'x isize>,
|
||||
{
|
||||
// ok for IntStruct, but not UintStruct
|
||||
}
|
||||
|
||||
fn bar<T>()
|
||||
where T : for<'x> TheTrait<&'x isize, A = &'x usize>
|
||||
where
|
||||
T: for<'x> TheTrait<&'x isize, A = &'x usize>,
|
||||
{
|
||||
// ok for UintStruct, but not IntStruct
|
||||
}
|
||||
|
||||
fn tuple_one<T>()
|
||||
where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
|
||||
where
|
||||
T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>,
|
||||
{
|
||||
// not ok for tuple, two lifetimes and we pick first
|
||||
}
|
||||
|
||||
fn tuple_two<T>()
|
||||
where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
|
||||
where
|
||||
T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>,
|
||||
{
|
||||
// not ok for tuple, two lifetimes and we pick second
|
||||
}
|
||||
|
||||
fn tuple_three<T>()
|
||||
where T : for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize>
|
||||
where
|
||||
T: for<'x> TheTrait<(&'x isize, &'x isize), A = &'x isize>,
|
||||
{
|
||||
// ok for tuple
|
||||
}
|
||||
|
||||
fn tuple_four<T>()
|
||||
where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)>
|
||||
where
|
||||
T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>,
|
||||
{
|
||||
// not ok for tuple, two lifetimes, and lifetime matching is invariant
|
||||
}
|
||||
|
|
@ -89,14 +94,14 @@ pub fn call_bar() {
|
|||
|
||||
pub fn call_tuple_one() {
|
||||
tuple_one::<Tuple>();
|
||||
//~^ ERROR not satisfied
|
||||
//~| ERROR type mismatch
|
||||
//~^ ERROR implementation of `TheTrait` is not general enough
|
||||
//~| ERROR implementation of `TheTrait` is not general enough
|
||||
}
|
||||
|
||||
pub fn call_tuple_two() {
|
||||
tuple_two::<Tuple>();
|
||||
//~^ ERROR not satisfied
|
||||
//~| ERROR type mismatch
|
||||
//~^ ERROR implementation of `TheTrait` is not general enough
|
||||
//~| ERROR implementation of `TheTrait` is not general enough
|
||||
}
|
||||
|
||||
pub fn call_tuple_three() {
|
||||
|
|
@ -105,7 +110,7 @@ pub fn call_tuple_three() {
|
|||
|
||||
pub fn call_tuple_four() {
|
||||
tuple_four::<Tuple>();
|
||||
//~^ ERROR not satisfied
|
||||
//~^ ERROR implementation of `TheTrait` is not general enough
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
error[E0271]: type mismatch resolving `for<'x> <UintStruct as TheTrait<&'x isize>>::A == &'x isize`
|
||||
--> $DIR/associated-types-eq-hr.rs:82:5
|
||||
--> $DIR/associated-types-eq-hr.rs:87:5
|
||||
|
|
||||
LL | fn foo<T>()
|
||||
| --- required by a bound in this
|
||||
LL | where T : for<'x> TheTrait<&'x isize, A = &'x isize>
|
||||
| ------------- required by this bound in `foo`
|
||||
LL | where
|
||||
LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>,
|
||||
| ------------- required by this bound in `foo`
|
||||
...
|
||||
LL | foo::<UintStruct>();
|
||||
| ^^^^^^^^^^^^^^^^^ expected `isize`, found `usize`
|
||||
|
|
@ -13,12 +14,13 @@ LL | foo::<UintStruct>();
|
|||
found reference `&usize`
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize`
|
||||
--> $DIR/associated-types-eq-hr.rs:86:5
|
||||
--> $DIR/associated-types-eq-hr.rs:91:5
|
||||
|
|
||||
LL | fn bar<T>()
|
||||
| --- required by a bound in this
|
||||
LL | where T : for<'x> TheTrait<&'x isize, A = &'x usize>
|
||||
| ------------- required by this bound in `bar`
|
||||
LL | where
|
||||
LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>,
|
||||
| ------------- required by this bound in `bar`
|
||||
...
|
||||
LL | bar::<IntStruct>();
|
||||
| ^^^^^^^^^^^^^^^^ expected `usize`, found `isize`
|
||||
|
|
@ -26,71 +28,86 @@ LL | bar::<IntStruct>();
|
|||
= note: expected reference `&usize`
|
||||
found reference `&isize`
|
||||
|
||||
error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
|
||||
--> $DIR/associated-types-eq-hr.rs:91:17
|
||||
error: implementation of `TheTrait` is not general enough
|
||||
--> $DIR/associated-types-eq-hr.rs:96:5
|
||||
|
|
||||
LL | fn tuple_one<T>()
|
||||
| --------- required by a bound in this
|
||||
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
|
||||
| ---------------------------------------------------------- required by this bound in `tuple_one`
|
||||
LL | / pub trait TheTrait<T> {
|
||||
LL | | type A;
|
||||
LL | |
|
||||
LL | | fn get(&self, t: T) -> Self::A;
|
||||
LL | | }
|
||||
| |_- trait `TheTrait` defined here
|
||||
...
|
||||
LL | tuple_one::<Tuple>();
|
||||
| ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
|
||||
LL | tuple_one::<Tuple>();
|
||||
| ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<Tuple as TheTrait<(&'a isize, &'a isize)>>
|
||||
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
|
||||
= note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'x isize`
|
||||
--> $DIR/associated-types-eq-hr.rs:91:5
|
||||
error: implementation of `TheTrait` is not general enough
|
||||
--> $DIR/associated-types-eq-hr.rs:96:5
|
||||
|
|
||||
LL | fn tuple_one<T>()
|
||||
| --------- required by a bound in this
|
||||
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>
|
||||
| ------------- required by this bound in `tuple_one`
|
||||
LL | / pub trait TheTrait<T> {
|
||||
LL | | type A;
|
||||
LL | |
|
||||
LL | | fn get(&self, t: T) -> Self::A;
|
||||
LL | | }
|
||||
| |_- trait `TheTrait` defined here
|
||||
...
|
||||
LL | tuple_one::<Tuple>();
|
||||
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
|
||||
LL | tuple_one::<Tuple>();
|
||||
| ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough
|
||||
|
|
||||
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
|
||||
= note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
|
||||
|
||||
error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
|
||||
--> $DIR/associated-types-eq-hr.rs:97:17
|
||||
error: implementation of `TheTrait` is not general enough
|
||||
--> $DIR/associated-types-eq-hr.rs:102:5
|
||||
|
|
||||
LL | fn tuple_two<T>()
|
||||
| --------- required by a bound in this
|
||||
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
|
||||
| ---------------------------------------------------------- required by this bound in `tuple_two`
|
||||
LL | / pub trait TheTrait<T> {
|
||||
LL | | type A;
|
||||
LL | |
|
||||
LL | | fn get(&self, t: T) -> Self::A;
|
||||
LL | | }
|
||||
| |_- trait `TheTrait` defined here
|
||||
...
|
||||
LL | tuple_two::<Tuple>();
|
||||
| ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
|
||||
LL | tuple_two::<Tuple>();
|
||||
| ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<Tuple as TheTrait<(&'a isize, &'a isize)>>
|
||||
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
|
||||
= note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'x, 'y> <Tuple as TheTrait<(&'x isize, &'y isize)>>::A == &'y isize`
|
||||
--> $DIR/associated-types-eq-hr.rs:97:5
|
||||
error: implementation of `TheTrait` is not general enough
|
||||
--> $DIR/associated-types-eq-hr.rs:102:5
|
||||
|
|
||||
LL | fn tuple_two<T>()
|
||||
| --------- required by a bound in this
|
||||
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>
|
||||
| ------------- required by this bound in `tuple_two`
|
||||
LL | / pub trait TheTrait<T> {
|
||||
LL | | type A;
|
||||
LL | |
|
||||
LL | | fn get(&self, t: T) -> Self::A;
|
||||
LL | | }
|
||||
| |_- trait `TheTrait` defined here
|
||||
...
|
||||
LL | tuple_two::<Tuple>();
|
||||
| ^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
|
||||
LL | tuple_two::<Tuple>();
|
||||
| ^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough
|
||||
|
|
||||
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
|
||||
= note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
|
||||
|
||||
error[E0277]: the trait bound `for<'x, 'y> Tuple: TheTrait<(&'x isize, &'y isize)>` is not satisfied
|
||||
--> $DIR/associated-types-eq-hr.rs:107:18
|
||||
error: implementation of `TheTrait` is not general enough
|
||||
--> $DIR/associated-types-eq-hr.rs:112:5
|
||||
|
|
||||
LL | fn tuple_four<T>()
|
||||
| ---------- required by a bound in this
|
||||
LL | where T : for<'x,'y> TheTrait<(&'x isize, &'y isize)>
|
||||
| ------------------------------------------- required by this bound in `tuple_four`
|
||||
LL | / pub trait TheTrait<T> {
|
||||
LL | | type A;
|
||||
LL | |
|
||||
LL | | fn get(&self, t: T) -> Self::A;
|
||||
LL | | }
|
||||
| |_- trait `TheTrait` defined here
|
||||
...
|
||||
LL | tuple_four::<Tuple>();
|
||||
| ^^^^^ the trait `for<'x, 'y> TheTrait<(&'x isize, &'y isize)>` is not implemented for `Tuple`
|
||||
LL | tuple_four::<Tuple>();
|
||||
| ^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<Tuple as TheTrait<(&'a isize, &'a isize)>>
|
||||
= note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
|
||||
= note: ...but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0277.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
error: lifetime may not live long enough
|
||||
--> $DIR/project-fn-ret-invariant.rs:55:4
|
||||
--> $DIR/project-fn-ret-invariant.rs:56:5
|
||||
|
|
||||
LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | (a, b)
|
||||
| ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
||||
LL | (a, b)
|
||||
| ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'b`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/project-fn-ret-invariant.rs:55:4
|
||||
--> $DIR/project-fn-ret-invariant.rs:56:5
|
||||
|
|
||||
LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | (a, b)
|
||||
| ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
||||
LL | (a, b)
|
||||
| ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/project-fn-ret-invariant.rs:53:21
|
||||
--> $DIR/project-fn-ret-invariant.rs:54:22
|
||||
|
|
||||
LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -------- --------------------
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | let a = bar(foo, y);
|
||||
| ^ ...but data from `x` is returned here
|
||||
LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -------- --------------------
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | let a = bar(foo, y);
|
||||
| ^ ...but data from `x` is returned here
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/project-fn-ret-invariant.rs:54:21
|
||||
--> $DIR/project-fn-ret-invariant.rs:56:9
|
||||
|
|
||||
LL | fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -------- --------------------
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | let a = bar(foo, y);
|
||||
LL | let b = bar(foo, x);
|
||||
| ^ ...but data from `y` is returned here
|
||||
LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -------- --------------------
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
...
|
||||
LL | (a, b)
|
||||
| ^ ...but data from `x` is returned here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/project-fn-ret-invariant.rs:59:1
|
||||
--> $DIR/project-fn-ret-invariant.rs:60:1
|
||||
|
|
||||
LL | fn main() { }
|
||||
| ^^^^^^^^^^^^^
|
||||
LL | fn main() {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
error: lifetime may not live long enough
|
||||
--> $DIR/project-fn-ret-invariant.rs:38:12
|
||||
--> $DIR/project-fn-ret-invariant.rs:39:13
|
||||
|
|
||||
LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
LL | let f = foo; // <-- No consistent type can be inferred for `f` here.
|
||||
LL | let a = bar(f, x);
|
||||
| ^^^^^^^^^ argument requires that `'a` must outlive `'b`
|
||||
LL | let f = foo; // <-- No consistent type can be inferred for `f` here.
|
||||
LL | let a = bar(f, x);
|
||||
| ^^^^^^^^^ argument requires that `'a` must outlive `'b`
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'b`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/project-fn-ret-invariant.rs:39:12
|
||||
--> $DIR/project-fn-ret-invariant.rs:40:13
|
||||
|
|
||||
LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | let b = bar(f, y);
|
||||
| ^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
||||
LL | let b = bar(f, y);
|
||||
| ^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'b: 'a`
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/project-fn-ret-invariant.rs:39:19
|
||||
--> $DIR/project-fn-ret-invariant.rs:40:20
|
||||
|
|
||||
LL | fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -------- --------------------
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
| -------- --------------------
|
||||
| |
|
||||
| this parameter and the return type are declared with different lifetimes...
|
||||
...
|
||||
LL | let b = bar(f, y);
|
||||
| ^ ...but data from `x` is returned here
|
||||
LL | let b = bar(f, y);
|
||||
| ^ ...but data from `x` is returned here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,60 +1,61 @@
|
|||
#![feature(unboxed_closures)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
// Test for projection cache. We should be able to project distinct
|
||||
// lifetimes from `foo` as we reinstantiate it multiple times, but not
|
||||
// if we do it just once. In this variant, the region `'a` is used in
|
||||
// an invariant position, which affects the results.
|
||||
|
||||
// revisions: ok oneuse transmute krisskross
|
||||
|
||||
#![allow(dead_code, unused_variables)]
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Type<'a> {
|
||||
// Invariant
|
||||
data: PhantomData<fn(&'a u32) -> &'a u32>
|
||||
data: PhantomData<fn(&'a u32) -> &'a u32>,
|
||||
}
|
||||
|
||||
fn foo<'a>() -> Type<'a> { loop { } }
|
||||
fn foo<'a>() -> Type<'a> {
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn bar<T>(t: T, x: T::Output) -> T::Output
|
||||
where T: FnOnce<()>
|
||||
where
|
||||
T: FnOnce<()>,
|
||||
{
|
||||
t()
|
||||
}
|
||||
|
||||
#[cfg(ok)] // two instantiations: OK
|
||||
fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
let a = bar(foo, x);
|
||||
let b = bar(foo, y);
|
||||
(a, b)
|
||||
}
|
||||
|
||||
#[cfg(oneuse)] // one instantiation: BAD
|
||||
fn baz<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
let f = foo; // <-- No consistent type can be inferred for `f` here.
|
||||
let a = bar(f, x);
|
||||
let b = bar(f, y); //[oneuse]~ ERROR lifetime mismatch [E0623]
|
||||
(a, b)
|
||||
fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
let f = foo; // <-- No consistent type can be inferred for `f` here.
|
||||
let a = bar(f, x);
|
||||
let b = bar(f, y); //[oneuse]~ ERROR lifetime mismatch [E0623]
|
||||
(a, b)
|
||||
}
|
||||
|
||||
#[cfg(transmute)] // one instantiations: BAD
|
||||
fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
|
||||
// Cannot instantiate `foo` with any lifetime other than `'a`,
|
||||
// since it is provided as input.
|
||||
fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
|
||||
// Cannot instantiate `foo` with any lifetime other than `'a`,
|
||||
// since it is provided as input.
|
||||
|
||||
bar(foo, x) //[transmute]~ ERROR E0495
|
||||
bar(foo, x) //[transmute]~ ERROR E0495
|
||||
}
|
||||
|
||||
#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
|
||||
fn transmute<'a,'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
let a = bar(foo, y); //[krisskross]~ ERROR E0623
|
||||
let b = bar(foo, x); //[krisskross]~ ERROR E0623
|
||||
(a, b)
|
||||
fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||
let a = bar(foo, y); //[krisskross]~ ERROR E0623
|
||||
let b = bar(foo, x);
|
||||
(a, b) //[krisskross]~ ERROR E0623
|
||||
}
|
||||
|
||||
#[rustc_error]
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
//[ok]~^ ERROR fatal error triggered by #[rustc_error]
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error: lifetime may not live long enough
|
||||
--> $DIR/project-fn-ret-invariant.rs:48:4
|
||||
--> $DIR/project-fn-ret-invariant.rs:49:5
|
||||
|
|
||||
LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
|
||||
LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
|
||||
| -- lifetime `'a` defined here
|
||||
...
|
||||
LL | bar(foo, x)
|
||||
| ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
||||
LL | bar(foo, x)
|
||||
| ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
||||
|
|
||||
= help: consider replacing `'a` with `'static`
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +1,27 @@
|
|||
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
|
||||
--> $DIR/project-fn-ret-invariant.rs:48:4
|
||||
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
|
||||
--> $DIR/project-fn-ret-invariant.rs:49:9
|
||||
|
|
||||
LL | bar(foo, x)
|
||||
| ^^^^^^^^^^^
|
||||
LL | bar(foo, x)
|
||||
| ^^^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 44:8...
|
||||
--> $DIR/project-fn-ret-invariant.rs:44:8
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 45:8...
|
||||
--> $DIR/project-fn-ret-invariant.rs:45:8
|
||||
|
|
||||
LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> {
|
||||
LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
|
||||
| ^^
|
||||
note: ...so that the expression is assignable
|
||||
--> $DIR/project-fn-ret-invariant.rs:48:13
|
||||
--> $DIR/project-fn-ret-invariant.rs:49:14
|
||||
|
|
||||
LL | bar(foo, x)
|
||||
| ^
|
||||
LL | bar(foo, x)
|
||||
| ^
|
||||
= note: expected `Type<'_>`
|
||||
found `Type<'a>`
|
||||
= note: but, the lifetime must be valid for the static lifetime...
|
||||
note: ...so that the expression is assignable
|
||||
--> $DIR/project-fn-ret-invariant.rs:48:4
|
||||
--> $DIR/project-fn-ret-invariant.rs:49:5
|
||||
|
|
||||
LL | bar(foo, x)
|
||||
| ^^^^^^^^^^^
|
||||
LL | bar(foo, x)
|
||||
| ^^^^^^^^^^^
|
||||
= note: expected `Type<'static>`
|
||||
found `Type<'_>`
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/higher-ranked-projection.rs:25:5
|
||||
|
|
||||
LL | foo(());
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -1,14 +1,12 @@
|
|||
error[E0271]: type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _`
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/higher-ranked-projection.rs:25:5
|
||||
|
|
||||
LL | fn foo<U, T>(_t: T)
|
||||
| --- required by a bound in this
|
||||
LL | where for<'a> &'a T: Mirror<Image=U>
|
||||
| ------- required by this bound in `foo`
|
||||
...
|
||||
LL | foo(());
|
||||
| ^^^ expected bound lifetime parameter 'a, found concrete lifetime
|
||||
| ^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected type `&'a ()`
|
||||
found type `&()`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -23,5 +23,5 @@ fn foo<U, T>(_t: T)
|
|||
#[rustc_error]
|
||||
fn main() { //[good]~ ERROR fatal error triggered by #[rustc_error]
|
||||
foo(());
|
||||
//[bad]~^ ERROR type mismatch
|
||||
//[bad]~^ ERROR mismatched types
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,42 +1,43 @@
|
|||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/expect-fn-supply-fn.rs:30:5
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/expect-fn-supply-fn.rs:16:49
|
||||
|
|
||||
LL | fn with_closure_expecting_fn_with_free_region<F>(_: F)
|
||||
| ------------------------------------------ required by a bound in this
|
||||
LL | where F: for<'a> FnOnce(fn(&'a u32), &i32)
|
||||
| ------------------------- required by this bound in `with_closure_expecting_fn_with_free_region`
|
||||
LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
|
||||
| -- lifetime `'x` defined here
|
||||
...
|
||||
LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
|
||||
| ^
|
||||
| |
|
||||
| has type `fn(&'1 u32)`
|
||||
| requires that `'1` must outlive `'x`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/expect-fn-supply-fn.rs:16:49
|
||||
|
|
||||
LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
|
||||
| -- lifetime `'x` defined here
|
||||
...
|
||||
LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
|
||||
| ^ requires that `'x` must outlive `'static`
|
||||
|
|
||||
= help: consider replacing `'x` with `'static`
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/expect-fn-supply-fn.rs:32:49
|
||||
|
|
||||
LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _`
|
||||
| |
|
||||
| expected signature of `fn(fn(&'a u32), &i32) -> _`
|
||||
| ^
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/expect-fn-supply-fn.rs:37:5
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/expect-fn-supply-fn.rs:39:50
|
||||
|
|
||||
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
|
||||
| ------------------------------------------- required by a bound in this
|
||||
LL | where F: FnOnce(fn(&u32), &i32)
|
||||
| ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region`
|
||||
...
|
||||
LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _`
|
||||
| |
|
||||
| expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
|
||||
| ^
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/expect-fn-supply-fn.rs:46:5
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/expect-fn-supply-fn.rs:48:50
|
||||
|
|
||||
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
|
||||
| ------------------------------------------- required by a bound in this
|
||||
LL | where F: FnOnce(fn(&u32), &i32)
|
||||
| ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region`
|
||||
...
|
||||
LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _`
|
||||
| |
|
||||
| expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
|
||||
| ^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0631`.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
fn with_closure_expecting_fn_with_free_region<F>(_: F)
|
||||
where F: for<'a> FnOnce(fn(&'a u32), &i32)
|
||||
where
|
||||
F: for<'a> FnOnce(fn(&'a u32), &i32),
|
||||
{
|
||||
}
|
||||
|
||||
fn with_closure_expecting_fn_with_bound_region<F>(_: F)
|
||||
where F: FnOnce(fn(&u32), &i32)
|
||||
where
|
||||
F: FnOnce(fn(&u32), &i32),
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -28,14 +30,14 @@ fn expect_free_supply_bound() {
|
|||
// Here, we are given a function whose region is bound at closure level,
|
||||
// but we expect one bound in the argument. Error results.
|
||||
with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
|
||||
//~^ ERROR type mismatch
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) {
|
||||
// Here, we are given a `fn(&u32)` but we expect a `fn(&'x
|
||||
// u32)`. In principle, this could be ok, but we demand equality.
|
||||
with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
|
||||
//~^ ERROR type mismatch
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn expect_bound_supply_free_from_closure() {
|
||||
|
|
@ -44,7 +46,7 @@ fn expect_bound_supply_free_from_closure() {
|
|||
// the argument level.
|
||||
type Foo<'a> = fn(&'a u32);
|
||||
with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
|
||||
//~^ ERROR type mismatch
|
||||
//~^ ERROR mismatched types
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -52,8 +54,7 @@ fn expect_bound_supply_bound<'x>(x: &'x u32) {
|
|||
// No error in this case. The supplied type supplies the bound
|
||||
// regions, and hence we are able to figure out the type of `y`
|
||||
// from the expected type
|
||||
with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| {
|
||||
});
|
||||
with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| {});
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,81 +1,68 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/expect-fn-supply-fn.rs:14:52
|
||||
--> $DIR/expect-fn-supply-fn.rs:16:52
|
||||
|
|
||||
LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
|
||||
| ^^^^^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected fn pointer `fn(&u32)`
|
||||
found fn pointer `fn(&'x u32)`
|
||||
note: the anonymous lifetime #2 defined on the body at 14:48...
|
||||
--> $DIR/expect-fn-supply-fn.rs:14:48
|
||||
note: the anonymous lifetime #2 defined on the body at 16:48...
|
||||
--> $DIR/expect-fn-supply-fn.rs:16:48
|
||||
|
|
||||
LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 11:36
|
||||
--> $DIR/expect-fn-supply-fn.rs:11:36
|
||||
note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 13:36
|
||||
--> $DIR/expect-fn-supply-fn.rs:13:36
|
||||
|
|
||||
LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
|
||||
| ^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expect-fn-supply-fn.rs:14:52
|
||||
--> $DIR/expect-fn-supply-fn.rs:16:52
|
||||
|
|
||||
LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
|
||||
| ^^^^^^^^^^^ lifetime mismatch
|
||||
|
|
||||
= note: expected fn pointer `fn(&u32)`
|
||||
found fn pointer `fn(&'x u32)`
|
||||
note: the lifetime `'x` as defined on the function body at 11:36...
|
||||
--> $DIR/expect-fn-supply-fn.rs:11:36
|
||||
note: the lifetime `'x` as defined on the function body at 13:36...
|
||||
--> $DIR/expect-fn-supply-fn.rs:13:36
|
||||
|
|
||||
LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
|
||||
| ^^
|
||||
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 14:48
|
||||
--> $DIR/expect-fn-supply-fn.rs:14:48
|
||||
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 16:48
|
||||
--> $DIR/expect-fn-supply-fn.rs:16:48
|
||||
|
|
||||
LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/expect-fn-supply-fn.rs:30:5
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expect-fn-supply-fn.rs:32:52
|
||||
|
|
||||
LL | fn with_closure_expecting_fn_with_free_region<F>(_: F)
|
||||
| ------------------------------------------ required by a bound in this
|
||||
LL | where F: for<'a> FnOnce(fn(&'a u32), &i32)
|
||||
| ------------------------- required by this bound in `with_closure_expecting_fn_with_free_region`
|
||||
...
|
||||
LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _`
|
||||
| |
|
||||
| expected signature of `fn(fn(&'a u32), &i32) -> _`
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/expect-fn-supply-fn.rs:37:5
|
||||
| ^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `fn(&u32)`
|
||||
found fn pointer `for<'r> fn(&'r u32)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expect-fn-supply-fn.rs:39:53
|
||||
|
|
||||
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
|
||||
| ------------------------------------------- required by a bound in this
|
||||
LL | where F: FnOnce(fn(&u32), &i32)
|
||||
| ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region`
|
||||
...
|
||||
LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _`
|
||||
| |
|
||||
| expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/expect-fn-supply-fn.rs:46:5
|
||||
| ^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r> fn(&'r u32)`
|
||||
found fn pointer `fn(&'x u32)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/expect-fn-supply-fn.rs:48:53
|
||||
|
|
||||
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
|
||||
| ------------------------------------------- required by a bound in this
|
||||
LL | where F: FnOnce(fn(&u32), &i32)
|
||||
| ---------------------- required by this bound in `with_closure_expecting_fn_with_bound_region`
|
||||
...
|
||||
LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(fn(&'r u32), _) -> _`
|
||||
| |
|
||||
| expected signature of `fn(for<'r> fn(&'r u32), &i32) -> _`
|
||||
| ^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'r> fn(&'r u32)`
|
||||
found fn pointer `fn(&u32)`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0631.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ impl<'g> T<'g> for u32 {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
(&|_|()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
|
||||
(&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
|
||||
//~^ ERROR: type mismatch in closure arguments
|
||||
//~| ERROR: type mismatch resolving
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,14 @@
|
|||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/issue-41366.rs:10:5
|
||||
|
|
||||
LL | (&|_|()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
|
||||
| ^^-----^
|
||||
LL | (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
|
||||
| ^^------^
|
||||
| | |
|
||||
| | found signature of `fn(_) -> _`
|
||||
| expected signature of `for<'x> fn(<u32 as T<'x>>::V) -> _`
|
||||
| | found signature of `fn(u16) -> _`
|
||||
| expected signature of `fn(<u32 as T<'x>>::V) -> _`
|
||||
|
|
||||
= note: required for the cast to the object type `dyn for<'x> std::ops::Fn(<u32 as T<'x>>::V)`
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'x> <[closure@$DIR/issue-41366.rs:10:7: 10:12] as std::ops::FnOnce<(<u32 as T<'x>>::V,)>>::Output == ()`
|
||||
--> $DIR/issue-41366.rs:10:5
|
||||
|
|
||||
LL | (&|_|()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
|
||||
| ^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime
|
||||
|
|
||||
= note: required for the cast to the object type `dyn for<'x> std::ops::Fn(<u32 as T<'x>>::V)`
|
||||
error: aborting due to previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0631.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
For more information about this error, try `rustc --explain E0631`.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
// Test that impls for these two types are considered ovelapping:
|
||||
//
|
||||
// * `for<'r> fn(fn(&'r u32))`
|
||||
// * `fn(fn(&'a u32)` where `'a` is free
|
||||
//
|
||||
// This is because, for `'a = 'static`, the two types overlap.
|
||||
// Effectively for them to be equal to you get:
|
||||
//
|
||||
// * `for<'r> fn(fn(&'r u32)) <: fn(fn(&'static u32))`
|
||||
// * true if `exists<'r> { 'r: 'static }` (obviously true)
|
||||
// * `fn(fn(&'static u32)) <: for<'r> fn(fn(&'r u32))`
|
||||
// * true if `forall<'r> { 'static: 'r }` (also true)
|
||||
|
||||
trait Trait {}
|
||||
|
||||
impl Trait for for<'r> fn(fn(&'r ())) {}
|
||||
impl<'a> Trait for fn(fn(&'a ())) {}
|
||||
//~^ ERROR conflicting implementations
|
||||
//
|
||||
// Note in particular that we do NOT get a future-compatibility warning
|
||||
// here. This is because the new leak-check proposed in [MCP 295] does not
|
||||
// "error" when these two types are equated.
|
||||
//
|
||||
// [MCP 295]: https://github.com/rust-lang/compiler-team/issues/295
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`:
|
||||
--> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1
|
||||
|
|
||||
LL | impl Trait for for<'r> fn(fn(&'r ())) {}
|
||||
| ------------------------------------- first implementation here
|
||||
LL | impl<'a> Trait for fn(fn(&'a ())) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))`
|
||||
|
|
||||
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
26
src/test/ui/coherence/coherence-fn-implied-bounds.rs
Normal file
26
src/test/ui/coherence/coherence-fn-implied-bounds.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Test that our leak-check is not smart enough to take implied bounds
|
||||
// into account (yet). Here we have two types that look like they
|
||||
// should not be equivalent, but because of the rules on implied
|
||||
// bounds we ought to know that, in fact, `'a = 'b` must always hold,
|
||||
// and hence they are.
|
||||
//
|
||||
// Rustc can't figure this out and hence it accepts the impls but
|
||||
// gives a future-compatibility warning (because we'd like to make
|
||||
// this an error someday).
|
||||
//
|
||||
// Note that while we would like to make this a hard error, we also
|
||||
// give the same warning for `coherence-wasm-bindgen.rs`, which ought
|
||||
// to be accepted.
|
||||
|
||||
#![deny(coherence_leak_check)]
|
||||
|
||||
trait Trait {}
|
||||
|
||||
impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {}
|
||||
|
||||
impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 {
|
||||
//~^ ERROR conflicting implementations
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
20
src/test/ui/coherence/coherence-fn-implied-bounds.stderr
Normal file
20
src/test/ui/coherence/coherence-fn-implied-bounds.stderr
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
error: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32`:
|
||||
--> $DIR/coherence-fn-implied-bounds.rs:21:1
|
||||
|
|
||||
LL | impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {}
|
||||
| ------------------------------------------------------------------ first implementation here
|
||||
LL |
|
||||
LL | impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/coherence-fn-implied-bounds.rs:15:9
|
||||
|
|
||||
LL | #![deny(coherence_leak_check)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
|
||||
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
25
src/test/ui/coherence/coherence-fn-inputs.rs
Normal file
25
src/test/ui/coherence/coherence-fn-inputs.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Test that we consider these two types completely equal:
|
||||
//
|
||||
// * `for<'a, 'b> fn(&'a u32, &'b u32)`
|
||||
// * `for<'c> fn(&'c u32, &'c u32)`
|
||||
//
|
||||
// For a long time we considered these to be distinct types. But in fact they
|
||||
// are equivalent, if you work through the implications of subtyping -- this is
|
||||
// because:
|
||||
//
|
||||
// * `'c` can be the intersection of `'a` and `'b` (and there is always an intersection)
|
||||
// * `'a` and `'b` can both be equal to `'c`
|
||||
|
||||
trait Trait {}
|
||||
impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {}
|
||||
impl Trait for for<'c> fn(&'c u32, &'c u32) {
|
||||
//~^ ERROR conflicting implementations
|
||||
//
|
||||
// Note in particular that we do NOT get a future-compatibility warning
|
||||
// here. This is because the new leak-check proposed in [MCP 295] does not
|
||||
// "error" when these two types are equated.
|
||||
//
|
||||
// [MCP 295]: https://github.com/rust-lang/compiler-team/issues/295
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
13
src/test/ui/coherence/coherence-fn-inputs.stderr
Normal file
13
src/test/ui/coherence/coherence-fn-inputs.stderr
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
error[E0119]: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)`:
|
||||
--> $DIR/coherence-fn-inputs.rs:15:1
|
||||
|
|
||||
LL | impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {}
|
||||
| ----------------------------------------------- first implementation here
|
||||
LL | impl Trait for for<'c> fn(&'c u32, &'c u32) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u32, &'b u32)`
|
||||
|
|
||||
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
||||
21
src/test/ui/coherence/coherence-free-vs-bound-region.rs
Normal file
21
src/test/ui/coherence/coherence-free-vs-bound-region.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Capture a coherence pattern from wasm-bindgen that we discovered as part of
|
||||
// future-compatibility warning #56105. This pattern currently receives a lint
|
||||
// warning but we probably want to support it long term.
|
||||
//
|
||||
// Key distinction: we are implementing once for `A` (take ownership) and one
|
||||
// for `&A` (borrow).
|
||||
//
|
||||
// c.f. #56105
|
||||
|
||||
#![deny(coherence_leak_check)]
|
||||
|
||||
trait TheTrait {}
|
||||
|
||||
impl<'a> TheTrait for fn(&'a u8) {}
|
||||
|
||||
impl TheTrait for fn(&u8) {
|
||||
//~^ ERROR conflicting implementations of trait
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
20
src/test/ui/coherence/coherence-free-vs-bound-region.stderr
Normal file
20
src/test/ui/coherence/coherence-free-vs-bound-region.stderr
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
error: conflicting implementations of trait `TheTrait` for type `fn(&u8)`:
|
||||
--> $DIR/coherence-free-vs-bound-region.rs:16:1
|
||||
|
|
||||
LL | impl<'a> TheTrait for fn(&'a u8) {}
|
||||
| -------------------------------- first implementation here
|
||||
LL |
|
||||
LL | impl TheTrait for fn(&u8) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&u8)`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/coherence-free-vs-bound-region.rs:10:9
|
||||
|
|
||||
LL | #![deny(coherence_leak_check)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
|
||||
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
37
src/test/ui/coherence/coherence-wasm-bindgen.rs
Normal file
37
src/test/ui/coherence/coherence-wasm-bindgen.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Capture a coherence pattern from wasm-bindgen that we discovered as part of
|
||||
// future-compatibility warning #56105. This pattern currently receives a lint
|
||||
// warning but we probably want to support it long term.
|
||||
//
|
||||
// Key distinction: we are implementing once for `A` (take ownership) and one
|
||||
// for `&A` (borrow).
|
||||
//
|
||||
// c.f. #56105
|
||||
|
||||
#![deny(coherence_leak_check)]
|
||||
|
||||
trait IntoWasmAbi {
|
||||
fn some_method(&self) {}
|
||||
}
|
||||
|
||||
trait FromWasmAbi {}
|
||||
trait RefFromWasmAbi {}
|
||||
trait ReturnWasmAbi {}
|
||||
|
||||
impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b)
|
||||
where
|
||||
A: FromWasmAbi,
|
||||
R: ReturnWasmAbi,
|
||||
{
|
||||
}
|
||||
|
||||
// Explicitly writing the bound lifetime.
|
||||
impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b)
|
||||
where
|
||||
A: RefFromWasmAbi,
|
||||
R: ReturnWasmAbi,
|
||||
{
|
||||
//~^^^^^ ERROR conflicting implementation
|
||||
//~| WARNING this was previously accepted
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
32
src/test/ui/coherence/coherence-wasm-bindgen.stderr
Normal file
32
src/test/ui/coherence/coherence-wasm-bindgen.stderr
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
error: conflicting implementations of trait `IntoWasmAbi` for type `&dyn std::ops::Fn(&_) -> _`:
|
||||
--> $DIR/coherence-wasm-bindgen.rs:28:1
|
||||
|
|
||||
LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b)
|
||||
LL | | where
|
||||
LL | | A: FromWasmAbi,
|
||||
LL | | R: ReturnWasmAbi,
|
||||
LL | | {
|
||||
LL | | }
|
||||
| |_- first implementation here
|
||||
...
|
||||
LL | / impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b)
|
||||
LL | | where
|
||||
LL | | A: RefFromWasmAbi,
|
||||
LL | | R: ReturnWasmAbi,
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^ conflicting implementation for `&dyn std::ops::Fn(&_) -> _`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/coherence-wasm-bindgen.rs:10:9
|
||||
|
|
||||
LL | #![deny(coherence_leak_check)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
|
||||
= note: downstream crates may implement trait `FromWasmAbi` for type `&_`
|
||||
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
8
src/test/ui/generator/resume-arg-late-bound.nll.stderr
Normal file
8
src/test/ui/generator/resume-arg-late-bound.nll.stderr
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/resume-arg-late-bound.rs:15:5
|
||||
|
|
||||
LL | test(gen);
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -13,5 +13,6 @@ fn main() {
|
|||
*arg = true;
|
||||
};
|
||||
test(gen);
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,21 @@
|
|||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/resume-arg-late-bound.rs:15:10
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/resume-arg-late-bound.rs:15:5
|
||||
|
|
||||
LL | fn test(a: impl for<'a> Generator<&'a mut bool>) {}
|
||||
| ------------------------------- required by this bound in `test`
|
||||
...
|
||||
LL | test(gen);
|
||||
| ^^^
|
||||
| |
|
||||
| expected signature of `for<'a> fn(&'a mut bool) -> _`
|
||||
| found signature of `fn(&mut bool) -> _`
|
||||
| ^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected type `for<'a> std::ops::Generator<&'a mut bool>`
|
||||
found type `std::ops::Generator<&mut bool>`
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/resume-arg-late-bound.rs:15:5
|
||||
|
|
||||
LL | test(gen);
|
||||
| ^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected type `for<'a> std::ops::Generator<&'a mut bool>`
|
||||
found type `std::ops::Generator<&mut bool>`
|
||||
|
||||
For more information about this error, try `rustc --explain E0631`.
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/hr-subtype.rs:45:13
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32,
|
||||
LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
|
||||
| |_____________________________________________- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-subtype.rs:39:26
|
||||
--> $DIR/hr-subtype.rs:45:26
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
|
||||
| ^^^^^^^^^^^ one type is more general than the other
|
||||
...
|
||||
LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32,
|
||||
LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
|
||||
| |_________________________________________________________________________________________- in this macro invocation
|
||||
LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
|
||||
| |_____________________________________________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32>`
|
||||
found enum `std::option::Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32>`
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-subtype.rs:39:26
|
||||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/hr-subtype.rs:102:1
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
|
||||
...
|
||||
LL | / check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32),
|
||||
LL | | for<'a> fn(&'a u32, &'a u32)) }
|
||||
| |__________________________________________________________________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `std::option::Option<for<'a, 'b> fn(&'a u32, &'b u32)>`
|
||||
found enum `std::option::Option<for<'a> fn(&'a u32, &'a u32)>`
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
LL | / fn main() {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/hr-subtype.rs:100:1
|
||||
--> $DIR/hr-subtype.rs:102:1
|
||||
|
|
||||
LL | / fn main() {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/hr-subtype.rs:100:1
|
||||
--> $DIR/hr-subtype.rs:102:1
|
||||
|
|
||||
LL | / fn main() {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/hr-subtype.rs:45:13
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
|
||||
LL | | fn(&'x u32)) }
|
||||
| |______________- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-subtype.rs:39:26
|
||||
--> $DIR/hr-subtype.rs:45:26
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
|
||||
| ^^^^^^^^^^^ one type is more general than the other
|
||||
...
|
||||
LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
|
||||
LL | | fn(&'x u32)) }
|
||||
| |___________________________________________- in this macro invocation
|
||||
LL | | fn(&'x u32)) }
|
||||
| |______________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `std::option::Option<for<'a> fn(&'a u32)>`
|
||||
found enum `std::option::Option<fn(&'x u32)>`
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-subtype.rs:39:26
|
||||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/hr-subtype.rs:102:1
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
|
||||
...
|
||||
LL | / check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>),
|
||||
LL | | for<'a> fn(Co<'a>, Co<'a>)) }
|
||||
| |______________________________________________________________________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>)>`
|
||||
found enum `std::option::Option<for<'a> fn(Co<'a>, Co<'a>)>`
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
LL | / fn main() {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-subtype.rs:39:26
|
||||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/hr-subtype.rs:102:1
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
|
||||
...
|
||||
LL | / check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>,
|
||||
LL | | for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) }
|
||||
| |______________________________________________________________________________________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `std::option::Option<for<'a, 'b> fn(Co<'a>, Co<'b>) -> Contra<'a>>`
|
||||
found enum `std::option::Option<for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>>`
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
LL | / fn main() {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/hr-subtype.rs:100:1
|
||||
--> $DIR/hr-subtype.rs:102:1
|
||||
|
|
||||
LL | / fn main() {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-subtype.rs:39:26
|
||||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/hr-subtype.rs:102:1
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
|
||||
...
|
||||
LL | / check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>,
|
||||
LL | | for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
|
||||
| |______________________________________________________________________________________________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `std::option::Option<for<'a, 'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>>`
|
||||
found enum `std::option::Option<for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>>`
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
LL | / fn main() {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/hr-subtype.rs:45:13
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
|
||||
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
|
||||
| |__________________________________- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/hr-subtype.rs:45:13
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
|
||||
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
|
||||
| |__________________________________- in this macro invocation
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-subtype.rs:39:26
|
||||
--> $DIR/hr-subtype.rs:45:26
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
|
||||
| ^^^^^^^^^^^ one type is more general than the other
|
||||
...
|
||||
LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
|
||||
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
|
||||
| |__________________________________________________________________________- in this macro invocation
|
||||
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
|
||||
| |__________________________________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `std::option::Option<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>`
|
||||
found enum `std::option::Option<for<'a> fn(Inv<'a>, Inv<'a>)>`
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/hr-subtype.rs:100:1
|
||||
--> $DIR/hr-subtype.rs:102:1
|
||||
|
|
||||
LL | / fn main() {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
|
|||
|
|
@ -1,33 +1,33 @@
|
|||
error: lifetime may not live long enough
|
||||
--> $DIR/hr-subtype.rs:33:13
|
||||
--> $DIR/hr-subtype.rs:39:13
|
||||
|
|
||||
LL | fn subtype<'x,'y:'x,'z:'y>() {
|
||||
| -- -- lifetime `'y` defined here
|
||||
LL | fn subtype<'x, 'y: 'x, 'z: 'y>() {
|
||||
| -- -- lifetime `'y` defined here
|
||||
| |
|
||||
| lifetime `'x` defined here
|
||||
LL | gimme::<$t2>(None::<$t1>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y`
|
||||
...
|
||||
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |__________________________________________________- in this macro invocation
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |______________- in this macro invocation
|
||||
|
|
||||
= help: consider adding the following bound: `'x: 'y`
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/hr-subtype.rs:39:13
|
||||
--> $DIR/hr-subtype.rs:45:13
|
||||
|
|
||||
LL | fn supertype<'x,'y:'x,'z:'y>() {
|
||||
| -- -- lifetime `'y` defined here
|
||||
LL | fn supertype<'x, 'y: 'x, 'z: 'y>() {
|
||||
| -- -- lifetime `'y` defined here
|
||||
| |
|
||||
| lifetime `'x` defined here
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y`
|
||||
...
|
||||
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |__________________________________________________- in this macro invocation
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |______________- in this macro invocation
|
||||
|
|
||||
= help: consider adding the following bound: `'x: 'y`
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
|
|
|||
|
|
@ -1,65 +1,65 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-subtype.rs:33:26
|
||||
--> $DIR/hr-subtype.rs:39:26
|
||||
|
|
||||
LL | gimme::<$t2>(None::<$t1>);
|
||||
| ^^^^^^^^^^^ lifetime mismatch
|
||||
...
|
||||
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |__________________________________________________- in this macro invocation
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |______________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `std::option::Option<fn(Inv<'y>)>`
|
||||
found enum `std::option::Option<fn(Inv<'x>)>`
|
||||
note: the lifetime `'x` as defined on the function body at 32:20...
|
||||
--> $DIR/hr-subtype.rs:32:20
|
||||
note: the lifetime `'x` as defined on the function body at 38:20...
|
||||
--> $DIR/hr-subtype.rs:38:20
|
||||
|
|
||||
LL | fn subtype<'x,'y:'x,'z:'y>() {
|
||||
LL | fn subtype<'x, 'y: 'x, 'z: 'y>() {
|
||||
| ^^
|
||||
...
|
||||
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |__________________________________________________- in this macro invocation
|
||||
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 32:23
|
||||
--> $DIR/hr-subtype.rs:32:23
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |______________- in this macro invocation
|
||||
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:24
|
||||
--> $DIR/hr-subtype.rs:38:24
|
||||
|
|
||||
LL | fn subtype<'x,'y:'x,'z:'y>() {
|
||||
| ^^
|
||||
LL | fn subtype<'x, 'y: 'x, 'z: 'y>() {
|
||||
| ^^
|
||||
...
|
||||
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |__________________________________________________- in this macro invocation
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |______________- in this macro invocation
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-subtype.rs:39:26
|
||||
--> $DIR/hr-subtype.rs:45:26
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^ lifetime mismatch
|
||||
...
|
||||
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |__________________________________________________- in this macro invocation
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |______________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `std::option::Option<fn(Inv<'x>)>`
|
||||
found enum `std::option::Option<fn(Inv<'y>)>`
|
||||
note: the lifetime `'x` as defined on the function body at 38:22...
|
||||
--> $DIR/hr-subtype.rs:38:22
|
||||
note: the lifetime `'x` as defined on the function body at 44:22...
|
||||
--> $DIR/hr-subtype.rs:44:22
|
||||
|
|
||||
LL | fn supertype<'x,'y:'x,'z:'y>() {
|
||||
LL | fn supertype<'x, 'y: 'x, 'z: 'y>() {
|
||||
| ^^
|
||||
...
|
||||
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |__________________________________________________- in this macro invocation
|
||||
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25
|
||||
--> $DIR/hr-subtype.rs:38:25
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |______________- in this macro invocation
|
||||
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26
|
||||
--> $DIR/hr-subtype.rs:44:26
|
||||
|
|
||||
LL | fn supertype<'x,'y:'x,'z:'y>() {
|
||||
| ^^
|
||||
LL | fn supertype<'x, 'y: 'x, 'z: 'y>() {
|
||||
| ^^
|
||||
...
|
||||
LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |__________________________________________________- in this macro invocation
|
||||
LL | | fn(Inv<'y>)) }
|
||||
| |______________- in this macro invocation
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/hr-subtype.rs:100:1
|
||||
--> $DIR/hr-subtype.rs:102:1
|
||||
|
|
||||
LL | / fn main() {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
error: lifetime may not live long enough
|
||||
--> $DIR/hr-subtype.rs:39:13
|
||||
--> $DIR/hr-subtype.rs:45:13
|
||||
|
|
||||
LL | fn supertype<'x,'y:'x,'z:'y>() {
|
||||
| -- -- lifetime `'y` defined here
|
||||
LL | fn supertype<'x, 'y: 'x, 'z: 'y>() {
|
||||
| -- -- lifetime `'y` defined here
|
||||
| |
|
||||
| lifetime `'x` defined here
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'x` must outlive `'y`
|
||||
...
|
||||
LL | / check! { free_x_vs_free_y: (fn(&'x u32),
|
||||
LL | | fn(&'y u32)) }
|
||||
| |__________________________________________- in this macro invocation
|
||||
LL | | fn(&'y u32)) }
|
||||
| |______________- in this macro invocation
|
||||
|
|
||||
= help: consider adding the following bound: `'x: 'y`
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
|
|
|||
|
|
@ -1,33 +1,33 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-subtype.rs:39:26
|
||||
--> $DIR/hr-subtype.rs:45:26
|
||||
|
|
||||
LL | gimme::<$t1>(None::<$t2>);
|
||||
| ^^^^^^^^^^^ lifetime mismatch
|
||||
...
|
||||
LL | / check! { free_x_vs_free_y: (fn(&'x u32),
|
||||
LL | | fn(&'y u32)) }
|
||||
| |__________________________________________- in this macro invocation
|
||||
LL | | fn(&'y u32)) }
|
||||
| |______________- in this macro invocation
|
||||
|
|
||||
= note: expected enum `std::option::Option<fn(&'x u32)>`
|
||||
found enum `std::option::Option<fn(&'y u32)>`
|
||||
note: the lifetime `'x` as defined on the function body at 38:22...
|
||||
--> $DIR/hr-subtype.rs:38:22
|
||||
note: the lifetime `'x` as defined on the function body at 44:22...
|
||||
--> $DIR/hr-subtype.rs:44:22
|
||||
|
|
||||
LL | fn supertype<'x,'y:'x,'z:'y>() {
|
||||
LL | fn supertype<'x, 'y: 'x, 'z: 'y>() {
|
||||
| ^^
|
||||
...
|
||||
LL | / check! { free_x_vs_free_y: (fn(&'x u32),
|
||||
LL | | fn(&'y u32)) }
|
||||
| |__________________________________________- in this macro invocation
|
||||
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25
|
||||
--> $DIR/hr-subtype.rs:38:25
|
||||
LL | | fn(&'y u32)) }
|
||||
| |______________- in this macro invocation
|
||||
note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 44:26
|
||||
--> $DIR/hr-subtype.rs:44:26
|
||||
|
|
||||
LL | fn supertype<'x,'y:'x,'z:'y>() {
|
||||
| ^^
|
||||
LL | fn supertype<'x, 'y: 'x, 'z: 'y>() {
|
||||
| ^^
|
||||
...
|
||||
LL | / check! { free_x_vs_free_y: (fn(&'x u32),
|
||||
LL | | fn(&'y u32)) }
|
||||
| |__________________________________________- in this macro invocation
|
||||
LL | | fn(&'y u32)) }
|
||||
| |______________- in this macro invocation
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
|
|||
|
|
@ -18,60 +18,62 @@
|
|||
// revisions: bound_inv_a_b_vs_bound_inv_a
|
||||
// revisions: bound_a_b_ret_a_vs_bound_a_ret_a
|
||||
|
||||
fn gimme<T>(_: Option<T>) { }
|
||||
fn gimme<T>(_: Option<T>) {}
|
||||
|
||||
struct Inv<'a> { x: *mut &'a u32 }
|
||||
struct Inv<'a> {
|
||||
x: *mut &'a u32,
|
||||
}
|
||||
|
||||
struct Co<'a> { x: fn(&'a u32) }
|
||||
struct Co<'a> {
|
||||
x: fn(&'a u32),
|
||||
}
|
||||
|
||||
struct Contra<'a> { x: &'a u32 }
|
||||
struct Contra<'a> {
|
||||
x: &'a u32,
|
||||
}
|
||||
|
||||
macro_rules! check {
|
||||
($rev:ident: ($t1:ty, $t2:ty)) => {
|
||||
#[cfg($rev)]
|
||||
fn subtype<'x,'y:'x,'z:'y>() {
|
||||
fn subtype<'x, 'y: 'x, 'z: 'y>() {
|
||||
gimme::<$t2>(None::<$t1>);
|
||||
//[free_inv_x_vs_free_inv_y]~^ ERROR
|
||||
}
|
||||
|
||||
#[cfg($rev)]
|
||||
fn supertype<'x,'y:'x,'z:'y>() {
|
||||
fn supertype<'x, 'y: 'x, 'z: 'y>() {
|
||||
gimme::<$t1>(None::<$t2>);
|
||||
//[bound_a_vs_free_x]~^ ERROR
|
||||
//[free_x_vs_free_y]~^^ ERROR
|
||||
//[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR
|
||||
//[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR
|
||||
//[free_inv_x_vs_free_inv_y]~^^^^^ ERROR
|
||||
//[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types
|
||||
//[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR
|
||||
//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR
|
||||
//[bound_co_a_b_vs_bound_co_a]~^^^^^^^^^ ERROR
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// If both have bound regions, they are equivalent, regardless of
|
||||
// variant.
|
||||
check! { bound_a_vs_bound_a: (for<'a> fn(&'a u32),
|
||||
for<'a> fn(&'a u32)) }
|
||||
for<'a> fn(&'a u32)) }
|
||||
check! { bound_a_vs_bound_b: (for<'a> fn(&'a u32),
|
||||
for<'b> fn(&'b u32)) }
|
||||
for<'b> fn(&'b u32)) }
|
||||
check! { bound_inv_a_vs_bound_inv_b: (for<'a> fn(Inv<'a>),
|
||||
for<'b> fn(Inv<'b>)) }
|
||||
for<'b> fn(Inv<'b>)) }
|
||||
check! { bound_co_a_vs_bound_co_b: (for<'a> fn(Co<'a>),
|
||||
for<'b> fn(Co<'b>)) }
|
||||
for<'b> fn(Co<'b>)) }
|
||||
|
||||
// Bound is a subtype of free.
|
||||
check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
|
||||
fn(&'x u32)) }
|
||||
fn(&'x u32)) }
|
||||
|
||||
// Two free regions are relatable if subtyping holds.
|
||||
check! { free_x_vs_free_x: (fn(&'x u32),
|
||||
fn(&'x u32)) }
|
||||
fn(&'x u32)) }
|
||||
check! { free_x_vs_free_y: (fn(&'x u32),
|
||||
fn(&'y u32)) }
|
||||
fn(&'y u32)) }
|
||||
check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
||||
fn(Inv<'y>)) }
|
||||
fn(Inv<'y>)) }
|
||||
|
||||
// Somewhat surprisingly, a fn taking two distinct bound lifetimes and
|
||||
// a fn taking one bound lifetime can be interchangeable, but only if
|
||||
|
|
@ -82,25 +84,29 @@ check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
|
|||
// intersection;
|
||||
// - if we are contravariant, then 'a can be inferred to 'static.
|
||||
check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32),
|
||||
for<'a> fn(&'a u32, &'a u32)) }
|
||||
for<'a> fn(&'a u32, &'a u32)) }
|
||||
check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>),
|
||||
for<'a> fn(Co<'a>, Co<'a>)) }
|
||||
for<'a> fn(Co<'a>, Co<'a>)) }
|
||||
check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>,
|
||||
for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
|
||||
for<'a> fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
|
||||
check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>,
|
||||
for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) }
|
||||
for<'a> fn(Co<'a>, Co<'a>) -> Contra<'a>) }
|
||||
|
||||
// If we make those lifetimes invariant, then the two types are not interchangeable.
|
||||
check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
|
||||
for<'a> fn(Inv<'a>, Inv<'a>)) }
|
||||
for<'a> fn(Inv<'a>, Inv<'a>)) }
|
||||
check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32,
|
||||
for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
|
||||
for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
|
||||
|
||||
#[rustc_error]
|
||||
fn main() {
|
||||
//[bound_a_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error]
|
||||
//[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error]
|
||||
//[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error]
|
||||
//[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error]
|
||||
//[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error]
|
||||
//[bound_a_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error]
|
||||
//[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error]
|
||||
//[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error]
|
||||
//[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error]
|
||||
//[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error]
|
||||
//[bound_co_a_b_vs_bound_co_a]~^^^^^^ ERROR
|
||||
//[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR
|
||||
//[bound_a_b_vs_bound_a]~^^^^^^^^ ERROR
|
||||
//[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^^ ERROR
|
||||
}
|
||||
|
|
|
|||
13
src/test/ui/hr-subtype/return-static.rs
Normal file
13
src/test/ui/hr-subtype/return-static.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// check-pass
|
||||
|
||||
fn make<T>() -> T {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn take<T>(x: T) {}
|
||||
|
||||
fn main() {
|
||||
let x: for<'a> fn(&'a u32) -> _ = make();
|
||||
let y: &'static u32 = x(&22);
|
||||
take::<for<'b> fn(&'b u32) -> &'b u32>(x);
|
||||
}
|
||||
14
src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr
Normal file
14
src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/hrtb-conflate-regions.rs:27:10
|
||||
|
|
||||
LL | fn b() { want_foo2::<SomeStruct>(); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/hrtb-conflate-regions.rs:27:10
|
||||
|
|
||||
LL | fn b() { want_foo2::<SomeStruct>(); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -1,17 +1,16 @@
|
|||
error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied
|
||||
--> $DIR/hrtb-conflate-regions.rs:27:22
|
||||
error: implementation of `Foo` is not general enough
|
||||
--> $DIR/hrtb-conflate-regions.rs:27:10
|
||||
|
|
||||
LL | fn want_foo2<T>()
|
||||
| --------- required by a bound in this
|
||||
LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)>
|
||||
| -------------------------------------- required by this bound in `want_foo2`
|
||||
LL | / trait Foo<X> {
|
||||
LL | | fn foo(&self, x: X) { }
|
||||
LL | | }
|
||||
| |_- trait `Foo` defined here
|
||||
...
|
||||
LL | fn b() { want_foo2::<SomeStruct>(); }
|
||||
| ^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct`
|
||||
LL | fn b() { want_foo2::<SomeStruct>(); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<SomeStruct as Foo<(&'a isize, &'a isize)>>
|
||||
= note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
|
||||
= note: ...but `SomeStruct` actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
8
src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr
Normal file
8
src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/hrtb-exists-forall-fn.rs:17:12
|
||||
|
|
||||
LL | let _: for<'b> fn(&'b u32) = foo();
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -2,9 +2,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/hrtb-exists-forall-fn.rs:17:34
|
||||
|
|
||||
LL | let _: for<'b> fn(&'b u32) = foo();
|
||||
| ------------------- ^^^^^ expected concrete lifetime, found bound lifetime parameter 'b
|
||||
| |
|
||||
| expected due to this
|
||||
| ^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'b> fn(&'b u32)`
|
||||
found fn pointer `fn(&u32)`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5
|
||||
|
|
||||
LL | foo::<()>();
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -32,5 +32,5 @@ fn main() {
|
|||
// NB. *However*, the reinstated leak-check gives an error here.
|
||||
|
||||
foo::<()>();
|
||||
//~^ ERROR not satisfied
|
||||
//~^ ERROR implementation of `Trait` is not general enough
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,14 @@
|
|||
error[E0277]: the trait bound `(): Trait<for<'b> fn(&'b u32)>` is not satisfied
|
||||
--> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:11
|
||||
error: implementation of `Trait` is not general enough
|
||||
--> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5
|
||||
|
|
||||
LL | fn foo<T>()
|
||||
| --- required by a bound in this
|
||||
LL | where
|
||||
LL | T: Trait<for<'b> fn(&'b u32)>,
|
||||
| -------------------------- required by this bound in `foo`
|
||||
LL | trait Trait<T> {}
|
||||
| ----------------- trait `Trait` defined here
|
||||
...
|
||||
LL | foo::<()>();
|
||||
| ^^ the trait `Trait<for<'b> fn(&'b u32)>` is not implemented for `()`
|
||||
| ^^^^^^^^^ implementation of `Trait` is not general enough
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<() as Trait<fn(&'a u32)>>
|
||||
= note: `()` must implement `Trait<for<'b> fn(&'b u32)>`
|
||||
= note: ...but `()` actually implements `Trait<fn(&'0 u32)>`, for some specific lifetime `'0`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
//
|
||||
// In particular, we test this pattern in trait solving, where it is not connected
|
||||
// to any part of the source code.
|
||||
//
|
||||
// check-pass
|
||||
|
||||
trait Trait<T> {}
|
||||
|
||||
|
|
@ -30,9 +32,6 @@ fn main() {
|
|||
// - `?b: ?a` -- solveable if `?b` is inferred to `'static`
|
||||
// - So the subtyping check succeeds, somewhat surprisingly.
|
||||
// This is because we can use `'static`.
|
||||
//
|
||||
// NB. *However*, the reinstated leak-check gives an error here.
|
||||
|
||||
foo::<()>();
|
||||
//~^ ERROR not satisfied
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
error[E0277]: the trait bound `(): Trait<for<'b> fn(fn(&'b u32))>` is not satisfied
|
||||
--> $DIR/hrtb-exists-forall-trait-covariant.rs:36:11
|
||||
|
|
||||
LL | fn foo<T>()
|
||||
| --- required by a bound in this
|
||||
LL | where
|
||||
LL | T: Trait<for<'b> fn(fn(&'b u32))>,
|
||||
| ------------------------------ required by this bound in `foo`
|
||||
...
|
||||
LL | foo::<()>();
|
||||
| ^^ the trait `Trait<for<'b> fn(fn(&'b u32))>` is not implemented for `()`
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<() as Trait<fn(fn(&'a u32))>>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5
|
||||
|
|
||||
LL | foo::<()>();
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -25,5 +25,5 @@ fn main() {
|
|||
// yielding `fn(&!b u32)`, in a fresh universe U1
|
||||
// - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`.
|
||||
|
||||
foo::<()>(); //~ ERROR not satisfied
|
||||
foo::<()>(); //~ ERROR implementation of `Trait` is not general enough
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,14 @@
|
|||
error[E0277]: the trait bound `(): Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` is not satisfied
|
||||
--> $DIR/hrtb-exists-forall-trait-invariant.rs:28:11
|
||||
error: implementation of `Trait` is not general enough
|
||||
--> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5
|
||||
|
|
||||
LL | fn foo<T>()
|
||||
| --- required by a bound in this
|
||||
LL | where
|
||||
LL | T: Trait<for<'b> fn(Cell<&'b u32>)>,
|
||||
| -------------------------------- required by this bound in `foo`
|
||||
LL | trait Trait<T> {}
|
||||
| ----------------- trait `Trait` defined here
|
||||
...
|
||||
LL | foo::<()>();
|
||||
| ^^ the trait `Trait<for<'b> fn(std::cell::Cell<&'b u32>)>` is not implemented for `()`
|
||||
| ^^^^^^^^^ implementation of `Trait` is not general enough
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<() as Trait<fn(std::cell::Cell<&'a u32>)>>
|
||||
= note: `()` must implement `Trait<for<'b> fn(std::cell::Cell<&'b u32>)>`
|
||||
= note: ...but `()` actually implements `Trait<fn(std::cell::Cell<&'0 u32>)>`, for some specific lifetime `'0`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
24
src/test/ui/hrtb/hrtb-just-for-static.nll.stderr
Normal file
24
src/test/ui/hrtb/hrtb-just-for-static.nll.stderr
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/hrtb-just-for-static.rs:24:5
|
||||
|
|
||||
LL | want_hrtb::<StaticInt>()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/hrtb-just-for-static.rs:30:5
|
||||
|
|
||||
LL | fn give_some<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | want_hrtb::<&'a u32>()
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
|
||||
= help: consider replacing `'a` with `'static`
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/hrtb-just-for-static.rs:30:5
|
||||
|
|
||||
LL | want_hrtb::<&'a u32>()
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
@ -1,31 +1,30 @@
|
|||
error[E0277]: the trait bound `for<'a> StaticInt: Foo<&'a isize>` is not satisfied
|
||||
--> $DIR/hrtb-just-for-static.rs:24:17
|
||||
error: implementation of `Foo` is not general enough
|
||||
--> $DIR/hrtb-just-for-static.rs:24:5
|
||||
|
|
||||
LL | fn want_hrtb<T>()
|
||||
| --------- required by a bound in this
|
||||
LL | where T : for<'a> Foo<&'a isize>
|
||||
| ---------------------- required by this bound in `want_hrtb`
|
||||
LL | / trait Foo<X> {
|
||||
LL | | fn foo(&self, x: X) { }
|
||||
LL | | }
|
||||
| |_- trait `Foo` defined here
|
||||
...
|
||||
LL | want_hrtb::<StaticInt>()
|
||||
| ^^^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `StaticInt`
|
||||
LL | want_hrtb::<StaticInt>()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<StaticInt as Foo<&'static isize>>
|
||||
= note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`...
|
||||
= note: ...but `StaticInt` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1`
|
||||
|
||||
error[E0277]: the trait bound `for<'a> &'a u32: Foo<&'a isize>` is not satisfied
|
||||
--> $DIR/hrtb-just-for-static.rs:30:17
|
||||
error: implementation of `Foo` is not general enough
|
||||
--> $DIR/hrtb-just-for-static.rs:30:5
|
||||
|
|
||||
LL | fn want_hrtb<T>()
|
||||
| --------- required by a bound in this
|
||||
LL | where T : for<'a> Foo<&'a isize>
|
||||
| ---------------------- required by this bound in `want_hrtb`
|
||||
LL | / trait Foo<X> {
|
||||
LL | | fn foo(&self, x: X) { }
|
||||
LL | | }
|
||||
| |_- trait `Foo` defined here
|
||||
...
|
||||
LL | want_hrtb::<&'a u32>()
|
||||
| ^^^^^^^ the trait `for<'a> Foo<&'a isize>` is not implemented for `&'a u32`
|
||||
LL | want_hrtb::<&'a u32>()
|
||||
| ^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<&'a u32 as Foo<&'a isize>>
|
||||
= note: `Foo<&'0 isize>` would have to be implemented for the type `&'a u32`, for any lifetime `'0`...
|
||||
= note: ...but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
|
|
@ -1,17 +1,43 @@
|
|||
error: implementation of `Stream` is not general enough
|
||||
--> $DIR/issue-30786.rs:108:22
|
||||
error[E0599]: no method named `filterx` found for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>` in the current scope
|
||||
--> $DIR/issue-30786.rs:128:22
|
||||
|
|
||||
LL | / pub trait Stream {
|
||||
LL | | type Item;
|
||||
LL | | fn next(self) -> Option<Self::Item>;
|
||||
LL | | }
|
||||
| |_- trait `Stream` defined here
|
||||
LL | pub struct Map<S, F> {
|
||||
| --------------------
|
||||
| |
|
||||
| method `filterx` not found for this
|
||||
| doesn't satisfy `_: StreamExt`
|
||||
...
|
||||
LL | let map = source.map(|x: &_| x);
|
||||
| ^^^ implementation of `Stream` is not general enough
|
||||
LL | let filter = map.filterx(|x: &_| true);
|
||||
| ^^^^^^^ method not found in `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>`
|
||||
|
|
||||
= note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for any lifetime `'0`...
|
||||
= note: ...but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:108:26: 108:35]>`, for some specific lifetime `'1`
|
||||
= note: the method `filterx` exists but the following trait bounds were not satisfied:
|
||||
`&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
|
||||
which is required by `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt`
|
||||
`&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
|
||||
which is required by `&Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt`
|
||||
`&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
|
||||
which is required by `&mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt`
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0599]: no method named `countx` found for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` in the current scope
|
||||
--> $DIR/issue-30786.rs:141:24
|
||||
|
|
||||
LL | pub struct Filter<S, F> {
|
||||
| -----------------------
|
||||
| |
|
||||
| method `countx` not found for this
|
||||
| doesn't satisfy `_: StreamExt`
|
||||
...
|
||||
LL | let count = filter.countx();
|
||||
| ^^^^^^ method not found in `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>`
|
||||
|
|
||||
= note: the method `countx` exists but the following trait bounds were not satisfied:
|
||||
`&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
|
||||
which is required by `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt`
|
||||
`&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
|
||||
which is required by `&Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt`
|
||||
`&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
|
||||
which is required by `&mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
||||
|
|
|
|||
|
|
@ -1,56 +1,43 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-30786.rs:108:15
|
||||
error[E0599]: no method named `filterx` found for struct `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>` in the current scope
|
||||
--> $DIR/issue-30786.rs:128:22
|
||||
|
|
||||
LL | let map = source.map(|x: &_| x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-30786.rs:114:18
|
||||
LL | pub struct Map<S, F> {
|
||||
| --------------------
|
||||
| |
|
||||
| method `filterx` not found for this
|
||||
| doesn't satisfy `_: StreamExt`
|
||||
...
|
||||
LL | let filter = map.filterx(|x: &_| true);
|
||||
| ^^^^^^^ method not found in `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>`
|
||||
|
|
||||
LL | let filter = map.filter(|x: &_| true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: the method `filterx` exists but the following trait bounds were not satisfied:
|
||||
`&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
|
||||
which is required by `Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt`
|
||||
`&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
|
||||
which is required by `&Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt`
|
||||
`&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: Stream`
|
||||
which is required by `&mut Map<Repeat, [closure@$DIR/issue-30786.rs:127:27: 127:36]>: StreamExt`
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-30786.rs:114:18
|
||||
error[E0599]: no method named `countx` found for struct `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>` in the current scope
|
||||
--> $DIR/issue-30786.rs:141:24
|
||||
|
|
||||
LL | let filter = map.filter(|x: &_| true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-30786.rs:114:18
|
||||
LL | pub struct Filter<S, F> {
|
||||
| -----------------------
|
||||
| |
|
||||
| method `countx` not found for this
|
||||
| doesn't satisfy `_: StreamExt`
|
||||
...
|
||||
LL | let count = filter.countx();
|
||||
| ^^^^^^ method not found in `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>`
|
||||
|
|
||||
LL | let filter = map.filter(|x: &_| true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: the method `countx` exists but the following trait bounds were not satisfied:
|
||||
`&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
|
||||
which is required by `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt`
|
||||
`&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
|
||||
which is required by `&Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt`
|
||||
`&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: Stream`
|
||||
which is required by `&mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:140:30: 140:42]>: StreamExt`
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-30786.rs:114:18
|
||||
|
|
||||
LL | let filter = map.filter(|x: &_| true);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-30786.rs:119:17
|
||||
|
|
||||
LL | let count = filter.count(); // Assert that we still have a valid stream.
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-30786.rs:119:17
|
||||
|
|
||||
LL | let count = filter.count(); // Assert that we still have a valid stream.
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-30786.rs:119:17
|
||||
|
|
||||
LL | let count = filter.count(); // Assert that we still have a valid stream.
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-30786.rs:119:17
|
||||
|
|
||||
LL | let count = filter.count(); // Assert that we still have a valid stream.
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
//[nll]compile-flags: -Z borrowck=mir
|
||||
|
||||
pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here
|
||||
pub trait Stream {
|
||||
type Item;
|
||||
fn next(self) -> Option<Self::Item>;
|
||||
}
|
||||
|
|
@ -37,8 +37,9 @@ pub struct Map<S, F> {
|
|||
}
|
||||
|
||||
impl<'a, A, F, T> Stream for &'a mut Map<A, F>
|
||||
where &'a mut A: Stream,
|
||||
F: FnMut(<&'a mut A as Stream>::Item) -> T,
|
||||
where
|
||||
&'a mut A: Stream,
|
||||
F: FnMut(<&'a mut A as Stream>::Item) -> T,
|
||||
{
|
||||
type Item = T;
|
||||
fn next(self) -> Option<T> {
|
||||
|
|
@ -55,8 +56,9 @@ pub struct Filter<S, F> {
|
|||
}
|
||||
|
||||
impl<'a, A, F, T> Stream for &'a mut Filter<A, F>
|
||||
where for<'b> &'b mut A: Stream<Item=T>, // <---- BAD
|
||||
F: FnMut(&T) -> bool,
|
||||
where
|
||||
for<'b> &'b mut A: Stream<Item = T>, // <---- BAD
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
type Item = <&'a mut A as Stream>::Item;
|
||||
fn next(self) -> Option<Self::Item> {
|
||||
|
|
@ -69,29 +71,29 @@ where for<'b> &'b mut A: Stream<Item=T>, // <---- BAD
|
|||
}
|
||||
}
|
||||
|
||||
pub trait StreamExt where for<'b> &'b mut Self: Stream {
|
||||
fn map<F>(self, func: F) -> Map<Self, F>
|
||||
where Self: Sized,
|
||||
for<'a> &'a mut Map<Self, F>: Stream,
|
||||
pub trait StreamExt
|
||||
where
|
||||
for<'b> &'b mut Self: Stream,
|
||||
{
|
||||
fn mapx<F>(self, func: F) -> Map<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
for<'a> &'a mut Map<Self, F>: Stream,
|
||||
{
|
||||
Map {
|
||||
func: func,
|
||||
stream: self,
|
||||
}
|
||||
Map { func: func, stream: self }
|
||||
}
|
||||
|
||||
fn filter<F>(self, func: F) -> Filter<Self, F>
|
||||
where Self: Sized,
|
||||
for<'a> &'a mut Filter<Self, F>: Stream,
|
||||
fn filterx<F>(self, func: F) -> Filter<Self, F>
|
||||
where
|
||||
Self: Sized,
|
||||
for<'a> &'a mut Filter<Self, F>: Stream,
|
||||
{
|
||||
Filter {
|
||||
func: func,
|
||||
stream: self,
|
||||
}
|
||||
Filter { func: func, stream: self }
|
||||
}
|
||||
|
||||
fn count(mut self) -> usize
|
||||
where Self: Sized,
|
||||
fn countx(mut self) -> usize
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let mut count = 0;
|
||||
while let Some(_) = self.next() {
|
||||
|
|
@ -101,24 +103,44 @@ pub trait StreamExt where for<'b> &'b mut Self: Stream {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> StreamExt for T where for<'a> &'a mut T: Stream { }
|
||||
impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
|
||||
|
||||
fn main() {
|
||||
let source = Repeat(10);
|
||||
let map = source.map(|x: &_| x);
|
||||
//[nll]~^ ERROR higher-ranked subtype error
|
||||
//[migrate]~^^ ERROR implementation of `Stream` is not general enough
|
||||
//[migrate]~| NOTE `Stream` would have to be implemented for the type `&'0 mut Map
|
||||
//[migrate]~| NOTE but `Stream` is actually implemented for the type `&'1
|
||||
//[migrate]~| NOTE implementation of `Stream` is not general enough
|
||||
let filter = map.filter(|x: &_| true);
|
||||
//[nll]~^ ERROR higher-ranked subtype error
|
||||
//[nll]~| ERROR higher-ranked subtype error
|
||||
//[nll]~| ERROR higher-ranked subtype error
|
||||
//[nll]~| ERROR higher-ranked subtype error
|
||||
let count = filter.count(); // Assert that we still have a valid stream.
|
||||
//[nll]~^ ERROR higher-ranked subtype error
|
||||
//[nll]~| ERROR higher-ranked subtype error
|
||||
//[nll]~| ERROR higher-ranked subtype error
|
||||
//[nll]~| ERROR higher-ranked subtype error
|
||||
fn identity<T>(x: &T) -> &T {
|
||||
x
|
||||
}
|
||||
|
||||
fn variant1() {
|
||||
let source = Repeat(10);
|
||||
|
||||
// Here, the call to `mapx` returns a type `T` to which `StreamExt`
|
||||
// is not applicable, because `for<'b> &'b mut T: Stream`) doesn't hold.
|
||||
//
|
||||
// More concretely, the type `T` is `Map<Repeat, Closure>`, and
|
||||
// the where clause doesn't hold because the signature of the
|
||||
// closure gets inferred to a signature like `|&'_ Stream| -> &'_`
|
||||
// for some specific `'_`, rather than a more generic
|
||||
// signature.
|
||||
//
|
||||
// Why *exactly* we opt for this signature is a bit unclear to me,
|
||||
// we deduce it somehow from a reuqirement that `Map: Stream` I
|
||||
// guess.
|
||||
let map = source.mapx(|x: &_| x);
|
||||
let filter = map.filterx(|x: &_| true);
|
||||
//[migrate]~^ ERROR no method named `filterx`
|
||||
//[nll]~^^ ERROR no method named `filterx`
|
||||
}
|
||||
|
||||
fn variant2() {
|
||||
let source = Repeat(10);
|
||||
|
||||
// Here, we use a function, which is not subject to the vagaries
|
||||
// of closure signature inference. In this case, we get the error
|
||||
// on `countx` as, I think, the test originally expected.
|
||||
let map = source.mapx(identity);
|
||||
let filter = map.filterx(|x: &_| true);
|
||||
let count = filter.countx();
|
||||
//[migrate]~^ ERROR no method named `countx`
|
||||
//[nll]~^^ ERROR no method named `countx`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
8
src/test/ui/hrtb/issue-46989.nll.stderr
Normal file
8
src/test/ui/hrtb/issue-46989.nll.stderr
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-46989.rs:38:5
|
||||
|
|
||||
LL | assert_foo::<fn(&i32)>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -28,15 +28,13 @@
|
|||
//
|
||||
// holds because 'a can be instantiated to 'empty.
|
||||
|
||||
trait Foo {
|
||||
trait Foo {}
|
||||
|
||||
}
|
||||
|
||||
impl<A> Foo for fn(A) { }
|
||||
impl<A> Foo for fn(A) {}
|
||||
|
||||
fn assert_foo<T: Foo>() {}
|
||||
|
||||
fn main() {
|
||||
assert_foo::<fn(&i32)>();
|
||||
//~^ ERROR the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied
|
||||
//~^ ERROR implementation of `Foo` is not general enough
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
error[E0277]: the trait bound `for<'r> fn(&'r i32): Foo` is not satisfied
|
||||
--> $DIR/issue-46989.rs:40:18
|
||||
error: implementation of `Foo` is not general enough
|
||||
--> $DIR/issue-46989.rs:38:5
|
||||
|
|
||||
LL | fn assert_foo<T: Foo>() {}
|
||||
| --- required by this bound in `assert_foo`
|
||||
LL | trait Foo {}
|
||||
| ------------ trait `Foo` defined here
|
||||
...
|
||||
LL | assert_foo::<fn(&i32)>();
|
||||
| ^^^^^^^^ the trait `Foo` is not implemented for `for<'r> fn(&'r i32)`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
||||
|
|
||||
= help: the following implementations were found:
|
||||
<fn(A) as Foo>
|
||||
= note: `Foo` would have to be implemented for the type `for<'r> fn(&'r i32)`
|
||||
= note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
8
src/test/ui/issues/issue-40000.nll.stderr
Normal file
8
src/test/ui/issues/issue-40000.nll.stderr
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/issue-40000.rs:6:9
|
||||
|
|
||||
LL | foo(bar);
|
||||
| ^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -2,10 +2,10 @@ error[E0308]: mismatched types
|
|||
--> $DIR/issue-40000.rs:6:9
|
||||
|
|
||||
LL | foo(bar);
|
||||
| ^^^ expected concrete lifetime, found bound lifetime parameter
|
||||
| ^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected struct `std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r i32) + 'static)>`
|
||||
found struct `std::boxed::Box<dyn std::ops::Fn(_)>`
|
||||
= note: expected trait object `dyn for<'r> std::ops::Fn(&'r i32)`
|
||||
found trait object `dyn std::ops::Fn(&i32)`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,12 @@ impl<'a> Trait<'a> for Type {
|
|||
}
|
||||
|
||||
pub fn break_me<T, F>(f: F)
|
||||
where T: for<'b> Trait<'b>,
|
||||
F: for<'b> FnMut(<T as Trait<'b>>::Assoc) {
|
||||
where
|
||||
T: for<'b> Trait<'b>,
|
||||
F: for<'b> FnMut(<T as Trait<'b>>::Assoc),
|
||||
{
|
||||
break_me::<Type, fn(_)>;
|
||||
//~^ ERROR: type mismatch in function arguments
|
||||
//~| ERROR: type mismatch resolving
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,18 @@
|
|||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/issue-43623.rs:14:5
|
||||
--> $DIR/issue-43623.rs:16:5
|
||||
|
|
||||
LL | pub fn break_me<T, F>(f: F)
|
||||
| -------- required by a bound in this
|
||||
LL | where T: for<'b> Trait<'b>,
|
||||
LL | F: for<'b> FnMut(<T as Trait<'b>>::Assoc) {
|
||||
| -------------------------------------- required by this bound in `break_me`
|
||||
...
|
||||
LL | F: for<'b> FnMut(<T as Trait<'b>>::Assoc),
|
||||
| ------------------------------ required by this bound in `break_me`
|
||||
LL | {
|
||||
LL | break_me::<Type, fn(_)>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected signature of `for<'b> fn(<Type as Trait<'b>>::Assoc) -> _`
|
||||
| found signature of `fn(_) -> _`
|
||||
| expected signature of `fn(<Type as Trait<'b>>::Assoc) -> _`
|
||||
| found signature of `fn(()) -> _`
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'b> <fn(_) as std::ops::FnOnce<(<Type as Trait<'b>>::Assoc,)>>::Output == ()`
|
||||
--> $DIR/issue-43623.rs:14:5
|
||||
|
|
||||
LL | pub fn break_me<T, F>(f: F)
|
||||
| -------- required by a bound in this
|
||||
LL | where T: for<'b> Trait<'b>,
|
||||
LL | F: for<'b> FnMut(<T as Trait<'b>>::Assoc) {
|
||||
| ------------------------------ required by this bound in `break_me`
|
||||
LL | break_me::<Type, fn(_)>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter 'b, found concrete lifetime
|
||||
error: aborting due to previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0631.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
For more information about this error, try `rustc --explain E0631`.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer
|
|||
LL | let x = <fn (&())>::make_g();
|
||||
| ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())`
|
||||
|
|
||||
= note: the method `make_g` exists but the following trait bounds were not satisfied:
|
||||
`for<'r> fn(&'r ()): X`
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
note: `X` defines an item `make_g`, perhaps you need to implement it
|
||||
--> $DIR/issue-57362-2.rs:8:1
|
||||
|
|
|
|||
|
|
@ -7,11 +7,13 @@ impl<'a> Trait<'a> for () {
|
|||
}
|
||||
|
||||
pub fn foo<T, F>(_: T, _: F)
|
||||
where T: for<'a> Trait<'a>,
|
||||
F: for<'a> FnMut(<T as Trait<'a>>::Item) {}
|
||||
where
|
||||
T: for<'a> Trait<'a>,
|
||||
F: for<'a> FnMut(<T as Trait<'a>>::Item),
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo((), drop)
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
//~| ERROR type mismatch resolving
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,18 @@
|
|||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/issue-60283.rs:14:13
|
||||
--> $DIR/issue-60283.rs:17:13
|
||||
|
|
||||
LL | pub fn foo<T, F>(_: T, _: F)
|
||||
| --- required by a bound in this
|
||||
LL | where T: for<'a> Trait<'a>,
|
||||
LL | F: for<'a> FnMut(<T as Trait<'a>>::Item) {}
|
||||
| ------------------------------------- required by this bound in `foo`
|
||||
...
|
||||
LL | F: for<'a> FnMut(<T as Trait<'a>>::Item),
|
||||
| ----------------------------- required by this bound in `foo`
|
||||
...
|
||||
LL | foo((), drop)
|
||||
| ^^^^
|
||||
| |
|
||||
| expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
|
||||
| found signature of `fn(_) -> _`
|
||||
| expected signature of `fn(<() as Trait<'a>>::Item) -> _`
|
||||
| found signature of `fn(()) -> _`
|
||||
|
||||
error[E0271]: type mismatch resolving `for<'a> <fn(_) {std::mem::drop::<_>} as std::ops::FnOnce<(<() as Trait<'a>>::Item,)>>::Output == ()`
|
||||
--> $DIR/issue-60283.rs:14:5
|
||||
|
|
||||
LL | pub fn foo<T, F>(_: T, _: F)
|
||||
| --- required by a bound in this
|
||||
LL | where T: for<'a> Trait<'a>,
|
||||
LL | F: for<'a> FnMut(<T as Trait<'a>>::Item) {}
|
||||
| ----------------------------- required by this bound in `foo`
|
||||
...
|
||||
LL | foo((), drop)
|
||||
| ^^^ expected bound lifetime parameter 'a, found concrete lifetime
|
||||
error: aborting due to previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0631.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
For more information about this error, try `rustc --explain E0631`.
|
||||
|
|
|
|||
|
|
@ -4,23 +4,19 @@
|
|||
// longer get an error, because we recognize these two types as
|
||||
// equivalent!
|
||||
//
|
||||
// Whoops -- now that we reinstituted the leak-check, we get an error
|
||||
// again.
|
||||
// check-pass
|
||||
|
||||
fn foo(
|
||||
x: fn(&u8, &u8),
|
||||
y: for<'a> fn(&'a u8, &'a u8),
|
||||
) {
|
||||
fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) {
|
||||
// The two types above are actually equivalent. With the older
|
||||
// leak check, though, we didn't consider them as equivalent, and
|
||||
// hence we gave errors. But now we've fixed that.
|
||||
let z = match 22 {
|
||||
0 => x,
|
||||
_ => y, //~ ERROR `match` arms have incompatible types
|
||||
_ => y,
|
||||
};
|
||||
}
|
||||
|
||||
fn bar(
|
||||
x: fn(&u8, &u8),
|
||||
y: for<'a> fn(&'a u8, &'a u8),
|
||||
) {
|
||||
fn foo_cast(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) {
|
||||
let z = match 22 {
|
||||
// No error with an explicit cast:
|
||||
0 => x as for<'a> fn(&'a u8, &'a u8),
|
||||
|
|
@ -28,5 +24,4 @@ fn bar(
|
|||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
fn main() {}
|
||||
8
src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr
Normal file
8
src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/old-lub-glb-hr-noteq1.rs:11:14
|
||||
|
|
||||
LL | _ => y,
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
24
src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs
Normal file
24
src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Test taking the LUB of two function types that are not equatable but where one is more
|
||||
// general than the other. Test the case where the more general type (`x`) is the first
|
||||
// match arm specifically.
|
||||
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
|
||||
// But we can *upcast* explicitly the type of `x` and figure
|
||||
// things out:
|
||||
let z = match 22 {
|
||||
0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8,
|
||||
_ => y,
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
18
src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr
Normal file
18
src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/old-lub-glb-hr-noteq1.rs:11: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 | | };
|
||||
| |_____- `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`.
|
||||
33
src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs
Normal file
33
src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Test taking the LUB of two function types that are not equatable but where
|
||||
// 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
|
||||
// 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.
|
||||
//
|
||||
// ignore-compare-mode-nll
|
||||
|
||||
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 => y,
|
||||
_ => x, //~ ERROR `match` arms have incompatible types
|
||||
};
|
||||
}
|
||||
|
||||
fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
|
||||
// But we can *upcast* explicitly the type of `x` and figure
|
||||
// things out:
|
||||
let z = match 22 {
|
||||
0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8,
|
||||
_ => y,
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
18
src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr
Normal file
18
src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/old-lub-glb-hr-noteq2.rs:20: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 | | };
|
||||
| |_____- `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`.
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/old-lub-glb-hr.rs:16:14
|
||||
|
|
||||
LL | let z = match 22 {
|
||||
| _____________-
|
||||
LL | | 0 => x,
|
||||
| | - this is found to be of type `for<'r, 's> fn(&'r u8, &'s u8)`
|
||||
LL | | _ => y,
|
||||
| | ^ expected bound lifetime parameter, found concrete lifetime
|
||||
LL | | };
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
= note: expected type `for<'r, 's> fn(&'r u8, &'s u8)`
|
||||
found fn pointer `for<'a> fn(&'a u8, &'a u8)`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue