diff options
| author | bors <bors@rust-lang.org> | 2021-08-18 15:54:59 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-08-18 15:54:59 +0000 |
| commit | 3d0774d0dc98084d25d95cc1909a8051ebbd9cb1 (patch) | |
| tree | fc3a58189d33e8a6044f15dcd7705bc3f79be7b6 | |
| parent | 29d61427ac47dc16c83e1c66b929b1198a3ccc35 (diff) | |
| parent | 8343806ff5d130f2ad8e0bc9814694864dcb5397 (diff) | |
| download | rust-3d0774d0dc98084d25d95cc1909a8051ebbd9cb1.tar.gz rust-3d0774d0dc98084d25d95cc1909a8051ebbd9cb1.zip | |
Auto merge of #86700 - lqd:matthews-nll-hrtb-errors, r=nikomatsakis
Matthew's work on improving NLL's "higher-ranked subtype error"s This PR rebases `@matthewjasper's` [branch](https://github.com/matthewjasper/rust/tree/nll-hrtb-errors) which has great work to fix the obscure higher-ranked subtype errors that are tracked in #57374. These are a blocker to turning full NLLs on, and doing some internal cleanups to remove some of the old region code. The goal is so `@nikomatsakis` can take a look at this early, and I'll then do my best to help do the changes and followup work to land this work, and move closer to turning off the migration mode. I've only updated the branch and made it compile, removed a warning or two. r? `@nikomatsakis` (Here's the [zulip topic to discuss this](https://rust-lang.zulipchat.com/#narrow/stream/122657-t-compiler.2Fwg-nll/topic/.2357374.3A.20improving.20higher-ranked.20subtype.20errors.20via.20.2386700) that Niko wanted)
63 files changed, 1043 insertions, 345 deletions
diff --git a/Cargo.lock b/Cargo.lock index 65eec7f7a90..3420fe5e61c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4057,6 +4057,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", + "rustc_traits", "smallvec", "tracing", ] diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b628381d5aa..3d48d4c2fca 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1180,16 +1180,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | | // | elided as they were the same // not elided, they were different, but irrelevant + // + // For bound lifetimes, keep the names of the lifetimes, + // even if they are the same so that it's clear what's happening + // if we have something like + // + // for<'r, 's> fn(Inv<'r>, Inv<'s>) + // for<'r> fn(Inv<'r>, Inv<'r>) let lifetimes = sub1.regions().zip(sub2.regions()); for (i, lifetimes) in lifetimes.enumerate() { let l1 = lifetime_display(lifetimes.0); let l2 = lifetime_display(lifetimes.1); - if lifetimes.0 == lifetimes.1 { - values.0.push_normal("'_"); - values.1.push_normal("'_"); - } else { + if lifetimes.0 != lifetimes.1 { values.0.push_highlighted(l1); values.1.push_highlighted(l2); + } else if lifetimes.0.is_late_bound() { + values.0.push_normal(l1); + values.1.push_normal(l2); + } else { + values.0.push_normal("'_"); + values.1.push_normal("'_"); } self.push_comma(&mut values.0, &mut values.1, len, i); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 10217a5f574..9b9ded5c6ba 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1,4 +1,5 @@ pub use self::freshen::TypeFreshener; +pub use self::lexical_region_resolve::RegionResolutionError; pub use self::LateBoundRegionConversionTime::*; pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; @@ -1110,7 +1111,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// etc) this is the root universe U0. For inference variables or /// placeholders, however, it will return the universe which which /// they are associated. - fn universe_of_region(&self, r: ty::Region<'tcx>) -> ty::UniverseIndex { + pub fn universe_of_region(&self, r: ty::Region<'tcx>) -> ty::UniverseIndex { self.inner.borrow_mut().unwrap_region_constraints().universe(r) } @@ -1288,6 +1289,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { op(inner.unwrap_region_constraints().data()) } + pub fn region_var_origin(&self, vid: ty::RegionVid) -> RegionVariableOrigin { + let mut inner = self.inner.borrow_mut(); + let inner = &mut *inner; + inner + .region_constraint_storage + .as_mut() + .expect("regions already resolved") + .with_log(&mut inner.undo_log) + .var_origin(vid) + } + /// Takes ownership of the list of variable regions. This implies /// that all the region constraints have already been taken, and /// hence that `resolve_regions_and_report_errors` can never be @@ -1505,7 +1517,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.inner.borrow_mut().projection_cache().clear(); } - fn universe(&self) -> ty::UniverseIndex { + pub fn universe(&self) -> ty::UniverseIndex { self.universe.get() } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 7f4c33c5792..5adbfd469a4 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -445,6 +445,11 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { self.var_infos[vid].universe } + /// Returns the origin for the given variable. + pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin { + self.var_infos[vid].origin + } + fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) { // cannot add constraints once regions are resolved debug!("RegionConstraintCollector: add_constraint({:?})", constraint); diff --git a/compiler/rustc_mir/Cargo.toml b/compiler/rustc_mir/Cargo.toml index 7656cf38cc1..3049fb3b383 100644 --- a/compiler/rustc_mir/Cargo.toml +++ b/compiler/rustc_mir/Cargo.toml @@ -27,6 +27,7 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } +rustc_traits = { path = "../rustc_traits" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } rustc_apfloat = { path = "../rustc_apfloat" } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/bound_region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/bound_region_errors.rs new file mode 100644 index 00000000000..d0284dd0302 --- /dev/null +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/bound_region_errors.rs @@ -0,0 +1,341 @@ +use rustc_errors::DiagnosticBuilder; +use rustc_infer::infer::canonical::Canonical; +use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; +use rustc_infer::infer::region_constraints::Constraint; +use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _}; +use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt}; +use rustc_middle::ty::error::TypeError; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc_span::Span; +use rustc_trait_selection::traits::query::type_op; +use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _}; +use rustc_traits::type_op_prove_predicate_with_span; + +use std::fmt; +use std::rc::Rc; + +use crate::borrow_check::region_infer::values::RegionElement; +use crate::borrow_check::MirBorrowckCtxt; + +#[derive(Clone)] +crate struct UniverseInfo<'tcx>(UniverseInfoInner<'tcx>); + +/// What operation a universe was created for. +#[derive(Clone)] +enum UniverseInfoInner<'tcx> { + /// Relating two types which have binders. + RelateTys { expected: Ty<'tcx>, found: Ty<'tcx> }, + /// Created from performing a `TypeOp`. + TypeOp(Rc<dyn TypeOpInfo<'tcx> + 'tcx>), + /// Any other reason. + Other, +} + +impl UniverseInfo<'tcx> { + crate fn other() -> UniverseInfo<'tcx> { + UniverseInfo(UniverseInfoInner::Other) + } + + crate fn relate(expected: Ty<'tcx>, found: Ty<'tcx>) -> UniverseInfo<'tcx> { + UniverseInfo(UniverseInfoInner::RelateTys { expected, found }) + } + + crate fn report_error( + &self, + mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, + placeholder: ty::PlaceholderRegion, + error_element: RegionElement, + span: Span, + ) { + match self.0 { + UniverseInfoInner::RelateTys { expected, found } => { + let body_id = mbcx.infcx.tcx.hir().local_def_id_to_hir_id(mbcx.mir_def_id()); + let err = mbcx.infcx.report_mismatched_types( + &ObligationCause::misc(span, body_id), + expected, + found, + TypeError::RegionsPlaceholderMismatch, + ); + err.buffer(&mut mbcx.errors_buffer); + } + UniverseInfoInner::TypeOp(ref type_op_info) => { + type_op_info.report_error(mbcx, placeholder, error_element, span); + } + UniverseInfoInner::Other => { + // FIXME: This error message isn't great, but it doesn't show + // up in the existing UI tests. Consider investigating this + // some more. + mbcx.infcx + .tcx + .sess + .struct_span_err(span, "higher-ranked subtype error") + .buffer(&mut mbcx.errors_buffer); + } + } + } +} + +crate trait ToUniverseInfo<'tcx> { + fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx>; +} + +impl<'tcx> ToUniverseInfo<'tcx> + for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>> +{ + fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { + UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(PredicateQuery { + canonical_query: self, + base_universe, + }))) + } +} + +impl<'tcx, T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx> ToUniverseInfo<'tcx> + for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>> +{ + fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { + UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(NormalizeQuery { + canonical_query: self, + base_universe, + }))) + } +} + +impl<'tcx> ToUniverseInfo<'tcx> + for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>> +{ + fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { + // Ascribe user type isn't usually called on types that have different + // bound regions. + UniverseInfo::other() + } +} + +impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F, G>> { + fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { + // We can't rerun custom type ops. + UniverseInfo::other() + } +} + +#[allow(unused_lifetimes)] +trait TypeOpInfo<'tcx> { + /// Returns an error to be reported if rerunning the type op fails to + /// recover the error's cause. + fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx>; + + fn base_universe(&self) -> ty::UniverseIndex; + + fn nice_error( + &self, + tcx: TyCtxt<'tcx>, + span: Span, + placeholder_region: ty::Region<'tcx>, + error_region: Option<ty::Region<'tcx>>, + ) -> Option<DiagnosticBuilder<'tcx>>; + + fn report_error( + &self, + mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, + placeholder: ty::PlaceholderRegion, + error_element: RegionElement, + span: Span, + ) { + let tcx = mbcx.infcx.tcx; + let base_universe = self.base_universe(); + + let adjusted_universe = if let Some(adjusted) = + placeholder.universe.as_u32().checked_sub(base_universe.as_u32()) + { + adjusted + } else { + self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer); + return; + }; + + let placeholder_region = tcx.mk_region(ty::RePlaceholder(ty::Placeholder { + name: placeholder.name, + universe: adjusted_universe.into(), + })); + + let error_region = + if let RegionElement::PlaceholderRegion(error_placeholder) = error_element { + let adjusted_universe = + error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32()); + adjusted_universe.map(|adjusted| { + tcx.mk_region(ty::RePlaceholder(ty::Placeholder { + name: error_placeholder.name, + universe: adjusted.into(), + })) + }) + } else { + None + }; + + debug!(?placeholder_region); + + let nice_error = self.nice_error(tcx, span, placeholder_region, error_region); + + if let Some(nice_error) = nice_error { + nice_error.buffer(&mut mbcx.errors_buffer); + } else { + self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer); + } + } +} + +struct PredicateQuery<'tcx> { + canonical_query: + Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>, + base_universe: ty::UniverseIndex, +} + +impl TypeOpInfo<'tcx> for PredicateQuery<'tcx> { + fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); + err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate)); + err + } + + fn base_universe(&self) -> ty::UniverseIndex { + self.base_universe + } + + fn nice_error( + &self, + tcx: TyCtxt<'tcx>, + span: Span, + placeholder_region: ty::Region<'tcx>, + error_region: Option<ty::Region<'tcx>>, + ) -> Option<DiagnosticBuilder<'tcx>> { + tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| { + let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx); + type_op_prove_predicate_with_span(infcx, &mut *fulfill_cx, key, Some(span)); + try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region) + }) + } +} + +struct NormalizeQuery<'tcx, T> { + canonical_query: Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>, + base_universe: ty::UniverseIndex, +} + +impl<T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T> +where + T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx, +{ + fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); + err.note(&format!("could not normalize `{}`", self.canonical_query.value.value.value)); + err + } + + fn base_universe(&self) -> ty::UniverseIndex { + self.base_universe + } + + fn nice_error( + &self, + tcx: TyCtxt<'tcx>, + span: Span, + placeholder_region: ty::Region<'tcx>, + error_region: Option<ty::Region<'tcx>>, + ) -> Option<DiagnosticBuilder<'tcx>> { + tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| { + let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx); + + let mut selcx = SelectionContext::new(infcx); + + // FIXME(lqd): Unify and de-duplicate the following with the actual + // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the + // `ObligationCause`. The normalization results are currently different between + // `AtExt::normalize` used in the query and `normalize` called below: the former fails + // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check + // after #85499 lands to see if its fixes have erased this difference. + let (param_env, value) = key.into_parts(); + let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize( + &mut selcx, + param_env, + ObligationCause::dummy_with_span(span), + value.value, + ); + fulfill_cx.register_predicate_obligations(infcx, obligations); + + try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region) + }) + } +} + +fn try_extract_error_from_fulfill_cx<'tcx>( + mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>, + infcx: &InferCtxt<'_, 'tcx>, + placeholder_region: ty::Region<'tcx>, + error_region: Option<ty::Region<'tcx>>, +) -> Option<DiagnosticBuilder<'tcx>> { + let tcx = infcx.tcx; + + // We generally shouldn't have errors here because the query was + // already run, but there's no point using `delay_span_bug` + // when we're going to emit an error here anyway. + let _errors = fulfill_cx.select_all_or_error(infcx).err().unwrap_or_else(Vec::new); + + let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| { + debug!(?region_constraints); + region_constraints.constraints.iter().find_map(|(constraint, cause)| { + match *constraint { + Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => { + Some((sub, cause.clone())) + } + // FIXME: Should this check the universe of the var? + Constraint::VarSubReg(vid, sup) if sup == placeholder_region => { + Some((tcx.mk_region(ty::ReVar(vid)), cause.clone())) + } + _ => None, + } + }) + })?; + + debug!(?sub_region, ?cause); + let nice_error = match (error_region, sub_region) { + (Some(error_region), &ty::ReVar(vid)) => NiceRegionError::new( + infcx, + RegionResolutionError::SubSupConflict( + vid, + infcx.region_var_origin(vid), + cause.clone(), + error_region, + cause.clone(), + placeholder_region, + ), + ), + (Some(error_region), _) => NiceRegionError::new( + infcx, + RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region), + ), + // Note universe here is wrong... + (None, &ty::ReVar(vid)) => NiceRegionError::new( + infcx, + RegionResolutionError::UpperBoundUniverseConflict( + vid, + infcx.region_var_origin(vid), + infcx.universe_of_region(sub_region), + cause.clone(), + placeholder_region, + ), + ), + (None, _) => NiceRegionError::new( + infcx, + RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region), + ), + }; + nice_error.try_report_from_nll().or_else(|| { + if let SubregionOrigin::Subtype(trace) = cause { + Some( + infcx.report_and_explain_type_error(*trace, &TypeError::RegionsPlaceholderMismatch), + ) + } else { + None + } + }) +} diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs index 1bb8c7ebe5a..55c6410ed32 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs @@ -28,12 +28,14 @@ mod outlives_suggestion; mod region_name; mod var_name; +mod bound_region_errors; mod conflict_errors; mod explain_borrow; mod move_errors; mod mutability_errors; mod region_errors; +crate use bound_region_errors::{ToUniverseInfo, UniverseInfo}; crate use mutability_errors::AccessKind; crate use outlives_suggestion::OutlivesSuggestionBuilder; crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors}; diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs index 1460c2378d1..fe9df41db45 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs @@ -75,8 +75,8 @@ crate enum RegionErrorKind<'tcx> { longer_fr: RegionVid, /// The region element that erroneously must be outlived by `longer_fr`. error_element: RegionElement, - /// The origin of the placeholder region. - fr_origin: NllRegionVariableOrigin, + /// The placeholder region. + placeholder: ty::PlaceholderRegion, }, /// Any other lifetime error. @@ -210,25 +210,23 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { RegionErrorKind::BoundUniversalRegionError { longer_fr, - fr_origin, + placeholder, error_element, } => { - let error_region = self.regioncx.region_from_element(longer_fr, error_element); + let error_vid = self.regioncx.region_from_element(longer_fr, &error_element); // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. let (_, span) = self.regioncx.find_outlives_blame_span( &self.body, longer_fr, - fr_origin, - error_region, + NllRegionVariableOrigin::Placeholder(placeholder), + error_vid, ); - // FIXME: improve this error message - self.infcx - .tcx - .sess - .struct_span_err(span, "higher-ranked subtype error") - .buffer(&mut self.errors_buffer); + let universe = placeholder.universe; + let universe_info = self.regioncx.universe_info(universe); + + universe_info.report_error(self, placeholder, error_element, span); } RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => { diff --git a/compiler/rustc_mir/src/borrow_check/nll.rs b/compiler/rustc_mir/src/borrow_check/nll.rs index b74b1eb4952..66ca94d3b41 100644 --- a/compiler/rustc_mir/src/borrow_check/nll.rs +++ b/compiler/rustc_mir/src/borrow_check/nll.rs @@ -241,6 +241,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( outlives_constraints, member_constraints, closure_bounds_mapping, + universe_causes, type_tests, } = constraints; let placeholder_indices = Rc::new(placeholder_indices); @@ -262,6 +263,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( outlives_constraints, member_constraints, closure_bounds_mapping, + universe_causes, type_tests, liveness_constraints, elements, diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs index c40e6bf1ec3..a96cdbc13f3 100644 --- a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs @@ -21,7 +21,7 @@ use crate::borrow_check::{ constraints::{ graph::NormalConstraintGraph, ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet, }, - diagnostics::{RegionErrorKind, RegionErrors}, + diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo}, member_constraints::{MemberConstraintSet, NllMemberConstraintIndex}, nll::{PoloniusOutput, ToRegionVid}, region_infer::reverse_sccs::ReverseSccGraph, @@ -84,6 +84,9 @@ pub struct RegionInferenceContext<'tcx> { closure_bounds_mapping: FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>, + /// Map universe indexes to information on why we created it. + universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>, + /// Contains the minimum universe of any variable within the same /// SCC. We will ensure that no SCC contains values that are not /// visible from this index. @@ -253,6 +256,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>, >, + universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>, type_tests: Vec<TypeTest<'tcx>>, liveness_constraints: LivenessValues<RegionVid>, elements: &Rc<RegionValueElements>, @@ -293,6 +297,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { member_constraints, member_constraints_applied: Vec::new(), closure_bounds_mapping, + universe_causes, scc_universes, scc_representatives, scc_values, @@ -1632,7 +1637,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { errors_buffer.push(RegionErrorKind::BoundUniversalRegionError { longer_fr, error_element, - fr_origin: NllRegionVariableOrigin::Placeholder(placeholder), + placeholder, }); } @@ -1918,8 +1923,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// Get the region outlived by `longer_fr` and live at `element`. - crate fn region_from_element(&self, longer_fr: RegionVid, element: RegionElement) -> RegionVid { - match element { + crate fn region_from_element( + &self, + longer_fr: RegionVid, + element: &RegionElement, + ) -> RegionVid { + match *element { RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l), RegionElement::RootUniversalRegion(r) => r, RegionElement::PlaceholderRegion(error_placeholder) => self @@ -2138,6 +2147,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { categorized_path.remove(0) } + + crate fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { + self.universe_causes[universe].clone() + } } impl<'tcx> RegionDefinition<'tcx> { diff --git a/compiler/rustc_mir/src/borrow_check/type_check/canonical.rs b/compiler/rustc_mir/src/borrow_check/type_check/canonical.rs new file mode 100644 index 00000000000..9fafcfafe67 --- /dev/null +++ b/compiler/rustc_mir/src/borrow_check/type_check/canonical.rs @@ -0,0 +1,158 @@ +use std::fmt; + +use rustc_hir as hir; +use rustc_infer::infer::canonical::Canonical; +use rustc_infer::traits::query::NoSolution; +use rustc_middle::mir::ConstraintCategory; +use rustc_middle::ty::{self, ToPredicate, TypeFoldable}; +use rustc_span::Span; +use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput}; +use rustc_trait_selection::traits::query::Fallible; + +use crate::borrow_check::diagnostics::{ToUniverseInfo, UniverseInfo}; + +use super::{Locations, NormalizeLocation, TypeChecker}; + +impl<'a, 'tcx> TypeChecker<'a, 'tcx> { + /// Given some operation `op` that manipulates types, proves + /// predicates, or otherwise uses the inference context, executes + /// `op` and then executes all the further obligations that `op` + /// returns. This will yield a set of outlives constraints amongst + /// regions which are extracted and stored as having occurred at + /// `locations`. + /// + /// **Any `rustc_infer::infer` operations that might generate region + /// constraints should occur within this method so that those + /// constraints can be properly localized!** + pub(super) fn fully_perform_op<R, Op>( + &mut self, + locations: Locations, + category: ConstraintCategory, + op: Op, + ) -> Fallible<R> + where + Op: type_op::TypeOp<'tcx, Output = R>, + Canonical<'tcx, Op>: ToUniverseInfo<'tcx>, + { + let old_universe = self.infcx.universe(); + + let TypeOpOutput { output, constraints, canonicalized_query } = + op.fully_perform(self.infcx)?; + + if let Some(data) = &constraints { + self.push_region_constraints(locations, category, data); + } + + let universe = self.infcx.universe(); + + if old_universe != universe { + let universe_info = match canonicalized_query { + Some(canonicalized_query) => canonicalized_query.to_universe_info(old_universe), + None => UniverseInfo::other(), + }; + for u in old_universe..universe { + let info_universe = + self.borrowck_context.constraints.universe_causes.push(universe_info.clone()); + assert_eq!(u.as_u32() + 1, info_universe.as_u32()); + } + } + + Ok(output) + } + + pub(super) fn instantiate_canonical_with_fresh_inference_vars<T>( + &mut self, + span: Span, + canonical: &Canonical<'tcx, T>, + ) -> T + where + T: TypeFoldable<'tcx>, + { + let (instantiated, _) = + self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical); + + for _ in 0..canonical.max_universe.as_u32() { + let info = UniverseInfo::other(); + self.borrowck_context.constraints.universe_causes.push(info); + } + + instantiated + } + + pub(super) fn prove_trait_ref( + &mut self, + trait_ref: ty::TraitRef<'tcx>, + locations: Locations, + category: ConstraintCategory, + ) { + self.prove_predicates( + Some(ty::PredicateKind::Trait(ty::TraitPredicate { + trait_ref, + constness: hir::Constness::NotConst, + })), + locations, + category, + ); + } + + pub(super) fn normalize_and_prove_instantiated_predicates( + &mut self, + instantiated_predicates: ty::InstantiatedPredicates<'tcx>, + locations: Locations, + ) { + for predicate in instantiated_predicates.predicates { + let predicate = self.normalize(predicate, locations); + self.prove_predicate(predicate, locations, ConstraintCategory::Boring); + } + } + + pub(super) fn prove_predicates( + &mut self, + predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>, + locations: Locations, + category: ConstraintCategory, + ) { + for predicate in predicates { + let predicate = predicate.to_predicate(self.tcx()); + debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,); + + self.prove_predicate(predicate, locations, category); + } + } + + pub(super) fn prove_predicate( + &mut self, + predicate: ty::Predicate<'tcx>, + locations: Locations, + category: ConstraintCategory, + ) { + debug!("prove_predicate(predicate={:?}, location={:?})", predicate, locations,); + + let param_env = self.param_env; + self.fully_perform_op( + locations, + category, + param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)), + ) + .unwrap_or_else(|NoSolution| { + span_mirbug!(self, NoSolution, "could not prove {:?}", predicate); + }) + } + + pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T + where + T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx, + { + debug!("normalize(value={:?}, location={:?})", value, location); + let param_env = self.param_env; + self.fully_perform_op( + location.to_locations(), + ConstraintCategory::Boring, + param_env.and(type_op::normalize::Normalize::new(value)), + ) + .unwrap_or_else(|NoSolution| { + span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value); + value + }) + } +} diff --git a/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs b/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs index beee3181256..012d67255d1 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs @@ -11,6 +11,7 @@ use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use std::rc::Rc; +use type_op::TypeOpOutput; use crate::borrow_check::{ nll::ToRegionVid, @@ -255,7 +256,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { let constraint_sets: Vec<_> = unnormalized_input_output_tys .flat_map(|ty| { debug!("build: input_or_output={:?}", ty); - let (ty, constraints1) = self + let TypeOpOutput { output: ty, constraints: constraints1, .. } = self .param_env .and(type_op::normalize::Normalize::new(ty)) .fully_perform(self.infcx) @@ -264,7 +265,11 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { .tcx .sess .delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty)); - (self.infcx.tcx.ty_error(), None) + TypeOpOutput { + output: self.infcx.tcx.ty_error(), + constraints: None, + canonicalized_query: None, + } }); let constraints2 = self.add_implied_bounds(ty); normalized_inputs_and_output.push(ty); @@ -317,7 +322,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { /// from this local. fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<Rc<QueryRegionConstraints<'tcx>>> { debug!("add_implied_bounds(ty={:?})", ty); - let (bounds, constraints) = self + let TypeOpOutput { output: bounds, constraints, .. } = self .param_env .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) .fully_perform(self.infcx) diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs index 37e0643228a..f8989a7d9df 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs @@ -44,7 +44,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // Instantiate the canonicalized variables from // user-provided signature (e.g., the `_` in the code // above) with fresh variables. - let (poly_sig, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars( + let poly_sig = self.instantiate_canonical_with_fresh_inference_vars( body.span, &user_provided_poly_sig, ); diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs b/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs index f04736e04a0..e411f1dc108 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; use rustc_middle::ty::{Ty, TypeFoldable}; use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult; use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives; -use rustc_trait_selection::traits::query::type_op::TypeOp; +use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use std::rc::Rc; use crate::dataflow::impls::MaybeInitializedPlaces; @@ -519,9 +519,9 @@ impl LivenessContext<'_, '_, '_, 'tcx> { debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,); let param_env = typeck.param_env; - let (dropck_result, region_constraint_data) = + let TypeOpOutput { output, constraints, .. } = param_env.and(DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx).unwrap(); - DropData { dropck_result, region_constraint_data } + DropData { dropck_result: output, region_constraint_data: constraints } } } diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 801318e01d7..d05e0135dfe 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -38,7 +38,7 @@ use rustc_trait_selection::opaque_types::{GenerateMemberConstraints, InferCtxtEx use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::query::type_op; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; -use rustc_trait_selection::traits::query::{Fallible, NoSolution}; +use rustc_trait_selection::traits::query::Fallible; use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations}; use crate::dataflow::impls::MaybeInitializedPlaces; @@ -51,6 +51,7 @@ use crate::transform::{ use crate::borrow_check::{ borrow_set::BorrowSet, constraints::{OutlivesConstraint, OutlivesConstraintSet}, + diagnostics::UniverseInfo, facts::AllFacts, location::LocationTable, member_constraints::MemberConstraintSet, @@ -89,6 +90,7 @@ macro_rules! span_mirbug_and_err { }) } +mod canonical; mod constraint_conversion; pub mod free_region_relations; mod input_output; @@ -142,6 +144,7 @@ pub(crate) fn type_check<'mir, 'tcx>( member_constraints: MemberConstraintSet::default(), closure_bounds_mapping: Default::default(), type_tests: Vec::default(), + universe_causes: IndexVec::from_elem_n(UniverseInfo::other(), 1), }; let CreateResult { @@ -156,6 +159,11 @@ pub(crate) fn type_check<'mir, 'tcx>( &mut constraints, ); + for _ in ty::UniverseIndex::ROOT..infcx.universe() { + let info = UniverseInfo::other(); + constraints.universe_causes.push(info); + } + let mut borrowck_context = BorrowCheckContext { universal_regions, location_table, @@ -376,8 +384,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { ty, san_ty| { if let Err(terr) = verifier.cx.eq_types( - san_ty, ty, + san_ty, location.to_locations(), ConstraintCategory::Boring, ) { @@ -425,8 +433,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty; if let Err(terr) = self.cx.eq_types( - normalized_ty, literal_ty, + normalized_ty, locations, ConstraintCategory::Boring, ) { @@ -542,7 +550,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { return PlaceTy::from_ty(self.tcx().ty_error()); } } - place_ty = self.sanitize_projection(place_ty, elem, place, location) + place_ty = self.sanitize_projection(place_ty, elem, place, location); } if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { @@ -916,6 +924,8 @@ crate struct MirTypeckRegionConstraints<'tcx> { crate closure_bounds_mapping: FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>, + crate universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>, + crate type_tests: Vec<TypeTest<'tcx>>, } @@ -1043,8 +1053,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); for user_annotation in self.user_type_annotations { let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation; - let (annotation, _) = - self.infcx.instantiate_canonical_with_fresh_inference_vars(span, user_ty); + let annotation = self.instantiate_canonical_with_fresh_inference_vars(span, user_ty); match annotation { UserType::Ty(mut ty) => { ty = self.normalize(ty, Locations::All(span)); @@ -1097,31 +1106,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - /// Given some operation `op` that manipulates types, proves - /// predicates, or otherwise uses the inference context, executes - /// `op` and then executes all the further obligations that `op` - /// returns. This will yield a set of outlives constraints amongst - /// regions which are extracted and stored as having occurred at - /// `locations`. - /// - /// **Any `rustc_infer::infer` operations that might generate region - /// constraints should occur within this method so that those - /// constraints can be properly localized!** - fn fully_perform_op<R>( - &mut self, - locations: Locations, - category: ConstraintCategory, - op: impl type_op::TypeOp<'tcx, Output = R>, - ) -> Fallible<R> { - let (r, opt_data) = op.fully_perform(self.infcx)?; - - if let Some(data) = &opt_data { - self.push_region_constraints(locations, category, data); - } - - Ok(r) - } - fn push_region_constraints( &mut self, locations: Locations, @@ -1161,7 +1145,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { b, locations, category, - Some(self.borrowck_context), + self.borrowck_context, ) } @@ -1173,17 +1157,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations: Locations, category: ConstraintCategory, ) -> Fallible<()> { - self.relate_types(sub, ty::Variance::Covariant, sup, locations, category) + // Use this order of parameters because the sup type is usually the + // "expected" type in diagnostics. + self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category) } fn eq_types( &mut self, - a: Ty<'tcx>, - b: Ty<'tcx>, + expected: Ty<'tcx>, + found: Ty<'tcx>, locations: Locations, category: ConstraintCategory, ) -> Fallible<()> { - self.relate_types(a, ty::Variance::Invariant, b, locations, category) + self.relate_types(expected, ty::Variance::Invariant, found, locations, category) } fn relate_type_and_user_type( @@ -1222,7 +1208,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); let ty = curr_projected_ty.ty; - self.relate_types(a, v, ty, locations, category)?; + self.relate_types(ty, v.xform(ty::Variance::Contravariant), a, locations, category)?; Ok(()) } @@ -2053,8 +2039,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_fn_ptr_from = tcx.mk_fn_ptr(fn_sig); if let Err(terr) = self.eq_types( - ty_fn_ptr_from, ty, + ty_fn_ptr_from, location.to_locations(), ConstraintCategory::Cast, ) { @@ -2077,8 +2063,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_fn_ptr_from = tcx.mk_fn_ptr(tcx.signature_unclosure(sig, *unsafety)); if let Err(terr) = self.eq_types( - ty_fn_ptr_from, ty, + ty_fn_ptr_from, location.to_locations(), ConstraintCategory::Cast, ) { @@ -2106,8 +2092,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig); if let Err(terr) = self.eq_types( - ty_fn_ptr_from, ty, + ty_fn_ptr_from, location.to_locations(), ConstraintCategory::Cast, ) { @@ -2294,20 +2280,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { kind: TypeVariableOriginKind::MiscVariable, span: body.source_info(location).span, }); - self.relate_types( - common_ty, - ty::Variance::Contravariant, + self.sub_types( ty_left, + common_ty, location.to_locations(), ConstraintCategory::Boring, ) .unwrap_or_else(|err| { bug!("Could not equate type variable with {:?}: {:?}", ty_left, err) }); - if let Err(terr) = self.relate_types( - common_ty, - ty::Variance::Contravariant, + if let Err(terr) = self.sub_types( ty_right, + common_ty, location.to_locations(), ConstraintCategory::Boring, ) { @@ -2682,66 +2666,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { tcx.predicates_of(def_id).instantiate(tcx, substs) } - fn prove_trait_ref( - &mut self, - trait_ref: ty::TraitRef<'tcx>, - locations: Locations, - category: ConstraintCategory, - ) { - self.prove_predicates( - Some(ty::PredicateKind::Trait(ty::TraitPredicate { - trait_ref, - constness: hir::Constness::NotConst, - })), - locations, - category, - ); - } - - fn normalize_and_prove_instantiated_predicates( - &mut self, - instantiated_predicates: ty::InstantiatedPredicates<'tcx>, - locations: Locations, - ) { - for predicate in instantiated_predicates.predicates { - let predicate = self.normalize(predicate, locations); - self.prove_predicate(predicate, locations, ConstraintCategory::Boring); - } - } - - fn prove_predicates( - &mut self, - predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>, - locations: Locations, - category: ConstraintCategory, - ) { - for predicate in predicates { - let predicate = predicate.to_predicate(self.tcx()); - debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,); - - self.prove_predicate(predicate, locations, category); - } - } - - fn prove_predicate( - &mut self, - predicate: ty::Predicate<'tcx>, - locations: Locations, - category: ConstraintCategory, - ) { - debug!("prove_predicate(predicate={:?}, location={:?})", predicate, locations,); - - let param_env = self.param_env; - self.fully_perform_op( - locations, - category, - param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)), - ) - .unwrap_or_else(|NoSolution| { - span_mirbug!(self, NoSolution, "could not prove {:?}", predicate); - }) - } - fn typeck_mir(&mut self, body: &Body<'tcx>) { self.last_span = body.span; debug!("run_on_mir: {:?}", body.span); @@ -2764,23 +2688,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.check_iscleanup(&body, block_data); } } - - fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T - where - T: type_op::normalize::Normalizable<'tcx> + Copy + 'tcx, - { - debug!("normalize(value={:?}, location={:?})", value, location); - let param_env = self.param_env; - self.fully_perform_op( - location.to_locations(), - ConstraintCategory::Boring, - param_env.and(type_op::normalize::Normalize::new(value)), - ) - .unwrap_or_else(|NoSolution| { - span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value); - value - }) - } } trait NormalizeLocation: fmt::Debug + Copy { diff --git a/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs b/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs index f97252a117a..971c4daa6b3 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs @@ -6,6 +6,7 @@ use rustc_middle::ty::{self, Const, Ty}; use rustc_trait_selection::traits::query::Fallible; use crate::borrow_check::constraints::OutlivesConstraint; +use crate::borrow_check::diagnostics::UniverseInfo; use crate::borrow_check::type_check::{BorrowCheckContext, Locations}; /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`: @@ -24,12 +25,19 @@ pub(super) fn relate_types<'tcx>( b: Ty<'tcx>, locations: Locations, category: ConstraintCategory, - borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>, + borrowck_context: &mut BorrowCheckContext<'_, 'tcx>, ) -> Fallible<()> { debug!("relate_types(a={:?}, v={:?}, b={:?}, locations={:?})", a, v, b, locations); TypeRelating::new( infcx, - NllTypeRelatingDelegate::new(infcx, borrowck_context, param_env, locations, category), + NllTypeRelatingDelegate::new( + infcx, + borrowck_context, + param_env, + locations, + category, + UniverseInfo::relate(a, b), + ), v, ) .relate(a, b)?; @@ -38,7 +46,7 @@ pub(super) fn relate_types<'tcx>( struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { infcx: &'me InferCtxt<'me, 'tcx>, - borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>, + borrowck_context: &'me mut BorrowCheckContext<'bccx, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -47,17 +55,22 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { /// What category do we assign the resulting `'a: 'b` relationships? category: ConstraintCategory, + + /// Information so that error reporting knows what types we are relating + /// when reporting a bound region error. + universe_info: UniverseInfo<'tcx>, } impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { fn new( infcx: &'me InferCtxt<'me, 'tcx>, - borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>, + borrowck_context: &'me mut BorrowCheckContext<'bccx, 'tcx>, param_env: ty::ParamEnv<'tcx>, locations: Locations, category: ConstraintCategory, + universe_info: UniverseInfo<'tcx>, ) -> Self { - Self { infcx, borrowck_context, param_env, locations, category } + Self { infcx, borrowck_context, param_env, locations, category, universe_info } } } @@ -67,24 +80,20 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { } fn create_next_universe(&mut self) -> ty::UniverseIndex { - self.infcx.create_next_universe() + let info_universe = + self.borrowck_context.constraints.universe_causes.push(self.universe_info.clone()); + let universe = self.infcx.create_next_universe(); + assert_eq!(info_universe, universe); + universe } fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> { - if self.borrowck_context.is_some() { - let origin = NllRegionVariableOrigin::Existential { from_forall }; - self.infcx.next_nll_region_var(origin) - } else { - self.infcx.tcx.lifetimes.re_erased - } + let origin = NllRegionVariableOrigin::Existential { from_forall }; + self.infcx.next_nll_region_var(origin) } fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> { - if let Some(borrowck_context) = &mut self.borrowck_context { - borrowck_context.constraints.placeholder_region(self.infcx, placeholder) - } else { - self.infcx.tcx.lifetimes.re_erased - } + self.borrowck_context.constraints.placeholder_region(self.infcx, placeholder) } fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { @@ -100,17 +109,15 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { sub: ty::Region<'tcx>, info: ty::VarianceDiagInfo<'tcx>, ) { - if let Some(borrowck_context) = &mut self.borrowck_context { - let sub = borrowck_context.universal_regions.to_region_vid(sub); - let sup = borrowck_context.universal_regions.to_region_vid(sup); - borrowck_context.constraints.outlives_constraints.push(OutlivesConstraint { - sup, - sub, - locations: self.locations, - category: self.category, - variance_info: info, - }); - } + let sub = self.borrowck_context.universal_regions.to_region_vid(sub); + let sup = self.borrowck_context.universal_regions.to_region_vid(sup); + self.borrowck_context.constraints.outlives_constraints.push(OutlivesConstraint { + sup, + sub, + locations: self.locations, + category: self.category, + variance_info: info, + }); } // We don't have to worry about the equality of consts during borrow checking diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs index 4f5476ca5d0..b5398f8a435 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs @@ -1,13 +1,13 @@ -use crate::infer::{InferCtxt, InferOk}; -use crate::traits::query::Fallible; -use std::fmt; - use crate::infer::canonical::query_response; -use crate::infer::canonical::QueryRegionConstraints; +use crate::infer::{InferCtxt, InferOk}; use crate::traits::engine::TraitEngineExt as _; +use crate::traits::query::type_op::TypeOpOutput; +use crate::traits::query::Fallible; use crate::traits::{ObligationCause, TraitEngine}; use rustc_infer::traits::TraitEngineExt as _; use rustc_span::source_map::DUMMY_SP; + +use std::fmt; use std::rc::Rc; pub struct CustomTypeOp<F, G> { @@ -35,10 +35,7 @@ where /// Processes the operation and all resulting obligations, /// returning the final result along with any region constraints /// (they will be given over to the NLL region solver). - fn fully_perform( - self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> { + fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> { if cfg!(debug_assertions) { info!("fully_perform({:?})", self); } @@ -58,10 +55,10 @@ where /// Executes `op` and then scrapes out all the "old style" region /// constraints that result, creating query-region-constraints. -fn scrape_region_constraints<'tcx, R>( +fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( infcx: &InferCtxt<'_, 'tcx>, op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>, -) -> Fallible<(R, Option<Rc<QueryRegionConstraints<'tcx>>>)> { +) -> Fallible<TypeOpOutput<'tcx, Op>> { let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx); let dummy_body_id = ObligationCause::dummy().body_id; @@ -101,8 +98,12 @@ fn scrape_region_constraints<'tcx, R>( ); if region_constraints.is_empty() { - Ok((value, None)) + Ok(TypeOpOutput { output: value, constraints: None, canonicalized_query: None }) } else { - Ok((value, Some(Rc::new(region_constraints)))) + Ok(TypeOpOutput { + output: value, + constraints: Some(Rc::new(region_constraints)), + canonicalized_query: None, + }) } } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index b351af44e94..3863dd61cef 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -3,7 +3,7 @@ use crate::traits::query::outlives_bounds::OutlivesBound; use crate::traits::query::Fallible; use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; -#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)] +#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)] pub struct ImpliedOutlivesBounds<'tcx> { pub ty: Ty<'tcx>, } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index fbff86618ad..12ca3faeb37 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -4,6 +4,7 @@ use crate::infer::canonical::{ use crate::infer::{InferCtxt, InferOk}; use crate::traits::query::Fallible; use crate::traits::ObligationCause; +use rustc_infer::infer::canonical::Canonical; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use std::fmt; @@ -30,10 +31,18 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug { /// Processes the operation and all resulting obligations, /// returning the final result along with any region constraints /// (they will be given over to the NLL region solver). - fn fully_perform( - self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)>; + fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>>; +} + +/// The output from performing a type op +pub struct TypeOpOutput<'tcx, Op: TypeOp<'tcx>> { + /// The output from the type op. + pub output: Op::Output, + /// Any region constraints from performing the type op. + pub constraints: Option<Rc<QueryRegionConstraints<'tcx>>>, + /// The canonicalized form of the query. + /// This for error reporting to be able to rerun the query. + pub canonicalized_query: Option<Canonical<'tcx, Op>>, } /// "Query type ops" are type ops that are implemented using a @@ -45,7 +54,7 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug { /// which produces the resulting query region constraints. /// /// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html -pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx { +pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx { type QueryResponse: TypeFoldable<'tcx>; /// Give query the option for a simple fast path that never @@ -71,9 +80,9 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx { query_key: ParamEnvAnd<'tcx, Self>, infcx: &InferCtxt<'_, 'tcx>, output_query_region_constraints: &mut QueryRegionConstraints<'tcx>, - ) -> Fallible<Self::QueryResponse> { + ) -> Fallible<(Self::QueryResponse, Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>)> { if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) { - return Ok(result); + return Ok((result, None)); } // FIXME(#33684) -- We need to use @@ -101,14 +110,14 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx { // create obligations. In that case, we have to go // fulfill them. We do this via a (recursive) query. for obligation in obligations { - let () = ProvePredicate::fully_perform_into( + let ((), _) = ProvePredicate::fully_perform_into( obligation.param_env.and(ProvePredicate::new(obligation.predicate)), infcx, output_query_region_constraints, )?; } - Ok(value) + Ok((value, Some(canonical_self))) } } @@ -118,18 +127,16 @@ where { type Output = Q::QueryResponse; - fn fully_perform( - self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> { + fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> { let mut region_constraints = QueryRegionConstraints::default(); - let r = Q::fully_perform_into(self, infcx, &mut region_constraints)?; + let (output, canonicalized_query) = + Q::fully_perform_into(self, infcx, &mut region_constraints)?; // Promote the final query-region-constraints into a // (optional) ref-counted vector: - let opt_qrc = + let region_constraints = if region_constraints.is_empty() { None } else { Some(Rc::new(region_constraints)) }; - Ok((r, opt_qrc)) + Ok(TypeOpOutput { output, constraints: region_constraints, canonicalized_query }) } } diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index d0b05beb4e6..8dd7c5bdfae 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -19,6 +19,8 @@ mod normalize_erasing_regions; mod normalize_projection_ty; mod type_op; +pub use type_op::type_op_prove_predicate_with_span; + use rustc_middle::ty::query::Providers; pub fn provide(p: &mut Providers) { diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index bd0acb0e53b..c2e0a998785 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts}; use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable, Variance}; use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Predicate, ToPredicate}; -use rustc_span::DUMMY_SP; +use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::query::normalize::AtExt; @@ -236,11 +236,25 @@ fn type_op_prove_predicate<'tcx>( canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { - let (param_env, ProvePredicate { predicate }) = key.into_parts(); - fulfill_cx.register_predicate_obligation( - infcx, - Obligation::new(ObligationCause::dummy(), param_env, predicate), - ); + type_op_prove_predicate_with_span(infcx, fulfill_cx, key, None); Ok(()) }) } + +/// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors, +/// this query can be re-run to better track the span of the obligation cause, and improve the error +/// message. Do not call directly unless you're in that very specific context. +pub fn type_op_prove_predicate_with_span<'a, 'tcx: 'a>( + infcx: &'a InferCtxt<'a, 'tcx>, + fulfill_cx: &'a mut dyn TraitEngine<'tcx>, + key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>, + span: Option<Span>, +) { + let cause = if let Some(span) = span { + ObligationCause::dummy_with_span(span) + } else { + ObligationCause::dummy() + }; + let (param_env, ProvePredicate { predicate }) = key.into_parts(); + fulfill_cx.register_predicate_obligation(infcx, Obligation::new(cause, param_env, predicate)); +} 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 index 2e03986a9ed..59e27cd2e7d 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr @@ -1,8 +1,12 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/higher-ranked-projection.rs:25:5 | LL | foo(()); - | ^^^^^^^ + | ^^^^^^^ one type is more general than the other + | + = note: expected type `&'a ()` + found reference `&()` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. 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 64a0b52a1fa..768dc8e12db 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 @@ -21,23 +21,33 @@ LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | = help: consider replacing `'x` with `'static` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:32:49 | LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); - | ^ + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'r> fn(&'r u32)` + found fn pointer `fn(&u32)` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:39:50 | LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); - | ^ + | ^ one type is more general than the other + | + = note: expected fn pointer `fn(&'x u32)` + found fn pointer `for<'r> fn(&'r u32)` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:48:50 | LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { - | ^ + | ^ one type is more general than the other + | + = note: expected fn pointer `fn(&u32)` + found fn pointer `for<'r> fn(&'r u32)` error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/generator/auto-trait-regions.nll.stderr b/src/test/ui/generator/auto-trait-regions.nll.stderr index 794369a8dc0..76970fb7872 100644 --- a/src/test/ui/generator/auto-trait-regions.nll.stderr +++ b/src/test/ui/generator/auto-trait-regions.nll.stderr @@ -24,17 +24,23 @@ LL | assert_foo(a); | = note: consider using a `let` binding to create a longer lived value -error: higher-ranked subtype error +error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:31:5 | LL | assert_foo(gen); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... + = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` -error: higher-ranked subtype error +error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:50:5 | LL | assert_foo(gen); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... + = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` error: aborting due to 4 previous errors diff --git a/src/test/ui/generator/resume-arg-late-bound.nll.stderr b/src/test/ui/generator/resume-arg-late-bound.nll.stderr index 7d712191924..25bc6afc550 100644 --- a/src/test/ui/generator/resume-arg-late-bound.nll.stderr +++ b/src/test/ui/generator/resume-arg-late-bound.nll.stderr @@ -1,8 +1,12 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/resume-arg-late-bound.rs:15:5 | LL | test(gen); - | ^^^^^^^^^ + | ^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'a> Generator<&'a mut bool>` + found type `Generator<&mut bool>` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/higher-rank-trait-bounds/issue-59311.rs b/src/test/ui/higher-rank-trait-bounds/issue-59311.rs index 1e1241c7f83..d617571753c 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-59311.rs +++ b/src/test/ui/higher-rank-trait-bounds/issue-59311.rs @@ -14,7 +14,7 @@ pub fn crash<V>(v: &V) where for<'a> &'a V: T + 'static, { - v.t(|| {}); //~ ERROR: higher-ranked subtype error + v.t(|| {}); //~ ERROR: higher-ranked lifetime error } fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr b/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr index ca632629267..c16c8206153 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr +++ b/src/test/ui/higher-rank-trait-bounds/issue-59311.stderr @@ -1,8 +1,10 @@ -error: higher-ranked subtype error +error: higher-ranked lifetime error --> $DIR/issue-59311.rs:17:9 | LL | v.t(|| {}); | ^^^^^ + | + = note: could not prove for<'a> &'a V: 'static 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.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.nll.stderr index 4cca552d7d4..439a113ef38 100644 --- 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 @@ -1,14 +1,17 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/hr-subtype.rs:45:13 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ 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 | + = note: expected enum `Option<for<'r, 's> fn(&'r u32, &'s u32) -> &'r u32>` + found enum `Option<for<'r> fn(&'r u32, &'r u32) -> &'r u32>` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) 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_free_x.nll.stderr b/src/test/ui/hr-subtype/hr-subtype.bound_a_vs_free_x.nll.stderr index 2c1ac126fab..61b3f0ca284 100644 --- 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 @@ -1,14 +1,17 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/hr-subtype.rs:45:13 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ 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 | + = note: expected enum `Option<for<'r> fn(&'r u32)>` + found enum `Option<fn(&u32)>` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) 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 index 816984654f7..75e2ba58f33 100644 --- 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 @@ -1,26 +1,31 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/hr-subtype.rs:45:13 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ 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 | + = note: expected enum `Option<for<'r, 's> fn(Inv<'r>, Inv<'s>)>` + found enum `Option<for<'r> fn(Inv<'r>, Inv<'r>)>` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/hr-subtype.rs:45:13 | LL | gimme::<$t1>(None::<$t2>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ 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 | + = note: expected enum `Option<for<'r, 's> fn(Inv<'r>, Inv<'s>)>` + found enum `Option<for<'r> fn(Inv<'r>, Inv<'r>)>` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr index f290a93326f..46f5308dd87 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.nll.stderr @@ -1,14 +1,20 @@ -error: higher-ranked subtype error +error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:27:10 | LL | fn b() { want_foo2::<SomeStruct>(); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` -error: higher-ranked subtype error +error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:27:10 | LL | fn b() { want_foo2::<SomeStruct>(); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr index 11390d9e2d2..1ee3c674963 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.nll.stderr @@ -1,8 +1,12 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/hrtb-exists-forall-fn.rs:17:12 | LL | let _: for<'b> fn(&'b u32) = foo(); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'b> fn(&'b u32)` + found fn pointer `fn(&u32)` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. 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 index a4c3ffd1f6c..364b613fc77 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.nll.stderr @@ -1,8 +1,11 @@ -error: higher-ranked subtype error +error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 | LL | foo::<()>(); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `()` must implement `Trait<for<'b> fn(&'b u32)>` + = note: ...but it actually implements `Trait<fn(&'0 u32)>`, for some specific lifetime `'0` error: aborting due to previous error 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 index e2a399b2faa..cb2ce8a4116 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.nll.stderr @@ -1,8 +1,11 @@ -error: higher-ranked subtype error +error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | LL | foo::<()>(); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ implementation of `Trait` is not general enough + | + = note: `()` must implement `Trait<for<'b> fn(Cell<&'b u32>)>` + = note: ...but it actually implements `Trait<fn(Cell<&'0 u32>)>`, for some specific lifetime `'0` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr index 8901a1b4681..a812282def9 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.nll.stderr @@ -1,8 +1,11 @@ -error: higher-ranked subtype error +error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:24:5 | LL | want_hrtb::<StaticInt>() - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... + = note: ...but it actually implements `Foo<&'static isize>` error: lifetime may not live long enough --> $DIR/hrtb-just-for-static.rs:30:5 diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr index c3dd7949575..aefe3cdfd64 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.nll.stderr @@ -57,11 +57,14 @@ LL | foo_hrtb_bar_not(&mut t); | = help: consider replacing `'b` with `'static` -error: higher-ranked subtype error +error: implementation of `Bar` is not general enough --> $DIR/hrtb-perfect-forwarding.rs:43:5 | LL | foo_hrtb_bar_not(&mut t); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough + | + = note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... + = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` warning: function cannot return without recursing --> $DIR/hrtb-perfect-forwarding.rs:48:1 diff --git a/src/test/ui/hrtb/issue-46989.nll.stderr b/src/test/ui/hrtb/issue-46989.nll.stderr index 6c127b92d97..309e1a676ed 100644 --- a/src/test/ui/hrtb/issue-46989.nll.stderr +++ b/src/test/ui/hrtb/issue-46989.nll.stderr @@ -1,8 +1,11 @@ -error: higher-ranked subtype error +error: implementation of `Foo` is not general enough --> $DIR/issue-46989.rs:38:5 | LL | assert_foo::<fn(&i32)>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = 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 diff --git a/src/test/ui/issues/issue-40000.nll.stderr b/src/test/ui/issues/issue-40000.nll.stderr index 4e2bde06a52..e6f0b5fbfba 100644 --- a/src/test/ui/issues/issue-40000.nll.stderr +++ b/src/test/ui/issues/issue-40000.nll.stderr @@ -1,14 +1,21 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/issue-40000.rs:6:9 | LL | foo(bar); - | ^^^ + | ^^^ one type is more general than the other + | + = note: expected trait object `dyn for<'r> Fn(&'r i32)` + found trait object `dyn Fn(&i32)` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/issue-40000.rs:6:9 | LL | foo(bar); - | ^^^ + | ^^^ one type is more general than the other + | + = note: expected trait object `dyn for<'r> Fn(&'r i32)` + found trait object `dyn Fn(&i32)` error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-54302-cases.nll.stderr b/src/test/ui/issues/issue-54302-cases.nll.stderr index 7463a3f286f..6e8b69c4bee 100644 --- a/src/test/ui/issues/issue-54302-cases.nll.stderr +++ b/src/test/ui/issues/issue-54302-cases.nll.stderr @@ -1,26 +1,38 @@ -error: higher-ranked subtype error +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:63:5 | LL | <u32 as RefFoo<u32>>::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` -error: higher-ranked subtype error +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:69:5 | LL | <i32 as RefFoo<i32>>::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... + = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` -error: higher-ranked subtype error +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:75:5 | LL | <u64 as RefFoo<u64>>::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... + = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` -error: higher-ranked subtype error +error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:81:5 | LL | <i64 as RefFoo<i64>>::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... + = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-55731.nll.stderr b/src/test/ui/issues/issue-55731.nll.stderr index dd38bb62912..97fd6678c99 100644 --- a/src/test/ui/issues/issue-55731.nll.stderr +++ b/src/test/ui/issues/issue-55731.nll.stderr @@ -1,11 +1,14 @@ -error: higher-ranked subtype error +error: implementation of `DistributedIteratorMulti` is not general enough --> $DIR/issue-55731.rs:48:5 | LL | / multi(Map { LL | | i: Cloned(PhantomData), LL | | f: X, LL | | }); - | |______^ + | |______^ implementation of `DistributedIteratorMulti` is not general enough + | + = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`... + = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57843.nll.stderr b/src/test/ui/issues/issue-57843.nll.stderr index 70d16cc9a1d..2ab49ec61cf 100644 --- a/src/test/ui/issues/issue-57843.nll.stderr +++ b/src/test/ui/issues/issue-57843.nll.stderr @@ -1,8 +1,11 @@ -error: higher-ranked subtype error +error: implementation of `FnOnce` is not general enough --> $DIR/issue-57843.rs:25:9 | LL | Foo(Box::new(|_| ())); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 bool)` must implement `FnOnce<(&'1 bool,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 bool,)>`, for some specific lifetime `'2` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/issue-79187-2.nll.stderr b/src/test/ui/lifetimes/issue-79187-2.nll.stderr index 4970c579e7b..907b43d6762 100644 --- a/src/test/ui/lifetimes/issue-79187-2.nll.stderr +++ b/src/test/ui/lifetimes/issue-79187-2.nll.stderr @@ -16,29 +16,47 @@ LL | take_foo(|a: &i32| -> &i32 { a }); | | let's call the lifetime of this reference `'2` | let's call the lifetime of this reference `'1` -error: higher-ranked subtype error +error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187-2.rs:8:5 | LL | take_foo(|a| a); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/issue-79187-2.rs:8:5 | LL | take_foo(|a| a); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r> Fn<(&'r i32,)>` + found type `Fn<(&i32,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-79187-2.rs:8:14 + | +LL | take_foo(|a| a); + | ^^^^^ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/issue-79187-2.rs:9:5 | LL | take_foo(|a: &i32| a); - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&i32` + found reference `&i32` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/issue-79187-2.rs:10:5 | LL | take_foo(|a: &i32| -> &i32 { a }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&i32` + found reference `&i32` error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lifetimes/issue-79187.nll.stderr b/src/test/ui/lifetimes/issue-79187.nll.stderr index aa8809dbc95..725b132e83a 100644 --- a/src/test/ui/lifetimes/issue-79187.nll.stderr +++ b/src/test/ui/lifetimes/issue-79187.nll.stderr @@ -1,14 +1,26 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/issue-79187.rs:5:5 | LL | thing(f); - | ^^^^^^^^ + | ^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r> FnOnce<(&'r u32,)>` + found type `FnOnce<(&u32,)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/issue-79187.rs:4:13 + | +LL | let f = |_| (); + | ^^^^^^ -error: higher-ranked subtype error +error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 | LL | thing(f); - | ^^^^^^^^ + | ^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. 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 index b95e247d2a8..3fdc2da9f1e 100644 --- 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 @@ -1,8 +1,12 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/old-lub-glb-hr-noteq1.rs:11:14 | LL | _ => y, - | ^ + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'r, 's> fn(&'r u8, &'s u8) -> &'r u8` + found fn pointer `for<'r> fn(&'r u8, &'r u8) -> &'r 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 index 51bf96f3233..ad14d6b7521 100644 --- a/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr +++ b/src/test/ui/lub-glb/old-lub-glb-object.nll.stderr @@ -1,14 +1,21 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/old-lub-glb-object.rs:10:14 | LL | _ => y, - | ^ + | ^ one type is more general than the other + | + = note: expected trait object `dyn for<'r, 's> Foo<&'r u8, &'s u8>` + found trait object `dyn for<'r> Foo<&'r u8, &'r u8>` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/old-lub-glb-object.rs:10:14 | LL | _ => y, - | ^ + | ^ one type is more general than the other + | + = note: expected trait object `dyn for<'r, 's> Foo<&'r u8, &'s u8>` + found trait object `dyn for<'r> Foo<&'r u8, &'r u8>` error: aborting due to 2 previous errors +For more information about this 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 index 745a61b866e..f29126e6afc 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.nll.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.nll.stderr @@ -1,14 +1,26 @@ -error: higher-ranked subtype error +error: implementation of `FnOnce` is not general enough --> $DIR/closure-mismatch.rs:8:5 | LL | baz(|_| ()); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/closure-mismatch.rs:8:5 | LL | baz(|_| ()); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ one type is more general than the other + | + = note: expected type `for<'r> Fn<(&'r (),)>` + found type `Fn<(&(),)>` +note: this closure does not fulfill the lifetime requirements + --> $DIR/closure-mismatch.rs:8:9 + | +LL | baz(|_| ()); + | ^^^^^^ error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/nll/relate_tys/fn-subtype.rs b/src/test/ui/nll/relate_tys/fn-subtype.rs index ac00627ad00..0730dcc9e49 100644 --- a/src/test/ui/nll/relate_tys/fn-subtype.rs +++ b/src/test/ui/nll/relate_tys/fn-subtype.rs @@ -6,5 +6,5 @@ fn main() { let x: fn(&'static ()) = |_| {}; - let y: for<'a> fn(&'a ()) = x; //~ ERROR higher-ranked subtype error + let y: for<'a> fn(&'a ()) = x; //~ ERROR mismatched types [E0308] } diff --git a/src/test/ui/nll/relate_tys/fn-subtype.stderr b/src/test/ui/nll/relate_tys/fn-subtype.stderr index b089b5aaa25..94def690086 100644 --- a/src/test/ui/nll/relate_tys/fn-subtype.stderr +++ b/src/test/ui/nll/relate_tys/fn-subtype.stderr @@ -1,8 +1,12 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/fn-subtype.rs:9:33 | LL | let y: for<'a> fn(&'a ()) = x; - | ^ + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'r> fn(&'r ())` + found fn pointer `fn(&())` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs index fca69b83efe..a6d6ffa0ce3 100644 --- a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs +++ b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.rs @@ -12,7 +12,7 @@ fn make_it() -> for<'a> fn(&'a u32, &'a u32) -> &'a u32 { fn foo() { let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); - //~^ ERROR higher-ranked subtype error + //~^ ERROR mismatched types [E0308] drop(a); } @@ -20,7 +20,7 @@ fn bar() { // The code path for patterns is mildly different, so go ahead and // test that too: let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); - //~^ ERROR higher-ranked subtype error + //~^ ERROR mismatched types [E0308] } -fn main() { } +fn main() {} diff --git a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr index 7906dbd37ef..8c1eaeb6aa7 100644 --- a/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr +++ b/src/test/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr @@ -1,14 +1,21 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/hr-fn-aaa-as-aba.rs:14:58 | LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); - | ^^^^^^^^^ + | ^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r, 's> fn(&'r u32, &'s u32) -> &'r u32` + found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/hr-fn-aaa-as-aba.rs:22:12 | LL | let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32` + found fn pointer `for<'r> fn(&'r u32, &'r u32) -> &'r u32` error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs index 44dcd191d1b..37a01f28946 100644 --- a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs +++ b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs @@ -30,6 +30,6 @@ impl<T> Y for fn(T) { fn main() { let _x = <fn(&())>::make_f(); - //~^ higher-ranked subtype error - //~| higher-ranked subtype error + //~^ ERROR implementation of `Y` is not general enough + //~| ERROR implementation of `Y` is not general enough } diff --git a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index 190b520c678..ed79c7df25e 100644 --- a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -1,14 +1,20 @@ -error: higher-ranked subtype error +error: implementation of `Y` is not general enough --> $DIR/impl-fn-ignore-binder-via-bottom.rs:32:14 | LL | let _x = <fn(&())>::make_f(); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough + | + = note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())` + = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` -error: higher-ranked subtype error +error: implementation of `Y` is not general enough --> $DIR/impl-fn-ignore-binder-via-bottom.rs:32:14 | LL | let _x = <fn(&())>::make_f(); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough + | + = note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())` + = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/relate_tys/trait-hrtb.rs b/src/test/ui/nll/relate_tys/trait-hrtb.rs index 80f31ca6b47..2e94fc5c12d 100644 --- a/src/test/ui/nll/relate_tys/trait-hrtb.rs +++ b/src/test/ui/nll/relate_tys/trait-hrtb.rs @@ -12,5 +12,5 @@ fn make_foo<'a>() -> Box<dyn Foo<'a>> { fn main() { let x: Box<dyn Foo<'static>> = make_foo(); - let y: Box<dyn for<'a> Foo<'a>> = x; //~ ERROR higher-ranked subtype error + let y: Box<dyn for<'a> Foo<'a>> = x; //~ ERROR mismatched types [E0308] } diff --git a/src/test/ui/nll/relate_tys/trait-hrtb.stderr b/src/test/ui/nll/relate_tys/trait-hrtb.stderr index 4df2f352522..60a7f204446 100644 --- a/src/test/ui/nll/relate_tys/trait-hrtb.stderr +++ b/src/test/ui/nll/relate_tys/trait-hrtb.stderr @@ -1,8 +1,12 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/trait-hrtb.rs:15:39 | LL | let y: Box<dyn for<'a> Foo<'a>> = x; - | ^ + | ^ one type is more general than the other + | + = note: expected trait object `dyn for<'r> Foo<'r>` + found trait object `dyn Foo<'_>` error: aborting due to previous error +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/nll/relate_tys/universe-violation.rs b/src/test/ui/nll/relate_tys/universe-violation.rs index d29f8f8af20..8389c8e8377 100644 --- a/src/test/ui/nll/relate_tys/universe-violation.rs +++ b/src/test/ui/nll/relate_tys/universe-violation.rs @@ -12,6 +12,6 @@ fn make_it() -> fn(&'static u32) -> &'static u32 { fn main() { let a: fn(_) -> _ = make_it(); - let b: fn(&u32) -> &u32 = a; //~ ERROR higher-ranked subtype error + let b: fn(&u32) -> &u32 = a; //~ ERROR mismatched types [E0308] drop(a); } diff --git a/src/test/ui/nll/relate_tys/universe-violation.stderr b/src/test/ui/nll/relate_tys/universe-violation.stderr index 6dc78789564..ff4c7abc250 100644 --- a/src/test/ui/nll/relate_tys/universe-violation.stderr +++ b/src/test/ui/nll/relate_tys/universe-violation.stderr @@ -1,8 +1,12 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/universe-violation.rs:15:31 | LL | let b: fn(&u32) -> &u32 = a; - | ^ + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'r> fn(&'r u32) -> &'r u32` + found fn pointer `fn(&u32) -> &u32` 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 4ddea2c27b2..a64ad46ef46 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 @@ -27,17 +27,24 @@ LL | a(x, y); = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0308`. 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 a9cf128bb62..ce5e7d01723 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 @@ -27,23 +27,33 @@ LL | a(x, y, z); = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` + found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` + found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12 | LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)` + found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)` error: aborting due to 5 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static-fail.nll.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static-fail.nll.stderr index d762f55f9d5..c2956cd8958 100644 --- a/src/test/ui/regions/regions-fn-subtyping-return-static-fail.nll.stderr +++ b/src/test/ui/regions/regions-fn-subtyping-return-static-fail.nll.stderr @@ -1,8 +1,12 @@ -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/regions-fn-subtyping-return-static-fail.rs:48:5 | LL | want_G(baz); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S` + found fn pointer `for<'r> fn(&'r S) -> &'r S` 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 db86572f1cf..cae692ad2f6 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 @@ -27,17 +27,24 @@ LL | a(x, y); = note: mutable references are invariant over their type parameter = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12 | LL | let _: fn(&mut &isize, &mut &isize) = a; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)` + found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)` error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfc1623.nll.stderr b/src/test/ui/rfc1623.nll.stderr index a3d94679434..cc247bbcb11 100644 --- a/src/test/ui/rfc1623.nll.stderr +++ b/src/test/ui/rfc1623.nll.stderr @@ -19,7 +19,7 @@ LL | struct SomeStruct<'x, 'y, 'z: 'x> { = 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 +error[E0308]: mismatched types --> $DIR/rfc1623.rs:21:35 | LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { @@ -29,9 +29,12 @@ LL | | bar: &Bar { bools: &[true, true] }, LL | | f: &id, LL | | LL | | }; - | |_^ + | |_^ one type is more general than the other + | + = note: expected type `for<'r, 's> Fn<(&'r Foo<'s>,)>` + found type `Fn<(&Foo<'_>,)>` -error: higher-ranked subtype error +error[E0308]: mismatched types --> $DIR/rfc1623.rs:21:35 | LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { @@ -41,9 +44,12 @@ LL | | bar: &Bar { bools: &[true, true] }, LL | | f: &id, LL | | LL | | }; - | |_^ + | |_^ one type is more general than the other + | + = note: expected type `for<'r, 's> Fn<(&'r Foo<'s>,)>` + found type `Fn<(&Foo<'_>,)>` -error: higher-ranked subtype error +error: implementation of `FnOnce` is not general enough --> $DIR/rfc1623.rs:21:35 | LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { @@ -53,9 +59,12 @@ LL | | bar: &Bar { bools: &[true, true] }, LL | | f: &id, LL | | LL | | }; - | |_^ + | |_^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'2 Foo<'_>) -> &'2 Foo<'_> {id::<&'2 Foo<'_>>}` must implement `FnOnce<(&'1 Foo<'_>,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 Foo<'_>,)>`, for some specific lifetime `'2` -error: higher-ranked subtype error +error: implementation of `FnOnce` is not general enough --> $DIR/rfc1623.rs:21:35 | LL | static SOME_STRUCT: &SomeStruct = &SomeStruct { @@ -65,8 +74,12 @@ LL | | bar: &Bar { bools: &[true, true] }, LL | | f: &id, LL | | LL | | }; - | |_^ + | |_^ implementation of `FnOnce` is not general enough + | + = note: `fn(&Foo<'2>) -> &Foo<'2> {id::<&Foo<'2>>}` must implement `FnOnce<(&Foo<'1>,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&Foo<'2>,)>`, for some specific lifetime `'2` error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/unboxed-closures/issue-30906.nll.stderr b/src/test/ui/unboxed-closures/issue-30906.nll.stderr index 2db392e8b8b..147a2097473 100644 --- a/src/test/ui/unboxed-closures/issue-30906.nll.stderr +++ b/src/test/ui/unboxed-closures/issue-30906.nll.stderr @@ -1,8 +1,11 @@ -error: higher-ranked subtype error +error: implementation of `FnOnce` is not general enough --> $DIR/issue-30906.rs:18:5 | LL | test(Compose(f, |_| {})); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2` error: aborting due to previous error 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 index d0c476dc6ec..f65db78fc89 100644 --- a/src/test/ui/where-clauses/where-for-self-2.nll.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.nll.stderr @@ -1,8 +1,11 @@ -error: higher-ranked subtype error +error: implementation of `Bar` is not general enough --> $DIR/where-for-self-2.rs:23:5 | LL | foo(&X); - | ^^^^^^^ + | ^^^^^^^ implementation of `Bar` is not general enough + | + = note: `&'0 u32` must implement `Bar`, for any lifetime `'0`... + = note: ...but `Bar` is actually implemented for the type `&'static u32` error: aborting due to previous error |
