Auto merge of #86700 - lqd:matthews-nll-hrtb-errors, r=nikomatsakis

Matthew's work on improving NLL's "higher-ranked subtype error"s

This PR rebases `@matthewjasper's` [branch](https://github.com/matthewjasper/rust/tree/nll-hrtb-errors) which has great work to fix the obscure higher-ranked subtype errors that are tracked in #57374.

These are a blocker to turning full NLLs on, and doing some internal cleanups to remove some of the old region code.

The goal is so `@nikomatsakis` can take a look at this early, and I'll then do my best to help do the changes and followup work to land this work, and move closer to turning off the migration mode.

I've only updated the branch and made it compile, removed a warning or two.

r? `@nikomatsakis`

(Here's the [zulip topic to discuss this](https://rust-lang.zulipchat.com/#narrow/stream/122657-t-compiler.2Fwg-nll/topic/.2357374.3A.20improving.20higher-ranked.20subtype.20errors.20via.20.2386700) that Niko wanted)
This commit is contained in:
bors 2021-08-18 15:54:59 +00:00
commit 3d0774d0dc
63 changed files with 1043 additions and 345 deletions

View file

@ -4057,6 +4057,7 @@ dependencies = [
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"rustc_traits",
"smallvec",
"tracing",
]

View file

@ -1180,16 +1180,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// | |
// | elided as they were the same
// not elided, they were different, but irrelevant
//
// For bound lifetimes, keep the names of the lifetimes,
// even if they are the same so that it's clear what's happening
// if we have something like
//
// for<'r, 's> fn(Inv<'r>, Inv<'s>)
// for<'r> fn(Inv<'r>, Inv<'r>)
let lifetimes = sub1.regions().zip(sub2.regions());
for (i, lifetimes) in lifetimes.enumerate() {
let l1 = lifetime_display(lifetimes.0);
let l2 = lifetime_display(lifetimes.1);
if lifetimes.0 == lifetimes.1 {
values.0.push_normal("'_");
values.1.push_normal("'_");
} else {
if lifetimes.0 != lifetimes.1 {
values.0.push_highlighted(l1);
values.1.push_highlighted(l2);
} else if lifetimes.0.is_late_bound() {
values.0.push_normal(l1);
values.1.push_normal(l2);
} else {
values.0.push_normal("'_");
values.1.push_normal("'_");
}
self.push_comma(&mut values.0, &mut values.1, len, i);
}

View file

@ -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()
}

View file

@ -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);

View file

@ -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" }

View file

@ -0,0 +1,341 @@
use rustc_errors::DiagnosticBuilder;
use rustc_infer::infer::canonical::Canonical;
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc_infer::infer::region_constraints::Constraint;
use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op;
use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _};
use rustc_traits::type_op_prove_predicate_with_span;
use std::fmt;
use std::rc::Rc;
use crate::borrow_check::region_infer::values::RegionElement;
use crate::borrow_check::MirBorrowckCtxt;
#[derive(Clone)]
crate struct UniverseInfo<'tcx>(UniverseInfoInner<'tcx>);
/// What operation a universe was created for.
#[derive(Clone)]
enum UniverseInfoInner<'tcx> {
/// Relating two types which have binders.
RelateTys { expected: Ty<'tcx>, found: Ty<'tcx> },
/// Created from performing a `TypeOp`.
TypeOp(Rc<dyn TypeOpInfo<'tcx> + 'tcx>),
/// Any other reason.
Other,
}
impl UniverseInfo<'tcx> {
crate fn other() -> UniverseInfo<'tcx> {
UniverseInfo(UniverseInfoInner::Other)
}
crate fn relate(expected: Ty<'tcx>, found: Ty<'tcx>) -> UniverseInfo<'tcx> {
UniverseInfo(UniverseInfoInner::RelateTys { expected, found })
}
crate fn report_error(
&self,
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
placeholder: ty::PlaceholderRegion,
error_element: RegionElement,
span: Span,
) {
match self.0 {
UniverseInfoInner::RelateTys { expected, found } => {
let body_id = mbcx.infcx.tcx.hir().local_def_id_to_hir_id(mbcx.mir_def_id());
let err = mbcx.infcx.report_mismatched_types(
&ObligationCause::misc(span, body_id),
expected,
found,
TypeError::RegionsPlaceholderMismatch,
);
err.buffer(&mut mbcx.errors_buffer);
}
UniverseInfoInner::TypeOp(ref type_op_info) => {
type_op_info.report_error(mbcx, placeholder, error_element, span);
}
UniverseInfoInner::Other => {
// FIXME: This error message isn't great, but it doesn't show
// up in the existing UI tests. Consider investigating this
// some more.
mbcx.infcx
.tcx
.sess
.struct_span_err(span, "higher-ranked subtype error")
.buffer(&mut mbcx.errors_buffer);
}
}
}
}
crate trait ToUniverseInfo<'tcx> {
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx>;
}
impl<'tcx> ToUniverseInfo<'tcx>
for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>
{
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(PredicateQuery {
canonical_query: self,
base_universe,
})))
}
}
impl<'tcx, T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx> ToUniverseInfo<'tcx>
for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>
{
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(NormalizeQuery {
canonical_query: self,
base_universe,
})))
}
}
impl<'tcx> ToUniverseInfo<'tcx>
for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>
{
fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
// Ascribe user type isn't usually called on types that have different
// bound regions.
UniverseInfo::other()
}
}
impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F, G>> {
fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
// We can't rerun custom type ops.
UniverseInfo::other()
}
}
#[allow(unused_lifetimes)]
trait TypeOpInfo<'tcx> {
/// Returns an error to be reported if rerunning the type op fails to
/// recover the error's cause.
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx>;
fn base_universe(&self) -> ty::UniverseIndex;
fn nice_error(
&self,
tcx: TyCtxt<'tcx>,
span: Span,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>>;
fn report_error(
&self,
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
placeholder: ty::PlaceholderRegion,
error_element: RegionElement,
span: Span,
) {
let tcx = mbcx.infcx.tcx;
let base_universe = self.base_universe();
let adjusted_universe = if let Some(adjusted) =
placeholder.universe.as_u32().checked_sub(base_universe.as_u32())
{
adjusted
} else {
self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer);
return;
};
let placeholder_region = tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
name: placeholder.name,
universe: adjusted_universe.into(),
}));
let error_region =
if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
let adjusted_universe =
error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
adjusted_universe.map(|adjusted| {
tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
name: error_placeholder.name,
universe: adjusted.into(),
}))
})
} else {
None
};
debug!(?placeholder_region);
let nice_error = self.nice_error(tcx, span, placeholder_region, error_region);
if let Some(nice_error) = nice_error {
nice_error.buffer(&mut mbcx.errors_buffer);
} else {
self.fallback_error(tcx, span).buffer(&mut mbcx.errors_buffer);
}
}
}
struct PredicateQuery<'tcx> {
canonical_query:
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>,
base_universe: ty::UniverseIndex,
}
impl TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate));
err
}
fn base_universe(&self) -> ty::UniverseIndex {
self.base_universe
}
fn nice_error(
&self,
tcx: TyCtxt<'tcx>,
span: Span,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> {
tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
type_op_prove_predicate_with_span(infcx, &mut *fulfill_cx, key, Some(span));
try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
})
}
}
struct NormalizeQuery<'tcx, T> {
canonical_query: Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>,
base_universe: ty::UniverseIndex,
}
impl<T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
where
T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx,
{
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error");
err.note(&format!("could not normalize `{}`", self.canonical_query.value.value.value));
err
}
fn base_universe(&self) -> ty::UniverseIndex {
self.base_universe
}
fn nice_error(
&self,
tcx: TyCtxt<'tcx>,
span: Span,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> {
tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
let mut selcx = SelectionContext::new(infcx);
// FIXME(lqd): Unify and de-duplicate the following with the actual
// `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
// `ObligationCause`. The normalization results are currently different between
// `AtExt::normalize` used in the query and `normalize` called below: the former fails
// to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
// after #85499 lands to see if its fixes have erased this difference.
let (param_env, value) = key.into_parts();
let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize(
&mut selcx,
param_env,
ObligationCause::dummy_with_span(span),
value.value,
);
fulfill_cx.register_predicate_obligations(infcx, obligations);
try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
})
}
}
fn try_extract_error_from_fulfill_cx<'tcx>(
mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
infcx: &InferCtxt<'_, 'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx>> {
let tcx = infcx.tcx;
// We generally shouldn't have errors here because the query was
// already run, but there's no point using `delay_span_bug`
// when we're going to emit an error here anyway.
let _errors = fulfill_cx.select_all_or_error(infcx).err().unwrap_or_else(Vec::new);
let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| {
debug!(?region_constraints);
region_constraints.constraints.iter().find_map(|(constraint, cause)| {
match *constraint {
Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => {
Some((sub, cause.clone()))
}
// FIXME: Should this check the universe of the var?
Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
Some((tcx.mk_region(ty::ReVar(vid)), cause.clone()))
}
_ => None,
}
})
})?;
debug!(?sub_region, ?cause);
let nice_error = match (error_region, sub_region) {
(Some(error_region), &ty::ReVar(vid)) => NiceRegionError::new(
infcx,
RegionResolutionError::SubSupConflict(
vid,
infcx.region_var_origin(vid),
cause.clone(),
error_region,
cause.clone(),
placeholder_region,
),
),
(Some(error_region), _) => NiceRegionError::new(
infcx,
RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region),
),
// Note universe here is wrong...
(None, &ty::ReVar(vid)) => NiceRegionError::new(
infcx,
RegionResolutionError::UpperBoundUniverseConflict(
vid,
infcx.region_var_origin(vid),
infcx.universe_of_region(sub_region),
cause.clone(),
placeholder_region,
),
),
(None, _) => NiceRegionError::new(
infcx,
RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region),
),
};
nice_error.try_report_from_nll().or_else(|| {
if let SubregionOrigin::Subtype(trace) = cause {
Some(
infcx.report_and_explain_type_error(*trace, &TypeError::RegionsPlaceholderMismatch),
)
} else {
None
}
})
}

View file

@ -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};

View file

@ -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 } => {

View file

@ -241,6 +241,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
outlives_constraints,
member_constraints,
closure_bounds_mapping,
universe_causes,
type_tests,
} = constraints;
let placeholder_indices = Rc::new(placeholder_indices);
@ -262,6 +263,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
outlives_constraints,
member_constraints,
closure_bounds_mapping,
universe_causes,
type_tests,
liveness_constraints,
elements,

View file

@ -21,7 +21,7 @@ use crate::borrow_check::{
constraints::{
graph::NormalConstraintGraph, ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
},
diagnostics::{RegionErrorKind, RegionErrors},
diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo},
member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
nll::{PoloniusOutput, ToRegionVid},
region_infer::reverse_sccs::ReverseSccGraph,
@ -84,6 +84,9 @@ pub struct RegionInferenceContext<'tcx> {
closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
/// Map universe indexes to information on why we created it.
universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
/// Contains the minimum universe of any variable within the same
/// SCC. We will ensure that no SCC contains values that are not
/// visible from this index.
@ -253,6 +256,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
Location,
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
>,
universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
type_tests: Vec<TypeTest<'tcx>>,
liveness_constraints: LivenessValues<RegionVid>,
elements: &Rc<RegionValueElements>,
@ -293,6 +297,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
member_constraints,
member_constraints_applied: Vec::new(),
closure_bounds_mapping,
universe_causes,
scc_universes,
scc_representatives,
scc_values,
@ -1632,7 +1637,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
errors_buffer.push(RegionErrorKind::BoundUniversalRegionError {
longer_fr,
error_element,
fr_origin: NllRegionVariableOrigin::Placeholder(placeholder),
placeholder,
});
}
@ -1918,8 +1923,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
/// Get the region outlived by `longer_fr` and live at `element`.
crate fn region_from_element(&self, longer_fr: RegionVid, element: RegionElement) -> RegionVid {
match element {
crate fn region_from_element(
&self,
longer_fr: RegionVid,
element: &RegionElement,
) -> RegionVid {
match *element {
RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
RegionElement::RootUniversalRegion(r) => r,
RegionElement::PlaceholderRegion(error_placeholder) => self
@ -2138,6 +2147,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
categorized_path.remove(0)
}
crate fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
self.universe_causes[universe].clone()
}
}
impl<'tcx> RegionDefinition<'tcx> {

View file

@ -0,0 +1,158 @@
use std::fmt;
use rustc_hir as hir;
use rustc_infer::infer::canonical::Canonical;
use rustc_infer::traits::query::NoSolution;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{self, ToPredicate, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
use rustc_trait_selection::traits::query::Fallible;
use crate::borrow_check::diagnostics::{ToUniverseInfo, UniverseInfo};
use super::{Locations, NormalizeLocation, TypeChecker};
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
/// Given some operation `op` that manipulates types, proves
/// predicates, or otherwise uses the inference context, executes
/// `op` and then executes all the further obligations that `op`
/// returns. This will yield a set of outlives constraints amongst
/// regions which are extracted and stored as having occurred at
/// `locations`.
///
/// **Any `rustc_infer::infer` operations that might generate region
/// constraints should occur within this method so that those
/// constraints can be properly localized!**
pub(super) fn fully_perform_op<R, Op>(
&mut self,
locations: Locations,
category: ConstraintCategory,
op: Op,
) -> Fallible<R>
where
Op: type_op::TypeOp<'tcx, Output = R>,
Canonical<'tcx, Op>: ToUniverseInfo<'tcx>,
{
let old_universe = self.infcx.universe();
let TypeOpOutput { output, constraints, canonicalized_query } =
op.fully_perform(self.infcx)?;
if let Some(data) = &constraints {
self.push_region_constraints(locations, category, data);
}
let universe = self.infcx.universe();
if old_universe != universe {
let universe_info = match canonicalized_query {
Some(canonicalized_query) => canonicalized_query.to_universe_info(old_universe),
None => UniverseInfo::other(),
};
for u in old_universe..universe {
let info_universe =
self.borrowck_context.constraints.universe_causes.push(universe_info.clone());
assert_eq!(u.as_u32() + 1, info_universe.as_u32());
}
}
Ok(output)
}
pub(super) fn instantiate_canonical_with_fresh_inference_vars<T>(
&mut self,
span: Span,
canonical: &Canonical<'tcx, T>,
) -> T
where
T: TypeFoldable<'tcx>,
{
let (instantiated, _) =
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
for _ in 0..canonical.max_universe.as_u32() {
let info = UniverseInfo::other();
self.borrowck_context.constraints.universe_causes.push(info);
}
instantiated
}
pub(super) fn prove_trait_ref(
&mut self,
trait_ref: ty::TraitRef<'tcx>,
locations: Locations,
category: ConstraintCategory,
) {
self.prove_predicates(
Some(ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: hir::Constness::NotConst,
})),
locations,
category,
);
}
pub(super) fn normalize_and_prove_instantiated_predicates(
&mut self,
instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
locations: Locations,
) {
for predicate in instantiated_predicates.predicates {
let predicate = self.normalize(predicate, locations);
self.prove_predicate(predicate, locations, ConstraintCategory::Boring);
}
}
pub(super) fn prove_predicates(
&mut self,
predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
locations: Locations,
category: ConstraintCategory,
) {
for predicate in predicates {
let predicate = predicate.to_predicate(self.tcx());
debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,);
self.prove_predicate(predicate, locations, category);
}
}
pub(super) fn prove_predicate(
&mut self,
predicate: ty::Predicate<'tcx>,
locations: Locations,
category: ConstraintCategory,
) {
debug!("prove_predicate(predicate={:?}, location={:?})", predicate, locations,);
let param_env = self.param_env;
self.fully_perform_op(
locations,
category,
param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
)
.unwrap_or_else(|NoSolution| {
span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
})
}
pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
where
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
{
debug!("normalize(value={:?}, location={:?})", value, location);
let param_env = self.param_env;
self.fully_perform_op(
location.to_locations(),
ConstraintCategory::Boring,
param_env.and(type_op::normalize::Normalize::new(value)),
)
.unwrap_or_else(|NoSolution| {
span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);
value
})
}
}

View file

@ -11,6 +11,7 @@ use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc;
use type_op::TypeOpOutput;
use crate::borrow_check::{
nll::ToRegionVid,
@ -255,7 +256,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
let constraint_sets: Vec<_> = unnormalized_input_output_tys
.flat_map(|ty| {
debug!("build: input_or_output={:?}", ty);
let (ty, constraints1) = self
let TypeOpOutput { output: ty, constraints: constraints1, .. } = self
.param_env
.and(type_op::normalize::Normalize::new(ty))
.fully_perform(self.infcx)
@ -264,7 +265,11 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
.tcx
.sess
.delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty));
(self.infcx.tcx.ty_error(), None)
TypeOpOutput {
output: self.infcx.tcx.ty_error(),
constraints: None,
canonicalized_query: None,
}
});
let constraints2 = self.add_implied_bounds(ty);
normalized_inputs_and_output.push(ty);
@ -317,7 +322,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
/// from this local.
fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<Rc<QueryRegionConstraints<'tcx>>> {
debug!("add_implied_bounds(ty={:?})", ty);
let (bounds, constraints) = self
let TypeOpOutput { output: bounds, constraints, .. } = self
.param_env
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
.fully_perform(self.infcx)

View file

@ -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,
);

View file

@ -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 }
}
}

View file

@ -38,7 +38,7 @@ use rustc_trait_selection::opaque_types::{GenerateMemberConstraints, InferCtxtEx
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
use rustc_trait_selection::traits::query::type_op;
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
use rustc_trait_selection::traits::query::{Fallible, NoSolution};
use rustc_trait_selection::traits::query::Fallible;
use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations};
use crate::dataflow::impls::MaybeInitializedPlaces;
@ -51,6 +51,7 @@ use crate::transform::{
use crate::borrow_check::{
borrow_set::BorrowSet,
constraints::{OutlivesConstraint, OutlivesConstraintSet},
diagnostics::UniverseInfo,
facts::AllFacts,
location::LocationTable,
member_constraints::MemberConstraintSet,
@ -89,6 +90,7 @@ macro_rules! span_mirbug_and_err {
})
}
mod canonical;
mod constraint_conversion;
pub mod free_region_relations;
mod input_output;
@ -142,6 +144,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
member_constraints: MemberConstraintSet::default(),
closure_bounds_mapping: Default::default(),
type_tests: Vec::default(),
universe_causes: IndexVec::from_elem_n(UniverseInfo::other(), 1),
};
let CreateResult {
@ -156,6 +159,11 @@ pub(crate) fn type_check<'mir, 'tcx>(
&mut constraints,
);
for _ in ty::UniverseIndex::ROOT..infcx.universe() {
let info = UniverseInfo::other();
constraints.universe_causes.push(info);
}
let mut borrowck_context = BorrowCheckContext {
universal_regions,
location_table,
@ -376,8 +384,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
ty,
san_ty| {
if let Err(terr) = verifier.cx.eq_types(
san_ty,
ty,
san_ty,
location.to_locations(),
ConstraintCategory::Boring,
) {
@ -425,8 +433,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty;
if let Err(terr) = self.cx.eq_types(
normalized_ty,
literal_ty,
normalized_ty,
locations,
ConstraintCategory::Boring,
) {
@ -542,7 +550,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
return PlaceTy::from_ty(self.tcx().ty_error());
}
}
place_ty = self.sanitize_projection(place_ty, elem, place, location)
place_ty = self.sanitize_projection(place_ty, elem, place, location);
}
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
@ -916,6 +924,8 @@ crate struct MirTypeckRegionConstraints<'tcx> {
crate closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
crate universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
crate type_tests: Vec<TypeTest<'tcx>>,
}
@ -1043,8 +1053,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
for user_annotation in self.user_type_annotations {
let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
let (annotation, _) =
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, user_ty);
let annotation = self.instantiate_canonical_with_fresh_inference_vars(span, user_ty);
match annotation {
UserType::Ty(mut ty) => {
ty = self.normalize(ty, Locations::All(span));
@ -1097,31 +1106,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
/// Given some operation `op` that manipulates types, proves
/// predicates, or otherwise uses the inference context, executes
/// `op` and then executes all the further obligations that `op`
/// returns. This will yield a set of outlives constraints amongst
/// regions which are extracted and stored as having occurred at
/// `locations`.
///
/// **Any `rustc_infer::infer` operations that might generate region
/// constraints should occur within this method so that those
/// constraints can be properly localized!**
fn fully_perform_op<R>(
&mut self,
locations: Locations,
category: ConstraintCategory,
op: impl type_op::TypeOp<'tcx, Output = R>,
) -> Fallible<R> {
let (r, opt_data) = op.fully_perform(self.infcx)?;
if let Some(data) = &opt_data {
self.push_region_constraints(locations, category, data);
}
Ok(r)
}
fn push_region_constraints(
&mut self,
locations: Locations,
@ -1161,7 +1145,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
b,
locations,
category,
Some(self.borrowck_context),
self.borrowck_context,
)
}
@ -1173,17 +1157,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
locations: Locations,
category: ConstraintCategory,
) -> Fallible<()> {
self.relate_types(sub, ty::Variance::Covariant, sup, locations, category)
// Use this order of parameters because the sup type is usually the
// "expected" type in diagnostics.
self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
}
fn eq_types(
&mut self,
a: Ty<'tcx>,
b: Ty<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory,
) -> Fallible<()> {
self.relate_types(a, ty::Variance::Invariant, b, locations, category)
self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
}
fn relate_type_and_user_type(
@ -1222,7 +1208,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
let ty = curr_projected_ty.ty;
self.relate_types(a, v, ty, locations, category)?;
self.relate_types(ty, v.xform(ty::Variance::Contravariant), a, locations, category)?;
Ok(())
}
@ -2053,8 +2039,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let ty_fn_ptr_from = tcx.mk_fn_ptr(fn_sig);
if let Err(terr) = self.eq_types(
ty_fn_ptr_from,
ty,
ty_fn_ptr_from,
location.to_locations(),
ConstraintCategory::Cast,
) {
@ -2077,8 +2063,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let ty_fn_ptr_from = tcx.mk_fn_ptr(tcx.signature_unclosure(sig, *unsafety));
if let Err(terr) = self.eq_types(
ty_fn_ptr_from,
ty,
ty_fn_ptr_from,
location.to_locations(),
ConstraintCategory::Cast,
) {
@ -2106,8 +2092,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
if let Err(terr) = self.eq_types(
ty_fn_ptr_from,
ty,
ty_fn_ptr_from,
location.to_locations(),
ConstraintCategory::Cast,
) {
@ -2294,20 +2280,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
kind: TypeVariableOriginKind::MiscVariable,
span: body.source_info(location).span,
});
self.relate_types(
common_ty,
ty::Variance::Contravariant,
self.sub_types(
ty_left,
common_ty,
location.to_locations(),
ConstraintCategory::Boring,
)
.unwrap_or_else(|err| {
bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
});
if let Err(terr) = self.relate_types(
common_ty,
ty::Variance::Contravariant,
if let Err(terr) = self.sub_types(
ty_right,
common_ty,
location.to_locations(),
ConstraintCategory::Boring,
) {
@ -2682,66 +2666,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
tcx.predicates_of(def_id).instantiate(tcx, substs)
}
fn prove_trait_ref(
&mut self,
trait_ref: ty::TraitRef<'tcx>,
locations: Locations,
category: ConstraintCategory,
) {
self.prove_predicates(
Some(ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: hir::Constness::NotConst,
})),
locations,
category,
);
}
fn normalize_and_prove_instantiated_predicates(
&mut self,
instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
locations: Locations,
) {
for predicate in instantiated_predicates.predicates {
let predicate = self.normalize(predicate, locations);
self.prove_predicate(predicate, locations, ConstraintCategory::Boring);
}
}
fn prove_predicates(
&mut self,
predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
locations: Locations,
category: ConstraintCategory,
) {
for predicate in predicates {
let predicate = predicate.to_predicate(self.tcx());
debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,);
self.prove_predicate(predicate, locations, category);
}
}
fn prove_predicate(
&mut self,
predicate: ty::Predicate<'tcx>,
locations: Locations,
category: ConstraintCategory,
) {
debug!("prove_predicate(predicate={:?}, location={:?})", predicate, locations,);
let param_env = self.param_env;
self.fully_perform_op(
locations,
category,
param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
)
.unwrap_or_else(|NoSolution| {
span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
})
}
fn typeck_mir(&mut self, body: &Body<'tcx>) {
self.last_span = body.span;
debug!("run_on_mir: {:?}", body.span);
@ -2764,23 +2688,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.check_iscleanup(&body, block_data);
}
}
fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
where
T: type_op::normalize::Normalizable<'tcx> + Copy + 'tcx,
{
debug!("normalize(value={:?}, location={:?})", value, location);
let param_env = self.param_env;
self.fully_perform_op(
location.to_locations(),
ConstraintCategory::Boring,
param_env.and(type_op::normalize::Normalize::new(value)),
)
.unwrap_or_else(|NoSolution| {
span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);
value
})
}
}
trait NormalizeLocation: fmt::Debug + Copy {

View file

@ -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

View file

@ -1,13 +1,13 @@
use crate::infer::{InferCtxt, InferOk};
use crate::traits::query::Fallible;
use std::fmt;
use crate::infer::canonical::query_response;
use crate::infer::canonical::QueryRegionConstraints;
use crate::infer::{InferCtxt, InferOk};
use crate::traits::engine::TraitEngineExt as _;
use crate::traits::query::type_op::TypeOpOutput;
use crate::traits::query::Fallible;
use crate::traits::{ObligationCause, TraitEngine};
use rustc_infer::traits::TraitEngineExt as _;
use rustc_span::source_map::DUMMY_SP;
use std::fmt;
use std::rc::Rc;
pub struct CustomTypeOp<F, G> {
@ -35,10 +35,7 @@ where
/// Processes the operation and all resulting obligations,
/// returning the final result along with any region constraints
/// (they will be given over to the NLL region solver).
fn fully_perform(
self,
infcx: &InferCtxt<'_, 'tcx>,
) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
if cfg!(debug_assertions) {
info!("fully_perform({:?})", self);
}
@ -58,10 +55,10 @@ where
/// Executes `op` and then scrapes out all the "old style" region
/// constraints that result, creating query-region-constraints.
fn scrape_region_constraints<'tcx, R>(
fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
infcx: &InferCtxt<'_, 'tcx>,
op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
) -> Fallible<(R, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
) -> Fallible<TypeOpOutput<'tcx, Op>> {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
let dummy_body_id = ObligationCause::dummy().body_id;
@ -101,8 +98,12 @@ fn scrape_region_constraints<'tcx, R>(
);
if region_constraints.is_empty() {
Ok((value, None))
Ok(TypeOpOutput { output: value, constraints: None, canonicalized_query: None })
} else {
Ok((value, Some(Rc::new(region_constraints))))
Ok(TypeOpOutput {
output: value,
constraints: Some(Rc::new(region_constraints)),
canonicalized_query: None,
})
}
}

View file

@ -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>,
}

View file

@ -4,6 +4,7 @@ use crate::infer::canonical::{
use crate::infer::{InferCtxt, InferOk};
use crate::traits::query::Fallible;
use crate::traits::ObligationCause;
use rustc_infer::infer::canonical::Canonical;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
use std::fmt;
@ -30,10 +31,18 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
/// Processes the operation and all resulting obligations,
/// returning the final result along with any region constraints
/// (they will be given over to the NLL region solver).
fn fully_perform(
self,
infcx: &InferCtxt<'_, 'tcx>,
) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)>;
fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>>;
}
/// The output from performing a type op
pub struct TypeOpOutput<'tcx, Op: TypeOp<'tcx>> {
/// The output from the type op.
pub output: Op::Output,
/// Any region constraints from performing the type op.
pub constraints: Option<Rc<QueryRegionConstraints<'tcx>>>,
/// The canonicalized form of the query.
/// This for error reporting to be able to rerun the query.
pub canonicalized_query: Option<Canonical<'tcx, Op>>,
}
/// "Query type ops" are type ops that are implemented using a
@ -45,7 +54,7 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
/// which produces the resulting query region constraints.
///
/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
type QueryResponse: TypeFoldable<'tcx>;
/// Give query the option for a simple fast path that never
@ -71,9 +80,9 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
query_key: ParamEnvAnd<'tcx, Self>,
infcx: &InferCtxt<'_, 'tcx>,
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
) -> Fallible<Self::QueryResponse> {
) -> Fallible<(Self::QueryResponse, Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>)> {
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
return Ok(result);
return Ok((result, None));
}
// FIXME(#33684) -- We need to use
@ -101,14 +110,14 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
// create obligations. In that case, we have to go
// fulfill them. We do this via a (recursive) query.
for obligation in obligations {
let () = ProvePredicate::fully_perform_into(
let ((), _) = ProvePredicate::fully_perform_into(
obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
infcx,
output_query_region_constraints,
)?;
}
Ok(value)
Ok((value, Some(canonical_self)))
}
}
@ -118,18 +127,16 @@ where
{
type Output = Q::QueryResponse;
fn fully_perform(
self,
infcx: &InferCtxt<'_, 'tcx>,
) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
let mut region_constraints = QueryRegionConstraints::default();
let r = Q::fully_perform_into(self, infcx, &mut region_constraints)?;
let (output, canonicalized_query) =
Q::fully_perform_into(self, infcx, &mut region_constraints)?;
// Promote the final query-region-constraints into a
// (optional) ref-counted vector:
let opt_qrc =
let region_constraints =
if region_constraints.is_empty() { None } else { Some(Rc::new(region_constraints)) };
Ok((r, opt_qrc))
Ok(TypeOpOutput { output, constraints: region_constraints, canonicalized_query })
}
}

View file

@ -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) {

View file

@ -8,7 +8,7 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts};
use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable, Variance};
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Predicate, ToPredicate};
use rustc_span::DUMMY_SP;
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::query::normalize::AtExt;
@ -236,11 +236,25 @@ fn type_op_prove_predicate<'tcx>(
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
let (param_env, ProvePredicate { predicate }) = key.into_parts();
fulfill_cx.register_predicate_obligation(
infcx,
Obligation::new(ObligationCause::dummy(), param_env, predicate),
);
type_op_prove_predicate_with_span(infcx, fulfill_cx, key, None);
Ok(())
})
}
/// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors,
/// this query can be re-run to better track the span of the obligation cause, and improve the error
/// message. Do not call directly unless you're in that very specific context.
pub fn type_op_prove_predicate_with_span<'a, 'tcx: 'a>(
infcx: &'a InferCtxt<'a, 'tcx>,
fulfill_cx: &'a mut dyn TraitEngine<'tcx>,
key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>,
span: Option<Span>,
) {
let cause = if let Some(span) = span {
ObligationCause::dummy_with_span(span)
} else {
ObligationCause::dummy()
};
let (param_env, ProvePredicate { predicate }) = key.into_parts();
fulfill_cx.register_predicate_obligation(infcx, Obligation::new(cause, param_env, predicate));
}

View file

@ -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`.

View file

@ -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`.

View file

@ -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

View file

@ -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`.

View file

@ -14,7 +14,7 @@ pub fn crash<V>(v: &V)
where
for<'a> &'a V: T + 'static,
{
v.t(|| {}); //~ ERROR: higher-ranked subtype error
v.t(|| {}); //~ ERROR: higher-ranked lifetime error
}
fn main() {}

View file

@ -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

View file

@ -1,14 +1,17 @@
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:45:13
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
...
LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32,
LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
| |_____________________________________________- in this macro invocation
|
= note: expected enum `Option<for<'r, 's> fn(&'r u32, &'s u32) -> &'r u32>`
found enum `Option<for<'r> fn(&'r u32, &'r u32) -> &'r u32>`
= note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,14 +1,17 @@
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:45:13
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
...
LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
LL | | fn(&'x u32)) }
| |______________- in this macro invocation
|
= note: expected enum `Option<for<'r> fn(&'r u32)>`
found enum `Option<fn(&u32)>`
= note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,26 +1,31 @@
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:45:13
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
...
LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
| |__________________________________- in this macro invocation
|
= note: expected enum `Option<for<'r, 's> fn(Inv<'r>, Inv<'s>)>`
found enum `Option<for<'r> fn(Inv<'r>, Inv<'r>)>`
= note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/hr-subtype.rs:45:13
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
...
LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
| |__________________________________- in this macro invocation
|
= note: expected enum `Option<for<'r, 's> fn(Inv<'r>, Inv<'s>)>`
found enum `Option<for<'r> fn(Inv<'r>, Inv<'r>)>`
= note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,14 +1,20 @@
error: higher-ranked subtype error
error: implementation of `Foo` is not general enough
--> $DIR/hrtb-conflate-regions.rs:27:10
|
LL | fn b() { want_foo2::<SomeStruct>(); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
= note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
error: higher-ranked subtype error
error: implementation of `Foo` is not general enough
--> $DIR/hrtb-conflate-regions.rs:27:10
|
LL | fn b() { want_foo2::<SomeStruct>(); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`...
= note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2`
error: aborting due to 2 previous errors

View file

@ -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`.

View file

@ -1,8 +1,11 @@
error: higher-ranked subtype error
error: implementation of `Trait` is not general enough
--> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5
|
LL | foo::<()>();
| ^^^^^^^^^^^
| ^^^^^^^^^^^ implementation of `Trait` is not general enough
|
= note: `()` must implement `Trait<for<'b> fn(&'b u32)>`
= note: ...but it actually implements `Trait<fn(&'0 u32)>`, for some specific lifetime `'0`
error: aborting due to previous error

View file

@ -1,8 +1,11 @@
error: higher-ranked subtype error
error: implementation of `Trait` is not general enough
--> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5
|
LL | foo::<()>();
| ^^^^^^^^^^^
| ^^^^^^^^^^^ implementation of `Trait` is not general enough
|
= note: `()` must implement `Trait<for<'b> fn(Cell<&'b u32>)>`
= note: ...but it actually implements `Trait<fn(Cell<&'0 u32>)>`, for some specific lifetime `'0`
error: aborting due to previous error

View file

@ -1,8 +1,11 @@
error: higher-ranked subtype error
error: implementation of `Foo` is not general enough
--> $DIR/hrtb-just-for-static.rs:24:5
|
LL | want_hrtb::<StaticInt>()
| ^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`...
= note: ...but it actually implements `Foo<&'static isize>`
error: lifetime may not live long enough
--> $DIR/hrtb-just-for-static.rs:30:5

View file

@ -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

View file

@ -1,8 +1,11 @@
error: higher-ranked subtype error
error: implementation of `Foo` is not general enough
--> $DIR/issue-46989.rs:38:5
|
LL | assert_foo::<fn(&i32)>();
| ^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `Foo` would have to be implemented for the type `for<'r> fn(&'r i32)`
= note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0`
error: aborting due to previous error

View file

@ -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`.

View file

@ -1,26 +1,38 @@
error: higher-ranked subtype error
error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:63:5
|
LL | <u32 as RefFoo<u32>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`...
= note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
error: higher-ranked subtype error
error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:69:5
|
LL | <i32 as RefFoo<i32>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`...
= note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1`
error: higher-ranked subtype error
error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:75:5
|
LL | <u64 as RefFoo<u64>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`...
= note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1`
error: higher-ranked subtype error
error: implementation of `Foo` is not general enough
--> $DIR/issue-54302-cases.rs:81:5
|
LL | <i64 as RefFoo<i64>>::ref_foo(a)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`...
= note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1`
error: aborting due to 4 previous errors

View file

@ -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

View file

@ -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

View file

@ -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`.

View file

@ -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`.

View file

@ -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`.

View file

@ -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`.

View file

@ -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`.

View file

@ -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]
}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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`.

View file

@ -30,6 +30,6 @@ impl<T> Y for fn(T) {
fn main() {
let _x = <fn(&())>::make_f();
//~^ higher-ranked subtype error
//~| higher-ranked subtype error
//~^ ERROR implementation of `Y` is not general enough
//~| ERROR implementation of `Y` is not general enough
}

View file

@ -1,14 +1,20 @@
error: higher-ranked subtype error
error: implementation of `Y` is not general enough
--> $DIR/impl-fn-ignore-binder-via-bottom.rs:32:14
|
LL | let _x = <fn(&())>::make_f();
| ^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough
|
= note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())`
= note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
error: higher-ranked subtype error
error: implementation of `Y` is not general enough
--> $DIR/impl-fn-ignore-binder-via-bottom.rs:32:14
|
LL | let _x = <fn(&())>::make_f();
| ^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough
|
= note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())`
= note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
error: aborting due to 2 previous errors

View file

@ -12,5 +12,5 @@ fn make_foo<'a>() -> Box<dyn Foo<'a>> {
fn main() {
let x: Box<dyn Foo<'static>> = make_foo();
let y: Box<dyn for<'a> Foo<'a>> = x; //~ ERROR higher-ranked subtype error
let y: Box<dyn for<'a> Foo<'a>> = x; //~ ERROR mismatched types [E0308]
}

View file

@ -1,8 +1,12 @@
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/trait-hrtb.rs:15:39
|
LL | let y: Box<dyn for<'a> Foo<'a>> = x;
| ^
| ^ one type is more general than the other
|
= note: expected trait object `dyn for<'r> Foo<'r>`
found trait object `dyn Foo<'_>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -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);
}

View file

@ -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`.

View file

@ -27,17 +27,24 @@ LL | a(x, y);
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12
|
LL | let _: fn(&mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)`
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12
|
LL | let _: fn(&mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)`
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -27,23 +27,33 @@ LL | a(x, y, z);
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12
|
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)`
found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)`
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12
|
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)`
found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)`
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12
|
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)`
found fn pointer `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 mut &isize)`
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -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`.

View file

@ -27,17 +27,24 @@ LL | a(x, y);
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/regions-lifetime-bounds-on-fns.rs:20:12
|
LL | let _: fn(&mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)`
error: higher-ranked subtype error
error[E0308]: mismatched types
--> $DIR/regions-lifetime-bounds-on-fns.rs:20:12
|
LL | let _: fn(&mut &isize, &mut &isize) = a;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
found fn pointer `for<'r, 's> fn(&'r mut &isize, &'s mut &isize)`
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -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`.

View file

@ -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

View file

@ -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