1
Fork 0

Lazily resolve type-alias-impl-trait defining uses

by using an opaque type obligation to bubble up comparisons between opaque types and other types

Also uses proper obligation causes so that the body id works, because out of some reason nll uses body ids for logic instead of just diagnostics.
This commit is contained in:
Oli Scherer 2021-08-20 14:47:12 +00:00 committed by Oli Scherer
parent 8d2b598459
commit 0f6e06b7c0
284 changed files with 2646 additions and 2097 deletions

View file

@ -359,6 +359,7 @@ crate fn required_region_bounds<'tcx>(
| ty::PredicateKind::RegionOutlives(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::OpaqueType(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
// Search for a bound of the form `erased_self_ty

View file

@ -853,6 +853,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::OpaqueType(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
};
}

View file

@ -775,6 +775,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
span,
"TypeWellFormedFromEnv predicate should only exist in the environment"
),
ty::PredicateKind::OpaqueType(..) => {
todo!("{:#?}", obligation);
}
}
}

View file

@ -397,6 +397,9 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
ty::PredicateKind::OpaqueType(..) => {
todo!("{:#?}", obligation);
}
},
Some(pred) => match pred {
ty::PredicateKind::Trait(data) => {
@ -642,6 +645,20 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
ty::PredicateKind::OpaqueType(a, b) => {
match self.selcx.infcx().handle_opaque_type(
a,
b,
&obligation.cause,
obligation.param_env,
) {
Ok(value) => ProcessResult::Changed(mk_pending(value)),
Err(err) => ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError(
ExpectedFound::new(true, a, b),
err,
)),
}
}
},
}
}

View file

@ -313,6 +313,7 @@ fn predicate_references_self<'tcx>(
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::OpaqueType(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
}
}
@ -347,6 +348,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
| ty::PredicateKind::TypeOutlives(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::OpaqueType(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
}
})

View file

@ -3,7 +3,7 @@ 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 crate::traits::TraitEngine;
use rustc_infer::traits::TraitEngineExt as _;
use rustc_span::source_map::DUMMY_SP;
@ -60,7 +60,6 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
) -> Fallible<TypeOpOutput<'tcx, Op>> {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
let dummy_body_id = ObligationCause::dummy().body_id;
// During NLL, we expect that nobody will register region
// obligations **except** as part of a custom type op (and, at the
@ -75,7 +74,6 @@ fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
);
let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
fulfill_cx.register_predicate_obligations(infcx, obligations);
let errors = fulfill_cx.select_all_or_error(infcx);
if !errors.is_empty() {

View file

@ -254,6 +254,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
};
if obligation.predicate.skip_binder().self_ty().is_ty_var() {
debug!(ty = ?obligation.predicate.skip_binder().self_ty(), "ambiguous inference var or opaque type");
// Self is a type variable (e.g., `_: AsRef<str>`).
//
// This is somewhat problematic, as the current scheme can't really

View file

@ -37,6 +37,7 @@ use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
@ -697,6 +698,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for chalk")
}
ty::PredicateKind::OpaqueType(a, b) => {
match self.infcx().handle_opaque_type(
a,
b,
&obligation.cause,
obligation.param_env,
) {
Ok(obligations) => {
self.evaluate_predicates_recursively(previous_stack, obligations)
}
Err(_) => Ok(EvaluatedToErr),
}
}
}
});
@ -1337,6 +1351,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
#[instrument(skip(self, param_env, cache_fresh_trait_pred, dep_node), level = "debug")]
fn insert_candidate_cache(
&mut self,
mut param_env: ty::ParamEnv<'tcx>,
@ -1377,6 +1392,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// a projection, look at the bounds of `T::Bar`, see if we can find a
/// `Baz` bound. We return indexes into the list returned by
/// `tcx.item_bounds` for any applicable bounds.
#[instrument(level = "debug", skip(self))]
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &TraitObligation<'tcx>,
@ -1384,10 +1400,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let poly_trait_predicate = self.infcx().resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate =
self.infcx().replace_bound_vars_with_placeholders(poly_trait_predicate);
debug!(
?placeholder_trait_predicate,
"match_projection_obligation_against_definition_bounds"
);
debug!(?placeholder_trait_predicate);
let tcx = self.infcx.tcx;
let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
@ -1438,7 +1451,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
})
.collect();
debug!(?matching_bounds, "match_projection_obligation_against_definition_bounds");
debug!(?matching_bounds);
matching_bounds
}
@ -1468,6 +1481,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
});
self.infcx
.at(&obligation.cause, obligation.param_env)
.define_opaque_types(false)
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
.map(|InferOk { obligations: _, value: () }| {
// This method is called within a probe, so we can't have
@ -1523,6 +1537,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx
.at(&obligation.cause, obligation.param_env)
.define_opaque_types(false)
.sup(obligation.predicate, infer_projection)
.map_or(false, |InferOk { obligations, value: () }| {
self.evaluate_predicates_recursively(
@ -2081,11 +2096,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
match self.match_impl(impl_def_id, obligation) {
Ok(substs) => substs,
Err(()) => {
bug!(
"Impl {:?} was matchable against {:?} but now is not",
impl_def_id,
obligation
self.infcx.tcx.sess.delay_span_bug(
obligation.cause.span,
&format!(
"Impl {:?} was matchable against {:?} but now is not",
impl_def_id, obligation
),
);
let value = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
let err = self.tcx().ty_error();
let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx(),
ty_op: |_| err,
lt_op: |l| l,
ct_op: |c| c,
});
Normalized { value, obligations: vec![] }
}
}
}
@ -2222,6 +2248,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
self.infcx
.at(&obligation.cause, obligation.param_env)
// We don't want opaque types to just randomly match everything,
// they should be opaque, even in their defining scope.
.define_opaque_types(false)
.sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
.map(|InferOk { obligations, .. }| obligations)
.map_err(|_| ())

View file

@ -146,6 +146,10 @@ pub fn predicate_obligations<'a, 'tcx>(
wf.compute(c1.into());
wf.compute(c2.into());
}
ty::PredicateKind::OpaqueType(opaque, ty) => {
wf.compute(opaque.into());
wf.compute(ty.into());
}
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}