diff --git a/Cargo.lock b/Cargo.lock index 940608975c5ec..2d2eaf741a4dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4055,6 +4055,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 50048534aaee5..0a049f83e3146 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1191,16 +1191,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 10217a5f57498..9b9ded5c6bab4 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 7f4c33c5792cb..5adbfd469a4ae 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 ec1627f5c8af4..72e3d5e564abe 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 0000000000000..d0284dd030236 --- /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 + '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>> +{ + 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> { + 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>, + ) -> Option>; + + 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>, + ) -> Option> { + tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| { + let mut fulfill_cx = >::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>>, + base_universe: ty::UniverseIndex, +} + +impl 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>, + ) -> Option> { + tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| { + let mut fulfill_cx = >::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 + 'tcx>, + infcx: &InferCtxt<'_, 'tcx>, + placeholder_region: ty::Region<'tcx>, + error_region: Option>, +) -> Option> { + 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 1bb8c7ebe5afd..55c6410ed3204 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 1460c2378d1c9..fe9df41db45e2 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 bfeafa33a91cf..7df4f5cfdb6db 100644 --- a/compiler/rustc_mir/src/borrow_check/nll.rs +++ b/compiler/rustc_mir/src/borrow_check/nll.rs @@ -239,6 +239,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); @@ -260,6 +261,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 c40e6bf1ec33b..a96cdbc13f345 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>, + /// Map universe indexes to information on why we created it. + universe_causes: IndexVec>, + /// 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>, type_tests: Vec>, liveness_constraints: LivenessValues, elements: &Rc, @@ -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 0000000000000..9fafcfafe67cd --- /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( + &mut self, + locations: Locations, + category: ConstraintCategory, + op: Op, + ) -> Fallible + 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( + &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>, + 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(&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 beee31812563e..012d67255d13b 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>> { 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 37e0643228acc..f8989a7d9df1c 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 f04736e04a053..e411f1dc10889 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 86dcb9c9c1b7a..b6b25a759913a 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>, + crate universe_causes: IndexVec>, + crate type_tests: Vec>, } @@ -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( - &mut self, - locations: Locations, - category: ConstraintCategory, - op: impl type_op::TypeOp<'tcx, Output = R>, - ) -> Fallible { - 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>, - 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(&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 f97252a117a6f..971c4daa6b311 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 4f5476ca5d0dc..b5398f8a4353b 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 { @@ -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>>)> { + fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible> { 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>, -) -> Fallible<(R, Option>>)> { +) -> Fallible> { let mut fulfill_cx = >::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 b351af44e942d..3863dd61cefc0 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 fbff86618ade3..12ca3faeb3797 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>>)>; + fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible>; +} + +/// 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>>, + /// The canonicalized form of the query. + /// This for error reporting to be able to rerun the query. + pub canonicalized_query: Option>, } /// "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 { + ) -> Fallible<(Self::QueryResponse, Option>>)> { 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>>)> { + fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible> { 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 d0b05beb4e63c..8dd7c5bdfaebc 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 f4a0cc6767f09..fe1fec9c0ab66 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -10,7 +10,7 @@ use rustc_middle::ty::{ self, FnSig, Lift, PolyFnSig, PredicateKind, 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; @@ -247,11 +247,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, +) { + 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 2e03986a9ed8f..59e27cd2e7dd6 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 64a0b52a1fac5..768dc8e12db50 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 794369a8dc02b..76970fb787214 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 7d71219192407..25bc6afc550b3 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 1e1241c7f83c5..d617571753c1d 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) 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 ca6326292672b..c16c820615324 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 4cca552d7d473..439a113ef3811 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 fn(&'r u32, &'s u32) -> &'r u32>` + found enum `Option 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 2c1ac126fabb9..61b3f0ca2847c 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 fn(&'r u32)>` + found enum `Option` = 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 816984654f7f7..75e2ba58f33fb 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 fn(Inv<'r>, Inv<'s>)>` + found enum `Option 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 fn(Inv<'r>, Inv<'s>)>` + found enum `Option 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 f290a93326f37..46f5308dd87ba 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::(); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ 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::(); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ 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 11390d9e2d265..1ee3c67496397 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 a4c3ffd1f6c08..364b613fc7717 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 fn(&'b u32)>` + = note: ...but it actually implements `Trait`, 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 e2a399b2faa9d..cb2ce8a4116aa 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 fn(Cell<&'b u32>)>` + = note: ...but it actually implements `Trait)>`, 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 8901a1b46817d..a812282def9a8 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::() - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ 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 c3dd794957540..aefe3cdfd6487 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 6c127b92d97d1..309e1a676edaf 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::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ 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 4e2bde06a52a5..e6f0b5fbfba1d 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 7463a3f286f4c..6e8b69c4beebb 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 | >::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 | >::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 | >::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 | >::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 dd38bb6291251..97fd6678c997e 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 70d16cc9a1da6..2ab49ec61cf59 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 4970c579e7b98..907b43d6762e9 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 aa8809dbc95f7..725b132e83a12 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 b95e247d2a8cf..3fdc2da9f1e2e 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 51bf96f32335b..ad14d6b7521bc 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 745a61b866ed2..f29126e6afc76 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 ac00627ad00eb..0730dcc9e4978 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 b089b5aaa2535..94def69008677 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 fca69b83efe99..a6d6ffa0ce3d2 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 7906dbd37efa9..8c1eaeb6aa7b9 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 44dcd191d1ba2..37a01f28946d2 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 Y for fn(T) { fn main() { let _x = ::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 190b520c6786c..ed79c7df25e2a 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 = ::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 = ::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 80f31ca6b4782..2e94fc5c12df1 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> { fn main() { let x: Box> = make_foo(); - let y: Box Foo<'a>> = x; //~ ERROR higher-ranked subtype error + let y: Box 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 4df2f352522a3..60a7f20444680 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 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 d29f8f8af208c..8389c8e8377ed 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 6dc78789564c7..ff4c7abc25055 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 4ddea2c27b2a6..a64ad46ef462b 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 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 a9cf128bb621a..ce5e7d0172308 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 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 d762f55f9d5f1..c2956cd89580f 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 db86572f1cf73..cae692ad2f6fa 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 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 a3d94679434d1..cc247bbcb1199 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 2db392e8b8b9f..147a20974732d 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 d0c476dc6ec05..f65db78fc8993 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