diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2020-06-23 00:33:52 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-06-23 00:33:52 -0700 |
| commit | 903823c59bcb9890df2a6fadcf7aa22f74eed67f (patch) | |
| tree | 41f5b5c6c8efb14b2306718f74250a5a6c61d956 | |
| parent | 59e87c0b81dd7f42d03f9b8d10cf3636feff9dd0 (diff) | |
| parent | d57689f9cde9a7066ffc8ca1125ea7e0d23df2c5 (diff) | |
| download | rust-903823c59bcb9890df2a6fadcf7aa22f74eed67f.tar.gz rust-903823c59bcb9890df2a6fadcf7aa22f74eed67f.zip | |
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
```
135 files changed, 2143 insertions, 1250 deletions
diff --git a/src/librustc_infer/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs index 0499dc9ed22..b6251e34008 100644 --- a/src/librustc_infer/infer/higher_ranked/mod.rs +++ b/src/librustc_infer/infer/higher_ranked/mod.rs @@ -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, ) } diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 91f4b3323f3..8f8ce03d638 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -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(()) }) } diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index 8de89251006..2350c28dfaa 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -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) { diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs index 91c39a0e78f..32e708bf52b 100644 --- a/src/librustc_infer/infer/region_constraints/leak_check.rs +++ b/src/librustc_infer/infer/region_constraints/leak_check.rs @@ -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,), - }; - - // 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 tainted_regions = taint_set.into_set(); - - // 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; - } - - 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) - }); - } + let universe_at_start_of_snapshot = snapshot.universe; + if universe_at_start_of_snapshot == max_universe { + return Ok(()); } + 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(()) } } -#[derive(Debug)] -struct TaintSet<'tcx> { - directions: TaintDirections, - regions: FxHashSet<ty::Region<'tcx>>, +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<'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 } +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 + ); + self.scc_universes[scc].take_min(universe, region); + + // 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)?; + } + } + } + + Ok(()) } - fn fixed_point<'a>( + // 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, - tcx: TyCtxt<'tcx>, - undo_log: impl IntoIterator<Item = &'a UndoLog<'tcx>> + Clone, - verifys: &[Verify<'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(..) => {} + 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); + } + }; + + Ok(()) + } + + /// 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 into_set(self) -> FxHashSet<ty::Region<'tcx>> { - self.regions + fn placeholder_error( + &self, + placeholder1: ty::PlaceholderRegion, + placeholder2: ty::PlaceholderRegion, + ) -> TypeError<'tcx> { + self.error(placeholder1, self.tcx.mk_region(ty::RePlaceholder(placeholder2))) } - fn len(&self) -> usize { - self.regions.len() + 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); + } } +} - 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); - } +// 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({})" + } +} - if self.directions.outgoing { - if self.regions.contains(&source) { - self.regions.insert(target); +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 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, + { + 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 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)) + } } diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index ed04ee02b72..0f3f3db8679 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -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)] diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs index 7ff12820db8..285d9ed6469 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -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), diff --git a/src/librustc_trait_selection/traits/coherence.rs b/src/librustc_trait_selection/traits/coherence.rs index 706cbf058b7..3ec7fe2bf25 100644 --- a/src/librustc_trait_selection/traits/coherence.rs +++ b/src/librustc_trait_selection/traits/coherence.rs @@ -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); diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 574d50a4fcc..bc696214cbc 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -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) }) } diff --git a/src/librustc_trait_selection/traits/select/candidate_assembly.rs b/src/librustc_trait_selection/traits/select/candidate_assembly.rs index 9045451056b..4dab5814f7b 100644 --- a/src/librustc_trait_selection/traits/select/candidate_assembly.rs +++ b/src/librustc_trait_selection/traits/select/candidate_assembly.rs @@ -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)); } }); diff --git a/src/librustc_trait_selection/traits/select/confirmation.rs b/src/librustc_trait_selection/traits/select/confirmation.rs index 50c04e8fc34..834bf17227d 100644 --- a/src/librustc_trait_selection/traits/select/confirmation.rs +++ b/src/librustc_trait_selection/traits/select/confirmation.rs @@ -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); diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs index 076bdad423a..cff5efbfd0f 100644 --- a/src/librustc_trait_selection/traits/select/mod.rs +++ b/src/librustc_trait_selection/traits/select/mod.rs @@ -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 { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index dec53c369bb..b6cd8da2362 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -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(); diff --git a/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir b/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir index 9742530bd81..aeb38f3f910 100644 --- a/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir +++ b/src/test/mir-opt/address-of/rustc.address_of_reborrow.SimplifyCfg-initial.after.mir @@ -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 diff --git a/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr b/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr new file mode 100644 index 00000000000..25e9f726ba5 --- /dev/null +++ b/src/test/ui/associated-types/associated-types-eq-hr.nll.stderr @@ -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`. diff --git a/src/test/ui/associated-types/associated-types-eq-hr.rs b/src/test/ui/associated-types/associated-types-eq-hr.rs index e6afa3f71c2..fb391913c32 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.rs +++ b/src/test/ui/associated-types/associated-types-eq-hr.rs @@ -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() {} diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 58d72746e76..127ab867355 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -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`. diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr index 71a533a36f4..4fc336122fa 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.nll.stderr @@ -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` diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr index 5009e0868a7..9462121bdf2 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.krisskross.stderr @@ -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 diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr index 8f445acf2b9..2156ecb1739 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.ok.stderr @@ -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 diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr index c39030fbed1..44850df7b2f 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.nll.stderr @@ -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` diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr index 65d16440ac9..64b57223908 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr @@ -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 diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs index 23d873212ed..0034d796826 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs @@ -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] diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr index f74d4ba73bf..db82c9fd437 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.nll.stderr @@ -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` diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index 0a05fc6bb82..ef57f9e0bc4 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -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<'_>` diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr new file mode 100644 index 00000000000..2e03986a9ed --- /dev/null +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/higher-ranked-projection.rs:25:5 + | +LL | foo(()); + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index 3b3e4c3ea11..811c9a8f5e1 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -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`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index 5315e21b0f5..1b5476d4c36 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.rs +++ b/src/test/ui/associated-types/higher-ranked-projection.rs @@ -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 } diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr index 97fdb76dd11..64a0b52a1fa 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr @@ -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(&u32), y| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _` - | | - | expected signature of `fn(fn(&'a u32), &i32) -> _` +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[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:37:5 +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:16:49 | -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 | 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| {}); + | ^ + +error: higher-ranked subtype error + --> $DIR/expect-fn-supply-fn.rs:39:50 + | 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`. diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs index a4e43da91ba..c81c40c18b4 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -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() {} diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index fae41c4114a..0de15dfa735 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -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) -> _` + | ^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `fn(&u32)` + found fn pointer `for<'r> fn(&'r u32)` -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:37:5 +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) -> _` + | ^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r> fn(&'r u32)` + found fn pointer `fn(&'x u32)` -error[E0631]: type mismatch in closure arguments - --> $DIR/expect-fn-supply-fn.rs:46:5 +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`. diff --git a/src/test/ui/closures/issue-41366.rs b/src/test/ui/closures/issue-41366.rs index 5cae0e76d1a..af1e37ba867 100644 --- a/src/test/ui/closures/issue-41366.rs +++ b/src/test/ui/closures/issue-41366.rs @@ -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 } diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr index 2f2871e9f0e..9c4b7d529ef 100644 --- a/src/test/ui/closures/issue-41366.stderr +++ b/src/test/ui/closures/issue-41366.stderr @@ -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 2 previous errors +error: aborting due to previous error -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`. diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs new file mode 100644 index 00000000000..99f805f7f0f --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.rs @@ -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() {} diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr new file mode 100644 index 00000000000..49271edf8e5 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr @@ -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`. diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.rs b/src/test/ui/coherence/coherence-fn-implied-bounds.rs new file mode 100644 index 00000000000..4539af9a32e --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-implied-bounds.rs @@ -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() {} diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.stderr b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr new file mode 100644 index 00000000000..a3e7f0bcde3 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr @@ -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 + diff --git a/src/test/ui/coherence/coherence-fn-inputs.rs b/src/test/ui/coherence/coherence-fn-inputs.rs new file mode 100644 index 00000000000..3afec5c5459 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-inputs.rs @@ -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() {} diff --git a/src/test/ui/coherence/coherence-fn-inputs.stderr b/src/test/ui/coherence/coherence-fn-inputs.stderr new file mode 100644 index 00000000000..56ab873a393 --- /dev/null +++ b/src/test/ui/coherence/coherence-fn-inputs.stderr @@ -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`. diff --git a/src/test/ui/coherence/coherence-free-vs-bound-region.rs b/src/test/ui/coherence/coherence-free-vs-bound-region.rs new file mode 100644 index 00000000000..2f5c49d293d --- /dev/null +++ b/src/test/ui/coherence/coherence-free-vs-bound-region.rs @@ -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() {} diff --git a/src/test/ui/coherence/coherence-free-vs-bound-region.stderr b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr new file mode 100644 index 00000000000..97aa4912721 --- /dev/null +++ b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr @@ -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 + diff --git a/src/test/ui/coherence/coherence-wasm-bindgen.rs b/src/test/ui/coherence/coherence-wasm-bindgen.rs new file mode 100644 index 00000000000..ee09a72449b --- /dev/null +++ b/src/test/ui/coherence/coherence-wasm-bindgen.rs @@ -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() {} diff --git a/src/test/ui/coherence/coherence-wasm-bindgen.stderr b/src/test/ui/coherence/coherence-wasm-bindgen.stderr new file mode 100644 index 00000000000..c77483bb847 --- /dev/null +++ b/src/test/ui/coherence/coherence-wasm-bindgen.stderr @@ -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 + diff --git a/src/test/ui/generator/resume-arg-late-bound.nll.stderr b/src/test/ui/generator/resume-arg-late-bound.nll.stderr new file mode 100644 index 00000000000..7d712191924 --- /dev/null +++ b/src/test/ui/generator/resume-arg-late-bound.nll.stderr @@ -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 + diff --git a/src/test/ui/generator/resume-arg-late-bound.rs b/src/test/ui/generator/resume-arg-late-bound.rs index 87b1f1a065b..a8f657eaabe 100644 --- a/src/test/ui/generator/resume-arg-late-bound.rs +++ b/src/test/ui/generator/resume-arg-late-bound.rs @@ -13,5 +13,6 @@ fn main() { *arg = true; }; test(gen); - //~^ ERROR type mismatch in function arguments + //~^ ERROR mismatched types + //~| ERROR mismatched types } diff --git a/src/test/ui/generator/resume-arg-late-bound.stderr b/src/test/ui/generator/resume-arg-late-bound.stderr index ffa440daed8..c379d9eae8e 100644 --- a/src/test/ui/generator/resume-arg-late-bound.stderr +++ b/src/test/ui/generator/resume-arg-late-bound.stderr @@ -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[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>` -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0631`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr new file mode 100644 index 00000000000..d5343566633 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr @@ -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 + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index b91798fa123..92a85825030 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -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>` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr index 45f53d4fe99..94837556610 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_vs_bound_a.stderr @@ -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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr index 6aba6466fad..94837556610 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_a.stderr @@ -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 | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr index 6aba6466fad..94837556610 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_bound_b.stderr @@ -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 | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr new file mode 100644 index 00000000000..f1156093967 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr @@ -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 + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr index c3e4f6d2ed0..98f5bff7327 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -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)>` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr index 4d7b86027f5..94837556610 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_b_vs_bound_co_a.stderr @@ -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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr index 7f0a4197dd7..94837556610 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_co_b_ret_contra_a.stderr @@ -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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr index 6aba6466fad..94837556610 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_co_a_vs_bound_co_b.stderr @@ -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 | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr index c12e543a44e..94837556610 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_contra_a_contra_b_ret_co_a.stderr @@ -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`. diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr new file mode 100644 index 00000000000..4541c462ee0 --- /dev/null +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.nll.stderr @@ -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 + diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index 460356856bd..100ba6ac27e 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -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>)>` diff --git a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr index 6aba6466fad..94837556610 100644 --- a/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.bound_inv_a_vs_bound_inv_b.stderr @@ -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 | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr index 6b5e7a5a634..af5cf41be0a 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.nll.stderr @@ -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) diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr index fc3643306e6..3c8af20e50c 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr @@ -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 diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr index 6aba6466fad..94837556610 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_x.stderr @@ -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 | | } | |_^ diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr index 7c0770924da..75d7e0e46b7 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.nll.stderr @@ -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) diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr index 0dde27788f6..7b4cdd4a419 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr @@ -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 diff --git a/src/test/ui/hr-subtype/hr-subtype.rs b/src/test/ui/hr-subtype/hr-subtype.rs index b31f198bd97..ad9500eedca 100644 --- a/src/test/ui/hr-subtype/hr-subtype.rs +++ b/src/test/ui/hr-subtype/hr-subtype.rs @@ -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 } diff --git a/src/test/ui/hr-subtype/return-static.rs b/src/test/ui/hr-subtype/return-static.rs new file mode 100644 index 00000000000..6455854f34d --- /dev/null +++ b/src/test/ui/hr-subtype/return-static.rs @@ -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); +} diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr new file mode 100644 index 00000000000..f290a93326f --- /dev/null +++ b/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr @@ -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 + diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 7250935ea29..45573814d13 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -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`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr new file mode 100644 index 00000000000..11390d9e2d2 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr @@ -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 + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr index 328e98657ef..9914783d976 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr @@ -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)` diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr new file mode 100644 index 00000000000..a4c3ffd1f6c --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr @@ -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 + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs index 4c1d4d28a09..921061916fc 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs @@ -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 } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr index 7a7285d3d76..fe8209d054c 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.stderr @@ -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`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs index 95b57d6c5bb..f95496a6c3c 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs @@ -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 } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr deleted file mode 100644 index 1e335f9ee96..00000000000 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.stderr +++ /dev/null @@ -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`. diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr new file mode 100644 index 00000000000..e2a399b2faa --- /dev/null +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr @@ -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 + diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs index 827a68beee8..b1b7ec6bcf1 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs @@ -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 } diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index 9174ea4d841..720e2276d53 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -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`. diff --git a/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr new file mode 100644 index 00000000000..8901a1b4681 --- /dev/null +++ b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr @@ -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 + diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 4fa40462477..5e3014317f5 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -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`. diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr index c0e3fd3cf46..90a7cadca41 100644 --- a/src/test/ui/hrtb/issue-30786.migrate.stderr +++ b/src/test/ui/hrtb/issue-30786.migrate.stderr @@ -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`. diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr index c736c5479f8..90a7cadca41 100644 --- a/src/test/ui/hrtb/issue-30786.nll.stderr +++ b/src/test/ui/hrtb/issue-30786.nll.stderr @@ -1,56 +1,43 @@ -error: higher-ranked subtype error - --> $DIR/issue-30786.rs:108:15 - | -LL | let map = source.map(|x: &_| x); - | ^^^^^^^^^^^^^^^^^^^^^ - -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:114:18 - | -LL | let filter = map.filter(|x: &_| true); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -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: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[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 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]>` + | + = 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[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`. diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs index c656f843065..8ce5c090b54 100644 --- a/src/test/ui/hrtb/issue-30786.rs +++ b/src/test/ui/hrtb/issue-30786.rs @@ -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() { +fn identity<T>(x: &T) -> &T { + x +} + +fn variant1() { 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 + + // 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() {} diff --git a/src/test/ui/hrtb/issue-46989.nll.stderr b/src/test/ui/hrtb/issue-46989.nll.stderr new file mode 100644 index 00000000000..6c127b92d97 --- /dev/null +++ b/src/test/ui/hrtb/issue-46989.nll.stderr @@ -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 + diff --git a/src/test/ui/hrtb/issue-46989.rs b/src/test/ui/hrtb/issue-46989.rs index 2c859055458..4a09f4be156 100644 --- a/src/test/ui/hrtb/issue-46989.rs +++ b/src/test/ui/hrtb/issue-46989.rs @@ -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 } diff --git a/src/test/ui/hrtb/issue-46989.stderr b/src/test/ui/hrtb/issue-46989.stderr index 0a7382c4dd8..c85c37ff923 100644 --- a/src/test/ui/hrtb/issue-46989.stderr +++ b/src/test/ui/hrtb/issue-46989.stderr @@ -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`. diff --git a/src/test/ui/issues/issue-40000.nll.stderr b/src/test/ui/issues/issue-40000.nll.stderr new file mode 100644 index 00000000000..f673fbae8b7 --- /dev/null +++ b/src/test/ui/issues/issue-40000.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/issue-40000.rs:6:9 + | +LL | foo(bar); + | ^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr index 983fdb13083..3eb3482ac91 100644 --- a/src/test/ui/issues/issue-40000.stderr +++ b/src/test/ui/issues/issue-40000.stderr @@ -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 diff --git a/src/test/ui/issues/issue-43623.rs b/src/test/ui/issues/issue-43623.rs index b259e9e269d..99cae46fd9c 100644 --- a/src/test/ui/issues/issue-43623.rs +++ b/src/test/ui/issues/issue-43623.rs @@ -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() {} diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr index 99fb2a1f5d0..80aca482b3d 100644 --- a/src/test/ui/issues/issue-43623.stderr +++ b/src/test/ui/issues/issue-43623.stderr @@ -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 2 previous errors +error: aborting due to previous error -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`. diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index 2edc0097464..47cc64ec470 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -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 diff --git a/src/test/ui/issues/issue-60283.rs b/src/test/ui/issues/issue-60283.rs index e5a9caa32fa..9c2b2dc9f4d 100644 --- a/src/test/ui/issues/issue-60283.rs +++ b/src/test/ui/issues/issue-60283.rs @@ -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 } diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index e74a34e247a..ad679bfa220 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -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(_) -> _` - -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 + | expected signature of `fn(<() as Trait<'a>>::Item) -> _` + | found signature of `fn(()) -> _` -error: aborting due to 2 previous errors +error: aborting due to previous error -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`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.rs b/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs index bc7b787cd65..fbf4aee0204 100644 --- a/src/test/ui/lub-glb/old-lub-glb-hr.rs +++ b/src/test/ui/lub-glb/old-lub-glb-hr-eq.rs @@ -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() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr new file mode 100644 index 00000000000..b95e247d2a8 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nll.stderr @@ -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 + diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs new file mode 100644 index 00000000000..918542d471b --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.rs @@ -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() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr new file mode 100644 index 00000000000..305e952d604 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.stderr @@ -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`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs new file mode 100644 index 00000000000..4bdd05b4f92 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.rs @@ -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() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr new file mode 100644 index 00000000000..252e13aada0 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-hr-noteq2.stderr @@ -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`. diff --git a/src/test/ui/lub-glb/old-lub-glb-hr.stderr b/src/test/ui/lub-glb/old-lub-glb-hr.stderr deleted file mode 100644 index 6d5d5117469..00000000000 --- a/src/test/ui/lub-glb/old-lub-glb-hr.stderr +++ /dev/null @@ -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`. diff --git a/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr new file mode 100644 index 00000000000..51bf96f3233 --- /dev/null +++ b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/old-lub-glb-object.rs:10:14 + | +LL | _ => y, + | ^ + +error: higher-ranked subtype error + --> $DIR/old-lub-glb-object.rs:10:14 + | +LL | _ => y, + | ^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/lub-glb/old-lub-glb-object.rs b/src/test/ui/lub-glb/old-lub-glb-object.rs index 63bbae59991..39d351c2355 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.rs +++ b/src/test/ui/lub-glb/old-lub-glb-object.rs @@ -1,22 +1,17 @@ // Test that we give a note when the old LUB/GLB algorithm would have // succeeded but the new code (which is stricter) gives an error. -trait Foo<T, U> { } +trait Foo<T, U> {} -fn foo( - x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, - y: &dyn for<'a> Foo<&'a u8, &'a u8>, -) { +fn foo(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) { let z = match 22 { + //~^ ERROR mismatched types 0 => x, - _ => y, //~ ERROR `match` arms have incompatible types + _ => y, }; } -fn bar( - x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, - y: &dyn for<'a> Foo<&'a u8, &'a u8>, -) { +fn bar(x: &dyn for<'a, 'b> Foo<&'a u8, &'b u8>, y: &dyn for<'a> Foo<&'a u8, &'a u8>) { // Accepted with explicit case: let z = match 22 { 0 => x as &dyn for<'a> Foo<&'a u8, &'a u8>, @@ -24,5 +19,4 @@ fn bar( }; } -fn main() { -} +fn main() {} diff --git a/src/test/ui/lub-glb/old-lub-glb-object.stderr b/src/test/ui/lub-glb/old-lub-glb-object.stderr index 65c797f6b19..6eabe5eaeee 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.stderr @@ -1,17 +1,16 @@ -error[E0308]: `match` arms have incompatible types - --> $DIR/old-lub-glb-object.rs:12:14 +error[E0308]: mismatched types + --> $DIR/old-lub-glb-object.rs:7:13 | LL | let z = match 22 { - | _____________- + | _____________^ +LL | | LL | | 0 => x, - | | - this is found to be of type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` LL | | _ => y, - | | ^ expected bound lifetime parameter 'a, found concrete lifetime LL | | }; - | |_____- `match` arms have incompatible types + | |_____^ one type is more general than the other | - = note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>` - found reference `&dyn for<'a> Foo<&'a u8, &'a u8>` + = note: expected trait object `dyn for<'a, 'b> Foo<&'a u8, &'b u8>` + found trait object `dyn for<'a> Foo<&'a u8, &'a u8>` error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr new file mode 100644 index 00000000000..6ed91b20ab8 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.nll.stderr @@ -0,0 +1,27 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:3:14 + | +LL | a.iter().map(|_: (u32, u32)| 45); + | ^^^ ------------------ found signature of `fn((u32, u32)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:4:14 + | +LL | a.iter().map(|_: &(u16, u16)| 45); + | ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:5:14 + | +LL | a.iter().map(|_: (u16, u16)| 45); + | ^^^ ------------------ found signature of `fn((u16, u16)) -> _` + | | + | expected signature of `fn(&(u32, u32)) -> _` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index 521bd3695df..e278049c8cc 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -7,6 +7,9 @@ fn main() { fn baz<F: Fn(*mut &u32)>(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { - baz(f); //~ ERROR type mismatch - //~| ERROR type mismatch + baz(f); + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 69a4b458ebf..664fa4bcaf3 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -22,28 +22,43 @@ LL | a.iter().map(|_: (u16, u16)| 45); | | | expected signature of `fn(&(u32, u32)) -> _` -error[E0631]: type mismatch in function arguments - --> $DIR/closure-arg-type-mismatch.rs:10:9 +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | fn baz<F: Fn(*mut &u32)>(_: F) {} - | ------------- required by this bound in `baz` -LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); - | ^ - | | - | expected signature of `for<'r> fn(*mut &'r u32) -> _` - | found signature of `fn(*mut &'a u32) -> _` + | ^^^ one type is more general than the other + | + = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` + found type `std::ops::Fn<(*mut &'a u32,)>` + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^ one type is more general than the other + | + = note: expected type `std::ops::FnOnce<(*mut &u32,)>` + found type `std::ops::FnOnce<(*mut &'a u32,)>` -error[E0271]: type mismatch resolving `for<'r> <fn(*mut &'a u32) as std::ops::FnOnce<(*mut &'r u32,)>>::Output == ()` +error[E0308]: mismatched types --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | fn baz<F: Fn(*mut &u32)>(_: F) {} - | ------------- required by this bound in `baz` -LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); - | ^^^ expected bound lifetime parameter, found concrete lifetime + | ^^^ one type is more general than the other + | + = note: expected type `for<'r> std::ops::Fn<(*mut &'r u32,)>` + found type `std::ops::Fn<(*mut &'a u32,)>` + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^ one type is more general than the other + | + = note: expected type `std::ops::FnOnce<(*mut &u32,)>` + found type `std::ops::FnOnce<(*mut &'a u32,)>` -error: aborting due to 5 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0271, E0631. -For more information about an error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/closure-mismatch.nll.stderr b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr new file mode 100644 index 00000000000..745a61b866e --- /dev/null +++ b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); + | ^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/closure-mismatch.rs:8:5 + | +LL | baz(|_| ()); + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/mismatched_types/closure-mismatch.rs b/src/test/ui/mismatched_types/closure-mismatch.rs index 40a4641fe71..d2b78b4b7db 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-mismatch.rs @@ -5,6 +5,5 @@ impl<T: Fn(&())> Foo for T {} fn baz<T: Foo>(_: T) {} fn main() { - baz(|_| ()); //~ ERROR type mismatch - //~^ ERROR type mismatch + baz(|_| ()); //~ ERROR mismatched types } diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index 389b2157446..d6c17d125cf 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -1,28 +1,12 @@ -error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.rs:8:9: 8:15] as std::ops::FnOnce<(&'r (),)>>::Output == ()` +error[E0308]: mismatched types --> $DIR/closure-mismatch.rs:8:5 | -LL | fn baz<T: Foo>(_: T) {} - | --- required by this bound in `baz` -... LL | baz(|_| ()); - | ^^^ expected bound lifetime parameter, found concrete lifetime + | ^^^ one type is more general than the other | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` + = note: expected type `for<'r> std::ops::Fn<(&'r (),)>` + found type `std::ops::Fn<(&(),)>` -error[E0631]: type mismatch in closure arguments - --> $DIR/closure-mismatch.rs:8:5 - | -LL | fn baz<T: Foo>(_: T) {} - | --- required by this bound in `baz` -... -LL | baz(|_| ()); - | ^^^ ------ found signature of `fn(_) -> _` - | | - | expected signature of `for<'r> fn(&'r ()) -> _` - | - = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:8:9: 8:15]` - -error: aborting due to 2 previous errors +error: aborting due to previous error -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 E0308`. diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr new file mode 100644 index 00000000000..d762f55f9d5 --- /dev/null +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:5 + | +LL | want_G(baz); + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.rs b/src/test/ui/regions-fn-subtyping-return-static-fail.rs index 2dd0c9796e2..539221b5a04 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.rs +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.rs @@ -13,11 +13,11 @@ struct S; // Given 'cx, return 'cx type F = for<'cx> fn(&'cx S) -> &'cx S; -fn want_F(f: F) { } +fn want_F(f: F) {} // Given anything, return 'static type G = for<'cx> fn(&'cx S) -> &'static S; -fn want_G(f: G) { } +fn want_G(f: G) {} // Should meet both. fn foo(x: &S) -> &'static S { @@ -25,7 +25,7 @@ fn foo(x: &S) -> &'static S { } // Should meet both. -fn bar<'a,'b>(x: &'a S) -> &'b S { +fn bar<'a, 'b>(x: &'a S) -> &'b S { panic!() } @@ -37,7 +37,7 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); //~ ERROR mismatched types + want_F(bar); want_F(baz); } @@ -48,5 +48,4 @@ fn supply_G() { want_G(baz); //~ ERROR mismatched types } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr index 27704b3e0a8..c9ce936c7d4 100644 --- a/src/test/ui/regions-fn-subtyping-return-static-fail.stderr +++ b/src/test/ui/regions-fn-subtyping-return-static-fail.stderr @@ -1,21 +1,12 @@ error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static-fail.rs:40:12 - | -LL | want_F(bar); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx - | - = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'cx S` - found fn item `for<'a> fn(&'a S) -> &S {bar::<'_>}` - -error[E0308]: mismatched types --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:12 | LL | want_G(baz); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx + | ^^^ one type is more general than the other | = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S` - found fn item `for<'r> fn(&'r S) -> &'r S {baz}` + found fn pointer `for<'r> fn(&'r S) -> &'r S` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr index c3e8789a903..695f5506d5e 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr @@ -1,14 +1,40 @@ -error[E0308]: mismatched types - --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 159d32b50b0..b83e07663fa 100644 --- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -20,12 +20,10 @@ error[E0308]: mismatched types --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr index 2aadd8f4f8c..a28f7aa3e08 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr @@ -1,14 +1,46 @@ -error[E0308]: mismatched types - --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5 + | +LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:5 + | +LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y, z); + | ^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ----------------------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 + | +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index dda6129e195..c93f2890f11 100644 --- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -31,12 +31,10 @@ error[E0308]: mismatched types --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ----------------------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` - found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize) {a::<'_, '_, '_>}` + found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` error: aborting due to 4 previous errors diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.rs b/src/test/ui/regions/regions-fn-subtyping-return-static.rs index fa2cc37d05b..de14d5ba82a 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.rs +++ b/src/test/ui/regions/regions-fn-subtyping-return-static.rs @@ -5,6 +5,8 @@ // *ANY* lifetime and returns a reference with the 'static lifetime. // This can safely be considered to be an instance of `F` because all // lifetimes are sublifetimes of 'static. +// +// check-pass #![allow(dead_code)] #![allow(unused_variables)] @@ -14,11 +16,11 @@ struct S; // Given 'cx, return 'cx type F = for<'cx> fn(&'cx S) -> &'cx S; -fn want_F(f: F) { } +fn want_F(f: F) {} // Given anything, return 'static type G = for<'cx> fn(&'cx S) -> &'static S; -fn want_G(f: G) { } +fn want_G(f: G) {} // Should meet both. fn foo(x: &S) -> &'static S { @@ -26,7 +28,7 @@ fn foo(x: &S) -> &'static S { } // Should meet both. -fn bar<'a,'b>(x: &'a S) -> &'b S { +fn bar<'a, 'b>(x: &'a S) -> &'b S { panic!() } @@ -38,10 +40,9 @@ fn baz(x: &S) -> &S { fn supply_F() { want_F(foo); - want_F(bar); //~ ERROR mismatched types + want_F(bar); want_F(baz); } -pub fn main() { -} +pub fn main() {} diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static.stderr deleted file mode 100644 index a8a7e97e6ac..00000000000 --- a/src/test/ui/regions/regions-fn-subtyping-return-static.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/regions-fn-subtyping-return-static.rs:41:12 - | -LL | want_F(bar); - | ^^^ expected concrete lifetime, found bound lifetime parameter 'cx - | - = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'cx S` - found fn item `for<'a> fn(&'a S) -> &S {bar::<'_>}` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr index 434a3e47b49..37f7fcf2e33 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr @@ -1,14 +1,40 @@ -error[E0308]: mismatched types - --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: higher-ranked subtype error + --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: higher-ranked subtype error + --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12 | - = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr index 01f43aeebaf..2b2dd0dbbf2 100644 --- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -20,12 +20,10 @@ error[E0308]: mismatched types --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ expected concrete lifetime, found bound lifetime parameter - | | - | expected due to this + | ^ one type is more general than the other | = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` - found fn item `for<'r, 's> fn(&'r mut &isize, &'s mut &isize) {a::<'_, '_>}` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc1623.nll.stderr b/src/test/ui/rfc1623.nll.stderr new file mode 100644 index 00000000000..848d4fef1ab --- /dev/null +++ b/src/test/ui/rfc1623.nll.stderr @@ -0,0 +1,68 @@ +error[E0277]: `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely + --> $DIR/rfc1623.rs:21:1 + | +LL | / static SOME_STRUCT: &SomeStruct = &SomeStruct { +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |__^ `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely + | + = help: within `&SomeStruct`, the trait `std::marker::Sync` is not implemented for `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: required because it appears within the type `&dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: required because it appears within the type `SomeStruct` + = note: required because it appears within the type `&SomeStruct` + = note: shared static variables must have a type that implements `Sync` + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: higher-ranked subtype error + --> $DIR/rfc1623.rs:21:35 + | +LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { + | ___________________________________^ +LL | | foo: &Foo { bools: &[false, true] }, +LL | | bar: &Bar { bools: &[true, true] }, +LL | | f: &id, +LL | | +LL | | }; + | |_^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc1623.rs b/src/test/ui/rfc1623.rs index 55f5d0b94dc..aa6b1c0012c 100644 --- a/src/test/ui/rfc1623.rs +++ b/src/test/ui/rfc1623.rs @@ -8,23 +8,21 @@ fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 { static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); - struct SomeStruct<'x, 'y, 'z: 'x> { foo: &'x Foo<'z>, bar: &'x Bar<'z>, - f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Bar<'b>, + f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Foo<'b>, } fn id<T>(t: T) -> T { t } -static SOME_STRUCT: &SomeStruct = SomeStruct { //~ ERROR mismatched types +static SOME_STRUCT: &SomeStruct = &SomeStruct { foo: &Foo { bools: &[false, true] }, bar: &Bar { bools: &[true, true] }, f: &id, - //~^ ERROR type mismatch in function arguments - //~| ERROR type mismatch resolving + //~^ ERROR mismatched types }; // very simple test for a 'static static with default lifetime diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr index ca956004ef7..2efc58ac381 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.stderr @@ -1,46 +1,12 @@ error[E0308]: mismatched types - --> $DIR/rfc1623.rs:22:35 - | -LL | static SOME_STRUCT: &SomeStruct = SomeStruct { - | ___________________________________^ -LL | | foo: &Foo { bools: &[false, true] }, -LL | | bar: &Bar { bools: &[true, true] }, -LL | | f: &id, -LL | | -LL | | -LL | | }; - | |_^ expected `&SomeStruct<'static, 'static, 'static>`, found struct `SomeStruct` - | -help: consider borrowing here - | -LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { -LL | foo: &Foo { bools: &[false, true] }, -LL | bar: &Bar { bools: &[true, true] }, -LL | f: &id, -LL | -LL | - ... - -error[E0631]: type mismatch in function arguments - --> $DIR/rfc1623.rs:25:8 - | -LL | fn id<T>(t: T) -> T { - | ------------------- found signature of `fn(_) -> _` -... -LL | f: &id, - | ^^^ expected signature of `for<'a, 'b> fn(&'a Foo<'b>) -> _` - | - = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` - -error[E0271]: type mismatch resolving `for<'a, 'b> <fn(_) -> _ {id::<_>} as std::ops::FnOnce<(&'a Foo<'b>,)>>::Output == &'a Foo<'b>` - --> $DIR/rfc1623.rs:25:8 + --> $DIR/rfc1623.rs:24:8 | LL | f: &id, - | ^^^ expected bound lifetime parameter 'a, found concrete lifetime + | ^^^ one type is more general than the other | - = note: required for the cast to the object type `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` + = note: expected type `std::ops::FnOnce<(&'a Foo<'b>,)>` + found type `std::ops::FnOnce<(&Foo<'_>,)>` -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0271, E0308, E0631. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr new file mode 100644 index 00000000000..8c9cb742fac --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.nll.stderr @@ -0,0 +1,14 @@ +error: higher-ranked subtype error + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^^^ + +error: higher-ranked subtype error + --> $DIR/issue-57611-trait-alias.rs:21:9 + | +LL | |x| x + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs index 1c2051e7eae..41e019247c9 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.rs @@ -14,8 +14,8 @@ trait Foo { struct X; impl Foo for X { - type Bar = impl Baz<Self, Self>; //~ ERROR type mismatch in closure arguments - //~^ ERROR type mismatch resolving + type Bar = impl Baz<Self, Self>; + //~^ ERROR mismatched types fn bar(&self) -> Self::Bar { |x| x diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr index cc121ac89fb..cd637056c94 100644 --- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr @@ -1,23 +1,12 @@ -error[E0631]: type mismatch in closure arguments +error[E0308]: mismatched types --> $DIR/issue-57611-trait-alias.rs:17:16 | LL | type Bar = impl Baz<Self, Self>; - | ^^^^^^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(&'r X) -> _` -... -LL | |x| x - | ----- found signature of `fn(_) -> _` + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: the return type of a function must have a statically known size + = note: expected type `std::ops::FnOnce<(&X,)>` + found type `std::ops::FnOnce<(&X,)>` -error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-57611-trait-alias.rs:21:9: 21:14] as std::ops::FnOnce<(&'r X,)>>::Output == &'r X` - --> $DIR/issue-57611-trait-alias.rs:17:16 - | -LL | type Bar = impl Baz<Self, Self>; - | ^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime - | - = note: the return type of a function must have a statically known size - -error: aborting due to 2 previous errors +error: aborting due to previous error -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 E0308`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs index a6e26614a6a..e2082d4f78e 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.rs @@ -1,23 +1,29 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -unsafe fn square(x: &isize) -> isize { (*x) * (*x) } +unsafe fn square(x: &isize) -> isize { + (*x) * (*x) +} -fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 } +fn call_it<F: Fn(&isize) -> isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut<F: FnMut(&isize) -> isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once<F: FnOnce(&isize) -> isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -25,4 +31,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index b9ee9e46020..b06f745e7c1 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:21 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21 | -LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it<F: Fn(&isize) -> isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:21 - | -LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:25 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25 | -LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut<F: FnMut(&isize) -> isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:18:25 - | -LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-unsafe-extern-fn.rs:24:26 + --> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26 | -LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once<F: FnOnce(&isize) -> isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs index dd3b1afc39f..dd76c597d28 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.rs @@ -1,23 +1,29 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -extern "C" fn square(x: &isize) -> isize { (*x) * (*x) } +extern "C" fn square(x: &isize) -> isize { + (*x) * (*x) +} -fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 } +fn call_it<F: Fn(&isize) -> isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut<F: FnMut(&isize) -> isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once<F: FnOnce(&isize) -> isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -25,4 +31,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index 654b626cf65..8f6945cda80 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:12:21 + --> $DIR/unboxed-closures-wrong-abi.rs:20:21 | -LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it<F: Fn(&isize) -> isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:12:21 - | -LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:18:25 + --> $DIR/unboxed-closures-wrong-abi.rs:25:25 | -LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut<F: FnMut(&isize) -> isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:18:25 - | -LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-abi.rs:24:26 + --> $DIR/unboxed-closures-wrong-abi.rs:30:26 | -LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once<F: FnOnce(&isize) -> isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs index c689d792661..02e8b7b47ae 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -1,24 +1,30 @@ // Tests that unsafe extern fn pointers do not implement any Fn traits. -use std::ops::{Fn,FnMut,FnOnce}; +use std::ops::{Fn, FnMut, FnOnce}; -unsafe fn square(x: isize) -> isize { x * x } +unsafe fn square(x: isize) -> isize { + x * x +} // note: argument type here is `isize`, not `&isize` -fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 } -fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 } -fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 } +fn call_it<F: Fn(&isize) -> isize>(_: &F, _: isize) -> isize { + 0 +} +fn call_it_mut<F: FnMut(&isize) -> isize>(_: &mut F, _: isize) -> isize { + 0 +} +fn call_it_once<F: FnOnce(&isize) -> isize>(_: F, _: isize) -> isize { + 0 +} fn a() { let x = call_it(&square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn b() { let y = call_it_mut(&mut square, 22); //~^ ERROR E0277 - //~| ERROR expected } fn c() { @@ -26,4 +32,4 @@ fn c() { //~^ ERROR E0277 } -fn main() { } +fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index 434c8a579f6..93a645b485e 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -1,30 +1,19 @@ error[E0277]: expected a `std::ops::Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:21 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:21:21 | -LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 } - | ----------------- required by this bound in `call_it` +LL | fn call_it<F: Fn(&isize) -> isize>(_: &F, _: isize) -> isize { + | ------------------- required by this bound in `call_it` ... LL | let x = call_it(&square, 22); | ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | = help: the trait `for<'r> std::ops::Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:21 - | -LL | fn call_it<F:Fn(&isize)->isize>(_: &F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it` -... -LL | let x = call_it(&square, 22); - | ^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` - error[E0277]: expected a `std::ops::FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:25 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:26:25 | -LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 } - | -------------------- required by this bound in `call_it_mut` +LL | fn call_it_mut<F: FnMut(&isize) -> isize>(_: &mut F, _: isize) -> isize { + | ---------------------- required by this bound in `call_it_mut` ... LL | let y = call_it_mut(&mut square, 22); | ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` @@ -32,27 +21,16 @@ LL | let y = call_it_mut(&mut square, 22); = help: the trait `for<'r> std::ops::FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:19:25 - | -LL | fn call_it_mut<F:FnMut(&isize)->isize>(_: &mut F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_mut` -... -LL | let y = call_it_mut(&mut square, 22); - | ^^^^^^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` - -error[E0277]: expected a `std::ops::FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` - --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:25:26 + --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:31:26 | -LL | fn call_it_once<F:FnOnce(&isize)->isize>(_: F, _: isize) -> isize { 0 } - | ----- required by this bound in `call_it_once` +LL | fn call_it_once<F: FnOnce(&isize) -> isize>(_: F, _: isize) -> isize { + | ----------------------- required by this bound in `call_it_once` ... LL | let z = call_it_once(square, 22); | ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}` | - = help: the trait `std::ops::FnOnce<(&isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'r> std::ops::FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/where-for-self-2.nll.stderr b/src/test/ui/where-clauses/where-for-self-2.nll.stderr new file mode 100644 index 00000000000..d0c476dc6ec --- /dev/null +++ b/src/test/ui/where-clauses/where-for-self-2.nll.stderr @@ -0,0 +1,8 @@ +error: higher-ranked subtype error + --> $DIR/where-for-self-2.rs:23:5 + | +LL | foo(&X); + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/where-clauses/where-for-self-2.rs b/src/test/ui/where-clauses/where-for-self-2.rs index 31174fd4cf1..37c6954fd52 100644 --- a/src/test/ui/where-clauses/where-for-self-2.rs +++ b/src/test/ui/where-clauses/where-for-self-2.rs @@ -14,9 +14,11 @@ impl Bar for &'static u32 { } fn foo<T>(x: &T) - where for<'a> &'a T: Bar -{} +where + for<'a> &'a T: Bar, +{ +} fn main() { - foo(&X); //~ ERROR trait bound + foo(&X); //~ ERROR implementation of `Bar` is not general enough } diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index 9976243b200..30eb78b2da4 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -1,17 +1,16 @@ -error[E0277]: the trait bound `for<'a> &'a _: Bar` is not satisfied - --> $DIR/where-for-self-2.rs:21:5 +error: implementation of `Bar` is not general enough + --> $DIR/where-for-self-2.rs:23:5 | -LL | fn foo<T>(x: &T) - | --- required by a bound in this -LL | where for<'a> &'a T: Bar - | --- required by this bound in `foo` +LL | / trait Bar { +LL | | fn bar(&self); +LL | | } + | |_- trait `Bar` defined here ... -LL | foo(&X); - | ^^^ the trait `for<'a> Bar` is not implemented for `&'a _` +LL | foo(&X); + | ^^^ implementation of `Bar` is not general enough | - = help: the following implementations were found: - <&'static u32 as Bar> + = note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + = note: ...but `Bar` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0277`. |
