2014-12-17 14:16:28 -05:00
|
|
|
//! Code for projecting associated types out of trait references.
|
|
|
|
|
2016-02-16 10:36:47 -08:00
|
|
|
use super::specialization_graph;
|
|
|
|
use super::translate_substs;
|
2019-12-22 17:42:04 -05:00
|
|
|
use super::util;
|
2020-02-11 19:46:31 +01:00
|
|
|
use super::MismatchedProjectionTypes;
|
2014-12-17 14:16:28 -05:00
|
|
|
use super::Obligation;
|
2014-12-30 17:42:02 -05:00
|
|
|
use super::ObligationCause;
|
2014-12-17 14:16:28 -05:00
|
|
|
use super::PredicateObligation;
|
2018-02-18 12:32:23 +09:00
|
|
|
use super::Selection;
|
2014-12-17 14:16:28 -05:00
|
|
|
use super::SelectionContext;
|
|
|
|
use super::SelectionError;
|
2020-04-05 19:57:32 +02:00
|
|
|
use super::{
|
2020-05-11 15:25:33 +00:00
|
|
|
ImplSourceClosureData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
|
2020-06-02 15:54:24 +00:00
|
|
|
ImplSourceGeneratorData, ImplSourceUserDefinedData,
|
2020-04-05 19:57:32 +02:00
|
|
|
};
|
2020-05-11 15:25:33 +00:00
|
|
|
use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2019-03-21 00:00:24 +00:00
|
|
|
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
2019-12-22 17:42:04 -05:00
|
|
|
use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
|
2020-02-22 11:44:18 +01:00
|
|
|
use crate::traits::error_reporting::InferCtxtExt;
|
2020-03-14 20:13:55 +02:00
|
|
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
2020-02-08 20:10:06 +00:00
|
|
|
use rustc_errors::ErrorReported;
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::def_id::DefId;
|
2020-08-18 11:47:27 +01:00
|
|
|
use rustc_hir::lang_items::LangItem;
|
2020-06-16 18:27:40 +01:00
|
|
|
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
|
2020-03-29 16:41:09 +02:00
|
|
|
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
|
2020-05-10 12:15:51 +01:00
|
|
|
use rustc_middle::ty::subst::Subst;
|
2020-03-29 16:41:09 +02:00
|
|
|
use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
|
2020-05-24 23:07:55 -04:00
|
|
|
use rustc_span::symbol::sym;
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2020-03-29 16:41:09 +02:00
|
|
|
pub use rustc_middle::traits::Reveal;
|
2016-02-23 12:47:09 -08:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
pub type ProjectionObligation<'tcx> = Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::ProjectionTy<'tcx>>;
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2020-08-13 20:45:08 +01:00
|
|
|
pub(super) struct InProgress;
|
|
|
|
|
2014-12-30 17:42:02 -05:00
|
|
|
/// When attempting to resolve `<T as TraitRef>::Name` ...
|
2015-06-18 08:51:23 +03:00
|
|
|
#[derive(Debug)]
|
2014-12-30 17:42:02 -05:00
|
|
|
pub enum ProjectionTyError<'tcx> {
|
2014-12-30 08:59:33 -05:00
|
|
|
/// ...we found multiple sources of information and couldn't resolve the ambiguity.
|
2014-12-17 14:16:28 -05:00
|
|
|
TooManyCandidates,
|
|
|
|
|
|
|
|
/// ...an error occurred matching `T : TraitRef`
|
|
|
|
TraitSelectionError(SelectionError<'tcx>),
|
|
|
|
}
|
|
|
|
|
2018-02-18 11:36:41 +09:00
|
|
|
#[derive(PartialEq, Eq, Debug)]
|
2014-12-17 14:16:28 -05:00
|
|
|
enum ProjectionTyCandidate<'tcx> {
|
2020-07-24 21:59:43 +01:00
|
|
|
/// From a where-clause in the env or object type
|
2014-12-17 14:16:28 -05:00
|
|
|
ParamEnv(ty::PolyProjectionPredicate<'tcx>),
|
2015-10-22 12:28:47 -04:00
|
|
|
|
2020-07-24 21:59:43 +01:00
|
|
|
/// From the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
|
2015-10-22 12:28:47 -04:00
|
|
|
TraitDef(ty::PolyProjectionPredicate<'tcx>),
|
|
|
|
|
2020-07-24 21:59:43 +01:00
|
|
|
/// Bounds specified on an object type
|
|
|
|
Object(ty::PolyProjectionPredicate<'tcx>),
|
|
|
|
|
|
|
|
/// From a "impl" (or a "pseudo-impl" returned by select)
|
2018-02-18 12:32:23 +09:00
|
|
|
Select(Selection<'tcx>),
|
2014-12-17 14:16:28 -05:00
|
|
|
}
|
|
|
|
|
2018-02-18 12:32:23 +09:00
|
|
|
enum ProjectionTyCandidateSet<'tcx> {
|
|
|
|
None,
|
|
|
|
Single(ProjectionTyCandidate<'tcx>),
|
|
|
|
Ambiguous,
|
|
|
|
Error(SelectionError<'tcx>),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> ProjectionTyCandidateSet<'tcx> {
|
|
|
|
fn mark_ambiguous(&mut self) {
|
|
|
|
*self = ProjectionTyCandidateSet::Ambiguous;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn mark_error(&mut self, err: SelectionError<'tcx>) {
|
|
|
|
*self = ProjectionTyCandidateSet::Error(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns true if the push was successful, or false if the candidate
|
|
|
|
// was discarded -- this could be because of ambiguity, or because
|
|
|
|
// a higher-priority candidate is already there.
|
|
|
|
fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool {
|
|
|
|
use self::ProjectionTyCandidate::*;
|
2019-12-22 17:42:04 -05:00
|
|
|
use self::ProjectionTyCandidateSet::*;
|
2018-05-31 10:17:51 -04:00
|
|
|
|
|
|
|
// This wacky variable is just used to try and
|
|
|
|
// make code readable and avoid confusing paths.
|
|
|
|
// It is assigned a "value" of `()` only on those
|
|
|
|
// paths in which we wish to convert `*self` to
|
|
|
|
// ambiguous (and return false, because the candidate
|
|
|
|
// was not used). On other paths, it is not assigned,
|
|
|
|
// and hence if those paths *could* reach the code that
|
|
|
|
// comes after the match, this fn would not compile.
|
2018-06-02 00:20:00 -07:00
|
|
|
let convert_to_ambiguous;
|
2018-05-31 10:17:51 -04:00
|
|
|
|
2018-02-18 12:32:23 +09:00
|
|
|
match self {
|
|
|
|
None => {
|
|
|
|
*self = Single(candidate);
|
2018-05-31 10:17:51 -04:00
|
|
|
return true;
|
2018-02-18 12:32:23 +09:00
|
|
|
}
|
2018-05-31 10:17:51 -04:00
|
|
|
|
2018-02-18 12:32:23 +09:00
|
|
|
Single(current) => {
|
2018-02-27 17:30:20 +09:00
|
|
|
// Duplicates can happen inside ParamEnv. In the case, we
|
|
|
|
// perform a lazy deduplication.
|
|
|
|
if current == &candidate {
|
|
|
|
return false;
|
|
|
|
}
|
2018-05-31 10:17:51 -04:00
|
|
|
|
2018-02-18 12:32:23 +09:00
|
|
|
// Prefer where-clauses. As in select, if there are multiple
|
|
|
|
// candidates, we prefer where-clause candidates over impls. This
|
|
|
|
// may seem a bit surprising, since impls are the source of
|
|
|
|
// "truth" in some sense, but in fact some of the impls that SEEM
|
|
|
|
// applicable are not, because of nested obligations. Where
|
|
|
|
// clauses are the safer choice. See the comment on
|
|
|
|
// `select::SelectionCandidate` and #21974 for more details.
|
|
|
|
match (current, candidate) {
|
2018-06-02 00:20:00 -07:00
|
|
|
(ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
|
2018-05-31 10:17:51 -04:00
|
|
|
(ParamEnv(..), _) => return false,
|
2018-09-12 16:57:19 +02:00
|
|
|
(_, ParamEnv(..)) => unreachable!(),
|
2018-06-02 00:20:00 -07:00
|
|
|
(_, _) => convert_to_ambiguous = (),
|
2018-02-18 12:32:23 +09:00
|
|
|
}
|
|
|
|
}
|
2018-05-31 10:17:51 -04:00
|
|
|
|
2018-02-18 12:32:23 +09:00
|
|
|
Ambiguous | Error(..) => {
|
2018-05-31 10:17:51 -04:00
|
|
|
return false;
|
2018-02-18 12:32:23 +09:00
|
|
|
}
|
|
|
|
}
|
2018-05-31 10:17:51 -04:00
|
|
|
|
|
|
|
// We only ever get here when we moved from a single candidate
|
|
|
|
// to ambiguous.
|
2018-06-02 00:20:00 -07:00
|
|
|
let () = convert_to_ambiguous;
|
2018-05-31 10:17:51 -04:00
|
|
|
*self = Ambiguous;
|
|
|
|
false
|
2018-02-18 12:32:23 +09:00
|
|
|
}
|
2014-12-17 14:16:28 -05:00
|
|
|
}
|
|
|
|
|
2015-01-26 14:20:38 -05:00
|
|
|
/// Evaluates constraints of the form:
|
|
|
|
///
|
|
|
|
/// for<...> <T as Trait>::U == V
|
|
|
|
///
|
2017-08-20 19:16:36 +03:00
|
|
|
/// If successful, this may result in additional obligations. Also returns
|
|
|
|
/// the projection cache key used to track these additional obligations.
|
2020-08-13 20:45:08 +01:00
|
|
|
///
|
|
|
|
/// ## Returns
|
|
|
|
///
|
|
|
|
/// - `Err(_)`: the projection can be normalized, but is not equal to the
|
|
|
|
/// expected type.
|
|
|
|
/// - `Ok(Err(InProgress))`: this is called recursively while normalizing
|
|
|
|
/// the same projection.
|
|
|
|
/// - `Ok(Ok(None))`: The projection cannot be normalized due to ambiguity
|
|
|
|
/// (resolving some inference variables in the projection may fix this).
|
|
|
|
/// - `Ok(Ok(Some(obligations)))`: The projection bound holds subject to
|
|
|
|
/// the given obligations. If the projection cannot be normalized because
|
|
|
|
/// the required trait bound doesn't hold this returned with `obligations`
|
|
|
|
/// being a predicate that cannot be proven.
|
2020-10-11 11:37:56 +01:00
|
|
|
#[instrument(level = "debug", skip(selcx))]
|
2020-08-13 20:45:08 +01:00
|
|
|
pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
|
2019-06-14 00:48:52 +03:00
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2019-06-14 01:32:15 +03:00
|
|
|
obligation: &PolyProjectionObligation<'tcx>,
|
2020-08-13 20:45:08 +01:00
|
|
|
) -> Result<
|
|
|
|
Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
|
|
|
|
MismatchedProjectionTypes<'tcx>,
|
|
|
|
> {
|
2014-12-17 14:16:28 -05:00
|
|
|
let infcx = selcx.infcx();
|
2020-05-22 18:16:28 +00:00
|
|
|
infcx.commit_if_ok(|_snapshot| {
|
2020-06-28 20:27:59 +01:00
|
|
|
let placeholder_predicate =
|
2018-11-03 14:52:37 +01:00
|
|
|
infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2018-09-07 20:11:23 -04:00
|
|
|
let placeholder_obligation = obligation.with(placeholder_predicate);
|
2019-02-20 05:22:23 -05:00
|
|
|
let result = project_and_unify_type(selcx, &placeholder_obligation)?;
|
|
|
|
Ok(result)
|
2015-02-03 06:12:43 -05:00
|
|
|
})
|
2014-12-17 14:16:28 -05:00
|
|
|
}
|
|
|
|
|
2015-01-26 14:20:38 -05:00
|
|
|
/// Evaluates constraints of the form:
|
|
|
|
///
|
|
|
|
/// <T as Trait>::U == V
|
|
|
|
///
|
|
|
|
/// If successful, this may result in additional obligations.
|
2020-08-13 20:45:08 +01:00
|
|
|
///
|
|
|
|
/// See [poly_project_and_unify_type] for an explanation of the return value.
|
2019-06-14 00:48:52 +03:00
|
|
|
fn project_and_unify_type<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2019-06-14 01:32:15 +03:00
|
|
|
obligation: &ProjectionObligation<'tcx>,
|
2020-08-13 20:45:08 +01:00
|
|
|
) -> Result<
|
|
|
|
Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
|
|
|
|
MismatchedProjectionTypes<'tcx>,
|
|
|
|
> {
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?obligation, "project_and_unify_type");
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2018-05-17 07:58:08 +10:00
|
|
|
let mut obligations = vec![];
|
2019-12-22 17:42:04 -05:00
|
|
|
let normalized_ty = match opt_normalize_projection_type(
|
|
|
|
selcx,
|
|
|
|
obligation.param_env,
|
|
|
|
obligation.predicate.projection_ty,
|
|
|
|
obligation.cause.clone(),
|
|
|
|
obligation.recursion_depth,
|
|
|
|
&mut obligations,
|
|
|
|
) {
|
2020-08-13 20:45:08 +01:00
|
|
|
Ok(Some(n)) => n,
|
|
|
|
Ok(None) => return Ok(Ok(None)),
|
|
|
|
Err(InProgress) => return Ok(Err(InProgress)),
|
2019-12-22 17:42:04 -05:00
|
|
|
};
|
2014-12-30 17:42:02 -05:00
|
|
|
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?normalized_ty, ?obligations, "project_and_unify_type result");
|
2014-12-30 17:42:02 -05:00
|
|
|
|
2014-12-17 14:16:28 -05:00
|
|
|
let infcx = selcx.infcx();
|
2019-12-22 17:42:04 -05:00
|
|
|
match infcx
|
|
|
|
.at(&obligation.cause, obligation.param_env)
|
|
|
|
.eq(normalized_ty, obligation.predicate.ty)
|
|
|
|
{
|
2016-08-24 18:09:46 -04:00
|
|
|
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
|
2016-05-12 18:01:23 -07:00
|
|
|
obligations.extend(inferred_obligations);
|
2020-08-13 20:45:08 +01:00
|
|
|
Ok(Ok(Some(obligations)))
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2018-04-26 13:31:24 -04:00
|
|
|
Err(err) => {
|
|
|
|
debug!("project_and_unify_type: equating types encountered error {:?}", err);
|
2018-11-06 15:05:44 -05:00
|
|
|
Err(MismatchedProjectionTypes { err })
|
2018-04-26 13:31:24 -04:00
|
|
|
}
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-26 14:20:38 -05:00
|
|
|
/// Normalizes any associated type projections in `value`, replacing
|
|
|
|
/// them with a fully resolved type where possible. The return value
|
|
|
|
/// combines the normalized result and any additional obligations that
|
|
|
|
/// were incurred as result.
|
2019-06-14 01:32:15 +03:00
|
|
|
pub fn normalize<'a, 'b, 'tcx, T>(
|
|
|
|
selcx: &'a mut SelectionContext<'b, 'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
cause: ObligationCause<'tcx>,
|
|
|
|
value: &T,
|
|
|
|
) -> Normalized<'tcx, T>
|
|
|
|
where
|
|
|
|
T: TypeFoldable<'tcx>,
|
2014-12-30 17:42:02 -05:00
|
|
|
{
|
2020-01-08 22:06:25 +01:00
|
|
|
let mut obligations = Vec::new();
|
|
|
|
let value = normalize_to(selcx, param_env, cause, value, &mut obligations);
|
|
|
|
Normalized { value, obligations }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn normalize_to<'a, 'b, 'tcx, T>(
|
|
|
|
selcx: &'a mut SelectionContext<'b, 'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
cause: ObligationCause<'tcx>,
|
|
|
|
value: &T,
|
|
|
|
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
|
|
|
) -> T
|
|
|
|
where
|
|
|
|
T: TypeFoldable<'tcx>,
|
|
|
|
{
|
|
|
|
normalize_with_depth_to(selcx, param_env, cause, 0, value, obligations)
|
2015-01-01 13:15:14 -05:00
|
|
|
}
|
|
|
|
|
2015-01-26 14:20:38 -05:00
|
|
|
/// As `normalize`, but with a custom depth.
|
2019-06-14 00:48:52 +03:00
|
|
|
pub fn normalize_with_depth<'a, 'b, 'tcx, T>(
|
|
|
|
selcx: &'a mut SelectionContext<'b, 'tcx>,
|
2017-05-23 04:19:47 -04:00
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2016-04-29 06:00:23 +03:00
|
|
|
cause: ObligationCause<'tcx>,
|
|
|
|
depth: usize,
|
2019-06-14 01:32:15 +03:00
|
|
|
value: &T,
|
|
|
|
) -> Normalized<'tcx, T>
|
2020-01-08 22:06:25 +01:00
|
|
|
where
|
|
|
|
T: TypeFoldable<'tcx>,
|
|
|
|
{
|
|
|
|
let mut obligations = Vec::new();
|
|
|
|
let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations);
|
|
|
|
Normalized { value, obligations }
|
|
|
|
}
|
|
|
|
|
2020-10-11 11:37:56 +01:00
|
|
|
#[instrument(level = "debug", skip(selcx, param_env, cause, obligations))]
|
2020-01-08 22:06:25 +01:00
|
|
|
pub fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
|
|
|
|
selcx: &'a mut SelectionContext<'b, 'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
cause: ObligationCause<'tcx>,
|
|
|
|
depth: usize,
|
|
|
|
value: &T,
|
|
|
|
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
|
|
|
) -> T
|
2019-06-14 01:32:15 +03:00
|
|
|
where
|
|
|
|
T: TypeFoldable<'tcx>,
|
2015-01-01 13:15:14 -05:00
|
|
|
{
|
2020-01-08 22:06:25 +01:00
|
|
|
let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations);
|
2018-11-02 16:14:24 +01:00
|
|
|
let result = ensure_sufficient_stack(|| normalizer.fold(value));
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?result, obligations.len = normalizer.obligations.len());
|
|
|
|
debug!(?normalizer.obligations,);
|
2020-01-08 22:06:25 +01:00
|
|
|
result
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
|
2019-06-14 19:39:39 +03:00
|
|
|
struct AssocTypeNormalizer<'a, 'b, 'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
selcx: &'a mut SelectionContext<'b, 'tcx>,
|
2017-05-23 04:19:47 -04:00
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2014-12-30 17:42:02 -05:00
|
|
|
cause: ObligationCause<'tcx>,
|
2020-01-08 22:06:25 +01:00
|
|
|
obligations: &'a mut Vec<PredicateObligation<'tcx>>,
|
2015-03-25 17:06:52 -07:00
|
|
|
depth: usize,
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
|
2019-06-14 01:32:15 +03:00
|
|
|
fn new(
|
|
|
|
selcx: &'a mut SelectionContext<'b, 'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
cause: ObligationCause<'tcx>,
|
|
|
|
depth: usize,
|
2020-01-08 22:06:25 +01:00
|
|
|
obligations: &'a mut Vec<PredicateObligation<'tcx>>,
|
2019-06-14 01:32:15 +03:00
|
|
|
) -> AssocTypeNormalizer<'a, 'b, 'tcx> {
|
2020-01-08 22:06:25 +01:00
|
|
|
AssocTypeNormalizer { selcx, param_env, cause, obligations, depth }
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
fn fold<T: TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
|
2019-05-11 19:08:26 +01:00
|
|
|
let value = self.selcx.infcx().resolve_vars_if_possible(value);
|
2014-12-30 17:42:02 -05:00
|
|
|
|
move leak-check to during coherence, candidate eval
In particular, it no longer occurs during the subtyping check. This is
important for enabling lazy normalization, because the subtyping check
will be producing sub-obligations that could affect its results.
Consider an example like
for<'a> fn(<&'a as Mirror>::Item) =
fn(&'b u8)
where `<T as Mirror>::Item = T` for all `T`. We will wish to produce a
new subobligation like
<'!1 as Mirror>::Item = &'b u8
This will, after being solved, ultimately yield a constraint that `'!1
= 'b` which will fail. But with the leak-check being performed on
subtyping, there is no opportunity to normalize `<'!1 as
Mirror>::Item` (unless we invoke that normalization directly from
within subtyping, and I would prefer that subtyping and unification
are distinct operations rather than part of the trait solving stack).
The reason to keep the leak check during coherence and trait
evaluation is partly for backwards compatibility. The coherence change
permits impls for `fn(T)` and `fn(&T)` to co-exist, and the trait
evaluation change means that we can distinguish those two cases
without ambiguity errors. It also avoids recreating #57639, where we
were incorrectly choosing a where clause that would have failed the
leak check over the impl which succeeds.
The other reason to keep the leak check in those places is that I
think it is actually close to the model we want. To the point, I think
the trait solver ought to have the job of "breaking down"
higher-ranked region obligation like ``!1: '2` into into region
obligations that operate on things in the root universe, at which
point they should be handed off to polonius. The leak check isn't
*really* doing that -- these obligations are still handed to the
region solver to process -- but if/when we do adopt that model, the
decision to pass/fail would be happening in roughly this part of the
code.
This change had somewhat more side-effects than I anticipated. It
seems like there are cases where the leak-check was not being enforced
during method proving and trait selection. I haven't quite tracked
this down but I think it ought to be documented, so that we know what
precisely we are committing to.
One surprising test was `issue-30786.rs`. The behavior there seems a
bit "fishy" to me, but the problem is not related to the leak check
change as far as I can tell, but more to do with the closure signature
inference code and perhaps the associated type projection, which
together seem to be conspiring to produce an unexpected
signature. Nonetheless, it is an example of where changing the
leak-check can have some unexpected consequences: we're now failing to
resolve a method earlier than we were, which suggests we might change
some method resolutions that would have been ambiguous to be
successful.
TODO:
* figure out remainig test failures
* add new coherence tests for the patterns we ARE disallowing
2020-05-20 10:19:36 +00:00
|
|
|
if !value.has_projections() { value } else { value.fold_with(self) }
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
|
|
|
|
fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
|
2014-12-30 17:42:02 -05:00
|
|
|
self.selcx.tcx()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
2020-01-02 12:14:23 +01:00
|
|
|
if !ty.has_projections() {
|
|
|
|
return ty;
|
|
|
|
}
|
2014-12-30 17:42:02 -05:00
|
|
|
// We don't want to normalize associated types that occur inside of region
|
|
|
|
// binders, because they may contain bound regions, and we can't cope with that.
|
|
|
|
//
|
|
|
|
// Example:
|
|
|
|
//
|
|
|
|
// for<'a> fn(<T as Foo<&'a>>::A)
|
|
|
|
//
|
|
|
|
// Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
|
|
|
|
// normalize it when we instantiate those bound regions (which
|
|
|
|
// should occur eventually).
|
|
|
|
|
2016-01-06 02:01:28 +00:00
|
|
|
let ty = ty.super_fold_with(self);
|
2020-08-03 00:49:11 +02:00
|
|
|
match *ty.kind() {
|
2020-08-12 09:08:34 +02:00
|
|
|
ty::Opaque(def_id, substs) => {
|
2018-05-08 16:10:16 +03:00
|
|
|
// Only normalize `impl Trait` after type-checking, usually in codegen.
|
2020-07-02 20:52:40 -04:00
|
|
|
match self.param_env.reveal() {
|
2017-05-17 08:01:04 -04:00
|
|
|
Reveal::UserFacing => ty,
|
|
|
|
|
|
|
|
Reveal::All => {
|
2020-05-15 21:44:28 -07:00
|
|
|
let recursion_limit = self.tcx().sess.recursion_limit();
|
2020-05-26 19:48:08 +01:00
|
|
|
if !recursion_limit.value_within_limit(self.depth) {
|
2018-01-17 17:19:23 -05:00
|
|
|
let obligation = Obligation::with_depth(
|
|
|
|
self.cause.clone(),
|
2020-05-26 19:48:08 +01:00
|
|
|
recursion_limit.0,
|
2018-01-17 17:19:23 -05:00
|
|
|
self.param_env,
|
|
|
|
ty,
|
|
|
|
);
|
|
|
|
self.selcx.infcx().report_overflow_error(&obligation, true);
|
|
|
|
}
|
|
|
|
|
2017-05-17 08:01:04 -04:00
|
|
|
let generic_ty = self.tcx().type_of(def_id);
|
|
|
|
let concrete_ty = generic_ty.subst(self.tcx(), substs);
|
2018-01-17 17:19:23 -05:00
|
|
|
self.depth += 1;
|
|
|
|
let folded_ty = self.fold_ty(concrete_ty);
|
|
|
|
self.depth -= 1;
|
|
|
|
folded_ty
|
2017-05-17 08:01:04 -04:00
|
|
|
}
|
2016-07-22 18:56:22 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
|
2020-08-12 09:08:34 +02:00
|
|
|
// This is kind of hacky -- we need to be able to
|
2014-12-30 17:42:02 -05:00
|
|
|
// handle normalization within binders because
|
|
|
|
// otherwise we wind up a need to normalize when doing
|
|
|
|
// trait matching (since you can have a trait
|
2020-06-06 12:05:37 +02:00
|
|
|
// obligation like `for<'a> T::B: Fn(&'a i32)`), but
|
2014-12-30 17:42:02 -05:00
|
|
|
// we can't normalize with bound regions in scope. So
|
|
|
|
// far now we just ignore binders but only normalize
|
|
|
|
// if all bound regions are gone (and then we still
|
|
|
|
// have to renormalize whenever we instantiate a
|
|
|
|
// binder). It would be better to normalize in a
|
|
|
|
// binding-aware fashion.
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
let normalized_ty = normalize_projection_type(
|
|
|
|
self.selcx,
|
|
|
|
self.param_env,
|
2020-01-22 16:30:15 +01:00
|
|
|
*data,
|
2019-12-22 17:42:04 -05:00
|
|
|
self.cause.clone(),
|
|
|
|
self.depth,
|
|
|
|
&mut self.obligations,
|
|
|
|
);
|
|
|
|
debug!(
|
2020-10-11 11:37:56 +01:00
|
|
|
?self.depth,
|
|
|
|
?ty,
|
|
|
|
?normalized_ty,
|
|
|
|
obligations.len = ?self.obligations.len(),
|
|
|
|
"AssocTypeNormalizer: normalized type"
|
2019-12-22 17:42:04 -05:00
|
|
|
);
|
2016-05-21 05:42:27 -04:00
|
|
|
normalized_ty
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
2015-01-08 12:02:15 -05:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
_ => ty,
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
}
|
2020-01-04 18:54:19 +13:00
|
|
|
|
|
|
|
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
2020-05-17 10:36:56 +02:00
|
|
|
if self.selcx.tcx().lazy_normalization() {
|
2020-01-04 18:54:19 +13:00
|
|
|
constant
|
|
|
|
} else {
|
|
|
|
let constant = constant.super_fold_with(self);
|
|
|
|
constant.eval(self.selcx.tcx(), self.param_env)
|
|
|
|
}
|
|
|
|
}
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
|
2015-01-26 14:20:38 -05:00
|
|
|
/// The guts of `normalize`: normalize a specific projection like `<T
|
|
|
|
/// as Trait>::Item`. The result is always a type (and possibly
|
|
|
|
/// additional obligations). If ambiguity arises, which implies that
|
|
|
|
/// there are unresolved type variables in the projection, we will
|
|
|
|
/// substitute a fresh type variable `$X` and generate a new
|
|
|
|
/// obligation `<T as Trait>::Item == $X` for later.
|
2019-06-14 00:48:52 +03:00
|
|
|
pub fn normalize_projection_type<'a, 'b, 'tcx>(
|
|
|
|
selcx: &'a mut SelectionContext<'b, 'tcx>,
|
2017-05-23 04:19:47 -04:00
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2014-12-30 17:42:02 -05:00
|
|
|
projection_ty: ty::ProjectionTy<'tcx>,
|
|
|
|
cause: ObligationCause<'tcx>,
|
2018-05-17 07:58:08 +10:00
|
|
|
depth: usize,
|
2019-06-14 01:32:15 +03:00
|
|
|
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
|
|
|
) -> Ty<'tcx> {
|
2019-12-22 17:42:04 -05:00
|
|
|
opt_normalize_projection_type(
|
|
|
|
selcx,
|
|
|
|
param_env,
|
2020-01-22 16:30:15 +01:00
|
|
|
projection_ty,
|
2019-12-22 17:42:04 -05:00
|
|
|
cause.clone(),
|
|
|
|
depth,
|
|
|
|
obligations,
|
|
|
|
)
|
2020-08-13 20:45:08 +01:00
|
|
|
.ok()
|
|
|
|
.flatten()
|
2019-12-22 17:42:04 -05:00
|
|
|
.unwrap_or_else(move || {
|
|
|
|
// if we bottom out in ambiguity, create a type variable
|
|
|
|
// and a deferred predicate to resolve this when more type
|
|
|
|
// information is available.
|
|
|
|
|
|
|
|
let tcx = selcx.infcx().tcx;
|
|
|
|
let def_id = projection_ty.item_def_id;
|
|
|
|
let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin {
|
|
|
|
kind: TypeVariableOriginKind::NormalizeProjectionType,
|
|
|
|
span: tcx.def_span(def_id),
|
|
|
|
});
|
|
|
|
let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
|
|
|
|
let obligation =
|
2020-05-07 10:12:19 +00:00
|
|
|
Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate(tcx));
|
2019-12-22 17:42:04 -05:00
|
|
|
obligations.push(obligation);
|
|
|
|
ty_var
|
|
|
|
})
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
|
2015-01-26 14:20:38 -05:00
|
|
|
/// The guts of `normalize`: normalize a specific projection like `<T
|
|
|
|
/// as Trait>::Item`. The result is always a type (and possibly
|
|
|
|
/// additional obligations). Returns `None` in the case of ambiguity,
|
|
|
|
/// which indicates that there are unbound type variables.
|
2018-05-17 07:58:08 +10:00
|
|
|
///
|
|
|
|
/// This function used to return `Option<NormalizedTy<'tcx>>`, which contains a
|
|
|
|
/// `Ty<'tcx>` and an obligations vector. But that obligation vector was very
|
|
|
|
/// often immediately appended to another obligations vector. So now this
|
|
|
|
/// function takes an obligations vector and appends to it directly, which is
|
|
|
|
/// slightly uglier but avoids the need for an extra short-lived allocation.
|
2020-10-11 11:37:56 +01:00
|
|
|
#[instrument(level = "debug", skip(selcx, param_env, cause, obligations))]
|
2019-06-14 00:48:52 +03:00
|
|
|
fn opt_normalize_projection_type<'a, 'b, 'tcx>(
|
|
|
|
selcx: &'a mut SelectionContext<'b, 'tcx>,
|
2017-05-23 04:19:47 -04:00
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2014-12-30 17:42:02 -05:00
|
|
|
projection_ty: ty::ProjectionTy<'tcx>,
|
|
|
|
cause: ObligationCause<'tcx>,
|
2018-05-17 07:58:08 +10:00
|
|
|
depth: usize,
|
2019-06-14 01:32:15 +03:00
|
|
|
obligations: &mut Vec<PredicateObligation<'tcx>>,
|
2020-08-13 20:45:08 +01:00
|
|
|
) -> Result<Option<Ty<'tcx>>, InProgress> {
|
2016-04-20 19:51:56 -04:00
|
|
|
let infcx = selcx.infcx();
|
|
|
|
|
2019-05-11 19:08:26 +01:00
|
|
|
let projection_ty = infcx.resolve_vars_if_possible(&projection_ty);
|
2020-02-22 11:44:18 +01:00
|
|
|
let cache_key = ProjectionCacheKey::new(projection_ty);
|
2016-04-20 19:51:56 -04:00
|
|
|
|
2016-05-21 08:30:52 -04:00
|
|
|
// FIXME(#20304) For now, I am caching here, which is good, but it
|
|
|
|
// means we don't capture the type variables that are created in
|
|
|
|
// the case of ambiguity. Which means we may create a large stream
|
|
|
|
// of such variables. OTOH, if we move the caching up a level, we
|
|
|
|
// would not benefit from caching when proving `T: Trait<U=Foo>`
|
|
|
|
// bounds. It might be the case that we want two distinct caches,
|
|
|
|
// or else another kind of cache entry.
|
|
|
|
|
2020-03-16 16:43:03 +01:00
|
|
|
let cache_result = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
|
2017-09-02 08:35:07 -04:00
|
|
|
match cache_result {
|
2019-12-22 17:42:04 -05:00
|
|
|
Ok(()) => {}
|
2016-05-21 08:30:52 -04:00
|
|
|
Err(ProjectionCacheEntry::Ambiguous) => {
|
2020-02-22 14:10:17 +00:00
|
|
|
// If we found ambiguity the last time, that means we will continue
|
|
|
|
// to do so until some type in the key changes (and we know it
|
|
|
|
// hasn't, because we just fully resolved it).
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!("found cache entry: ambiguous");
|
2020-08-13 20:45:08 +01:00
|
|
|
return Ok(None);
|
2016-05-21 08:30:52 -04:00
|
|
|
}
|
|
|
|
Err(ProjectionCacheEntry::InProgress) => {
|
|
|
|
// If while normalized A::B, we are asked to normalize
|
|
|
|
// A::B, just return A::B itself. This is a conservative
|
|
|
|
// answer, in the sense that A::B *is* clearly equivalent
|
|
|
|
// to A::B, though there may be a better value we can
|
|
|
|
// find.
|
|
|
|
|
|
|
|
// Under lazy normalization, this can arise when
|
|
|
|
// bootstrapping. That is, imagine an environment with a
|
|
|
|
// where-clause like `A::B == u32`. Now, if we are asked
|
|
|
|
// to normalize `A::B`, we will want to check the
|
|
|
|
// where-clauses in scope. So we will try to unify `A::B`
|
|
|
|
// with `A::B`, which can trigger a recursive
|
2020-08-13 20:45:08 +01:00
|
|
|
// normalization.
|
2016-05-21 08:30:52 -04:00
|
|
|
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!("found cache entry: in-progress");
|
2016-05-21 08:30:52 -04:00
|
|
|
|
2020-08-13 20:45:08 +01:00
|
|
|
return Err(InProgress);
|
2016-05-21 08:30:52 -04:00
|
|
|
}
|
2018-05-17 07:58:08 +10:00
|
|
|
Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
|
|
|
|
// This is the hottest path in this function.
|
|
|
|
//
|
2017-07-29 21:40:37 +03:00
|
|
|
// If we find the value in the cache, then return it along
|
|
|
|
// with the obligations that went along with it. Note
|
|
|
|
// that, when using a fulfillment context, these
|
|
|
|
// obligations could in principle be ignored: they have
|
|
|
|
// already been registered when the cache entry was
|
|
|
|
// created (and hence the new ones will quickly be
|
|
|
|
// discarded as duplicated). But when doing trait
|
|
|
|
// evaluation this is not the case, and dropping the trait
|
2018-11-27 02:59:49 +00:00
|
|
|
// evaluations can causes ICEs (e.g., #43132).
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?ty, "found normalized ty");
|
2017-09-02 08:35:07 -04:00
|
|
|
|
|
|
|
// Once we have inferred everything we need to know, we
|
|
|
|
// can ignore the `obligations` from that point on.
|
2019-03-11 18:46:20 +00:00
|
|
|
if infcx.unresolved_type_vars(&ty.value).is_none() {
|
2020-03-16 16:43:03 +01:00
|
|
|
infcx.inner.borrow_mut().projection_cache().complete_normalized(cache_key, &ty);
|
2019-12-22 17:42:04 -05:00
|
|
|
// No need to extend `obligations`.
|
2018-05-17 07:58:08 +10:00
|
|
|
} else {
|
|
|
|
obligations.extend(ty.obligations);
|
2017-09-02 08:35:07 -04:00
|
|
|
}
|
2020-08-13 20:45:08 +01:00
|
|
|
return Ok(Some(ty.value));
|
2016-05-21 08:30:52 -04:00
|
|
|
}
|
|
|
|
Err(ProjectionCacheEntry::Error) => {
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!("opt_normalize_projection_type: found error");
|
2018-05-17 07:58:08 +10:00
|
|
|
let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
|
|
|
|
obligations.extend(result.obligations);
|
2020-08-13 20:45:08 +01:00
|
|
|
return Ok(Some(result.value));
|
2016-05-21 08:30:52 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-23 04:19:47 -04:00
|
|
|
let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty);
|
2014-12-30 17:42:02 -05:00
|
|
|
match project_type(selcx, &obligation) {
|
2019-12-22 17:42:04 -05:00
|
|
|
Ok(ProjectedTy::Progress(Progress {
|
|
|
|
ty: projected_ty,
|
|
|
|
obligations: mut projected_obligations,
|
|
|
|
})) => {
|
2014-12-30 17:42:02 -05:00
|
|
|
// if projection succeeded, then what we get out of this
|
|
|
|
// is also non-normalized (consider: it was derived from
|
|
|
|
// an impl, where-clause etc) and hence we must
|
|
|
|
// re-normalize it
|
|
|
|
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?projected_ty, ?depth, ?projected_obligations);
|
2014-12-30 17:42:02 -05:00
|
|
|
|
2017-08-07 08:08:53 +03:00
|
|
|
let result = if projected_ty.has_projections() {
|
2020-01-08 22:06:25 +01:00
|
|
|
let mut normalizer = AssocTypeNormalizer::new(
|
|
|
|
selcx,
|
|
|
|
param_env,
|
|
|
|
cause,
|
|
|
|
depth + 1,
|
|
|
|
&mut projected_obligations,
|
|
|
|
);
|
2014-12-30 17:42:02 -05:00
|
|
|
let normalized_ty = normalizer.fold(&projected_ty);
|
|
|
|
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?normalized_ty, ?depth);
|
2014-12-30 17:42:02 -05:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
Normalized { value: normalized_ty, obligations: projected_obligations }
|
2014-12-30 17:42:02 -05:00
|
|
|
} else {
|
2019-12-22 17:42:04 -05:00
|
|
|
Normalized { value: projected_ty, obligations: projected_obligations }
|
2016-05-21 08:29:50 -04:00
|
|
|
};
|
2017-09-02 08:35:07 -04:00
|
|
|
|
|
|
|
let cache_value = prune_cache_value_obligations(infcx, &result);
|
2020-03-16 16:43:03 +01:00
|
|
|
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, cache_value);
|
2018-05-17 07:58:08 +10:00
|
|
|
obligations.extend(result.obligations);
|
2020-08-13 20:45:08 +01:00
|
|
|
Ok(Some(result.value))
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
Ok(ProjectedTy::NoProgress(projected_ty)) => {
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?projected_ty, "opt_normalize_projection_type: no progress");
|
2019-12-22 17:42:04 -05:00
|
|
|
let result = Normalized { value: projected_ty, obligations: vec![] };
|
2020-03-16 16:43:03 +01:00
|
|
|
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
|
2018-05-17 07:58:08 +10:00
|
|
|
// No need to extend `obligations`.
|
2020-08-13 20:45:08 +01:00
|
|
|
Ok(Some(result.value))
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
Err(ProjectionTyError::TooManyCandidates) => {
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!("opt_normalize_projection_type: too many candidates");
|
2020-03-16 16:43:03 +01:00
|
|
|
infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
|
2020-08-13 20:45:08 +01:00
|
|
|
Ok(None)
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
Err(ProjectionTyError::TraitSelectionError(_)) => {
|
2016-04-20 19:51:56 -04:00
|
|
|
debug!("opt_normalize_projection_type: ERROR");
|
2014-12-30 17:42:02 -05:00
|
|
|
// if we got an error processing the `T as Trait` part,
|
|
|
|
// just return `ty::err` but add the obligation `T :
|
|
|
|
// Trait`, which when processed will cause the error to be
|
|
|
|
// reported later
|
|
|
|
|
2020-03-16 16:43:03 +01:00
|
|
|
infcx.inner.borrow_mut().projection_cache().error(cache_key);
|
2018-05-17 07:58:08 +10:00
|
|
|
let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
|
|
|
|
obligations.extend(result.obligations);
|
2020-08-13 20:45:08 +01:00
|
|
|
Ok(Some(result.value))
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-02 08:35:07 -04:00
|
|
|
/// If there are unresolved type variables, then we need to include
|
|
|
|
/// any subobligations that bind them, at least until those type
|
|
|
|
/// variables are fully resolved.
|
2019-06-14 01:32:15 +03:00
|
|
|
fn prune_cache_value_obligations<'a, 'tcx>(
|
|
|
|
infcx: &'a InferCtxt<'a, 'tcx>,
|
|
|
|
result: &NormalizedTy<'tcx>,
|
|
|
|
) -> NormalizedTy<'tcx> {
|
2019-03-11 18:46:20 +00:00
|
|
|
if infcx.unresolved_type_vars(&result.value).is_none() {
|
2017-09-02 08:35:07 -04:00
|
|
|
return NormalizedTy { value: result.value, obligations: vec![] };
|
|
|
|
}
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
let mut obligations: Vec<_> = result
|
|
|
|
.obligations
|
|
|
|
.iter()
|
2020-06-18 20:41:43 +02:00
|
|
|
.filter(|obligation| {
|
2020-10-07 20:02:06 -04:00
|
|
|
let bound_predicate = obligation.predicate.bound_atom(infcx.tcx);
|
|
|
|
match bound_predicate.skip_binder() {
|
2020-06-18 20:41:43 +02:00
|
|
|
// We found a `T: Foo<X = U>` predicate, let's check
|
|
|
|
// if `U` references any unresolved type
|
|
|
|
// variables. In principle, we only care if this
|
|
|
|
// projection can help resolve any of the type
|
|
|
|
// variables found in `result.value` -- but we just
|
|
|
|
// check for any type variables here, for fear of
|
|
|
|
// indirect obligations (e.g., we project to `?0`,
|
|
|
|
// but we have `T: Foo<X = ?1>` and `?1: Bar<X =
|
|
|
|
// ?0>`).
|
2020-10-07 20:02:06 -04:00
|
|
|
ty::PredicateAtom::Projection(data) => infcx
|
|
|
|
.unresolved_type_vars(&bound_predicate.map_bound_ref(|_| data.ty))
|
|
|
|
.is_some(),
|
2019-12-22 17:42:04 -05:00
|
|
|
|
2020-06-18 20:41:43 +02:00
|
|
|
// We are only interested in `T: Foo<X = U>` predicates, whre
|
|
|
|
// `U` references one of `unresolved_type_vars`. =)
|
|
|
|
_ => false,
|
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
|
|
|
.cloned()
|
|
|
|
.collect();
|
2017-09-02 08:35:07 -04:00
|
|
|
|
|
|
|
obligations.shrink_to_fit();
|
|
|
|
|
|
|
|
NormalizedTy { value: result.value, obligations }
|
|
|
|
}
|
|
|
|
|
2016-01-07 13:51:16 -05:00
|
|
|
/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
|
|
|
|
/// hold. In various error cases, we cannot generate a valid
|
|
|
|
/// normalized projection. Therefore, we create an inference variable
|
|
|
|
/// return an associated obligation that, when fulfilled, will lead to
|
|
|
|
/// an error.
|
2015-05-05 22:09:17 +03:00
|
|
|
///
|
2018-08-22 01:35:02 +01:00
|
|
|
/// Note that we used to return `Error` here, but that was quite
|
2016-01-07 13:51:16 -05:00
|
|
|
/// dubious -- the premise was that an error would *eventually* be
|
|
|
|
/// reported, when the obligation was processed. But in general once
|
2018-08-22 01:35:02 +01:00
|
|
|
/// you see a `Error` you are supposed to be able to assume that an
|
2016-01-07 13:51:16 -05:00
|
|
|
/// error *has been* reported, so that you can take whatever heuristic
|
|
|
|
/// paths you want to take. To make things worse, it was possible for
|
|
|
|
/// cycles to arise, where you basically had a setup like `<MyType<$0>
|
|
|
|
/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
|
|
|
|
/// Trait>::Foo> to `[type error]` would lead to an obligation of
|
2019-02-08 14:53:55 +01:00
|
|
|
/// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
|
2016-01-07 13:51:16 -05:00
|
|
|
/// an error for this obligation, but we legitimately should not,
|
|
|
|
/// because it contains `[type error]`. Yuck! (See issue #29857 for
|
|
|
|
/// one case where this arose.)
|
2019-06-14 01:32:15 +03:00
|
|
|
fn normalize_to_error<'a, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'a, 'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
projection_ty: ty::ProjectionTy<'tcx>,
|
|
|
|
cause: ObligationCause<'tcx>,
|
|
|
|
depth: usize,
|
|
|
|
) -> NormalizedTy<'tcx> {
|
2017-07-11 10:33:09 -04:00
|
|
|
let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref();
|
2019-12-22 17:42:04 -05:00
|
|
|
let trait_obligation = Obligation {
|
|
|
|
cause,
|
|
|
|
recursion_depth: depth,
|
|
|
|
param_env,
|
2020-05-07 10:12:19 +00:00
|
|
|
predicate: trait_ref.without_const().to_predicate(selcx.tcx()),
|
2019-12-22 17:42:04 -05:00
|
|
|
};
|
2016-11-28 10:08:08 -08:00
|
|
|
let tcx = selcx.infcx().tcx;
|
2017-07-11 10:33:09 -04:00
|
|
|
let def_id = projection_ty.item_def_id;
|
2019-12-22 17:42:04 -05:00
|
|
|
let new_value = selcx.infcx().next_ty_var(TypeVariableOrigin {
|
|
|
|
kind: TypeVariableOriginKind::NormalizeProjectionType,
|
|
|
|
span: tcx.def_span(def_id),
|
|
|
|
});
|
|
|
|
Normalized { value: new_value, obligations: vec![trait_obligation] }
|
2014-12-17 14:16:28 -05:00
|
|
|
}
|
|
|
|
|
2014-12-30 17:42:02 -05:00
|
|
|
enum ProjectedTy<'tcx> {
|
2016-05-21 08:29:50 -04:00
|
|
|
Progress(Progress<'tcx>),
|
2014-12-30 17:42:02 -05:00
|
|
|
NoProgress(Ty<'tcx>),
|
|
|
|
}
|
|
|
|
|
2016-05-21 08:29:50 -04:00
|
|
|
struct Progress<'tcx> {
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
obligations: Vec<PredicateObligation<'tcx>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> Progress<'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
fn error(tcx: TyCtxt<'tcx>) -> Self {
|
2020-05-05 23:02:09 -05:00
|
|
|
Progress { ty: tcx.ty_error(), obligations: vec![] }
|
2016-05-21 08:29:50 -04:00
|
|
|
}
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self {
|
|
|
|
debug!(
|
2020-10-11 11:37:56 +01:00
|
|
|
self.obligations.len = ?self.obligations.len(),
|
|
|
|
obligations.len = obligations.len(),
|
|
|
|
"with_addl_obligations"
|
2019-12-22 17:42:04 -05:00
|
|
|
);
|
2016-05-23 19:52:44 -04:00
|
|
|
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?self.obligations, ?obligations, "with_addl_obligations");
|
2016-05-23 19:52:44 -04:00
|
|
|
|
2016-05-21 08:29:50 -04:00
|
|
|
self.obligations.append(&mut obligations);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Computes the result of a projection type (if we can).
|
2016-05-21 08:29:50 -04:00
|
|
|
///
|
|
|
|
/// IMPORTANT:
|
|
|
|
/// - `obligation` must be fully normalized
|
2019-06-14 00:48:52 +03:00
|
|
|
fn project_type<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2019-06-14 01:32:15 +03:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
|
|
|
) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?obligation, "project_type");
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2020-05-26 19:48:08 +01:00
|
|
|
if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
|
2014-12-30 17:42:02 -05:00
|
|
|
debug!("project: overflow!");
|
2018-11-06 13:01:44 +01:00
|
|
|
return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
|
2014-12-30 17:42:02 -05:00
|
|
|
}
|
|
|
|
|
2017-07-11 10:33:09 -04:00
|
|
|
let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
|
2015-01-02 04:20:34 -05:00
|
|
|
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?obligation_trait_ref);
|
2015-01-02 04:20:34 -05:00
|
|
|
|
|
|
|
if obligation_trait_ref.references_error() {
|
2016-05-21 08:29:50 -04:00
|
|
|
return Ok(ProjectedTy::Progress(Progress::error(selcx.tcx())));
|
2015-01-02 04:20:34 -05:00
|
|
|
}
|
|
|
|
|
2018-02-18 12:32:23 +09:00
|
|
|
let mut candidates = ProjectionTyCandidateSet::None;
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2018-02-18 12:32:23 +09:00
|
|
|
// Make sure that the following procedures are kept in order. ParamEnv
|
|
|
|
// needs to be first because it has highest priority, and Select checks
|
|
|
|
// the return value of push_candidate which assumes it's ran at last.
|
2019-12-22 17:42:04 -05:00
|
|
|
assemble_candidates_from_param_env(selcx, obligation, &obligation_trait_ref, &mut candidates);
|
2014-12-23 05:26:34 -05:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
assemble_candidates_from_trait_def(selcx, obligation, &obligation_trait_ref, &mut candidates);
|
2015-01-27 14:52:54 -05:00
|
|
|
|
2020-07-24 21:59:43 +01:00
|
|
|
assemble_candidates_from_object_ty(selcx, obligation, &obligation_trait_ref, &mut candidates);
|
|
|
|
|
|
|
|
if let ProjectionTyCandidateSet::Single(ProjectionTyCandidate::Object(_)) = candidates {
|
|
|
|
// Avoid normalization cycle from selection (see
|
|
|
|
// `assemble_candidates_from_object_ty`).
|
|
|
|
// FIXME(lazy_normalization): Lazy normalization should save us from
|
|
|
|
// having to do special case this.
|
|
|
|
} else {
|
|
|
|
assemble_candidates_from_impls(selcx, obligation, &obligation_trait_ref, &mut candidates);
|
|
|
|
};
|
2018-02-18 12:32:23 +09:00
|
|
|
|
|
|
|
match candidates {
|
2020-07-24 21:59:43 +01:00
|
|
|
ProjectionTyCandidateSet::Single(candidate) => {
|
|
|
|
Ok(ProjectedTy::Progress(confirm_candidate(selcx, obligation, candidate)))
|
|
|
|
}
|
2018-02-18 12:32:23 +09:00
|
|
|
ProjectionTyCandidateSet::None => Ok(ProjectedTy::NoProgress(
|
2019-12-22 17:42:04 -05:00
|
|
|
selcx
|
|
|
|
.tcx()
|
|
|
|
.mk_projection(obligation.predicate.item_def_id, obligation.predicate.substs),
|
|
|
|
)),
|
2018-02-18 12:32:23 +09:00
|
|
|
// Error occurred while trying to processing impls.
|
|
|
|
ProjectionTyCandidateSet::Error(e) => Err(ProjectionTyError::TraitSelectionError(e)),
|
|
|
|
// Inherent ambiguity that prevents us from even enumerating the
|
|
|
|
// candidates.
|
|
|
|
ProjectionTyCandidateSet::Ambiguous => Err(ProjectionTyError::TooManyCandidates),
|
2014-12-17 14:16:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The first thing we have to do is scan through the parameter
|
|
|
|
/// environment to see whether there are any projection predicates
|
|
|
|
/// there that can answer this question.
|
2019-06-14 00:48:52 +03:00
|
|
|
fn assemble_candidates_from_param_env<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2015-01-02 04:20:34 -05:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2015-04-21 18:59:58 +03:00
|
|
|
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
2019-06-14 01:32:15 +03:00
|
|
|
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
|
|
|
) {
|
2015-10-22 12:28:47 -04:00
|
|
|
debug!("assemble_candidates_from_param_env(..)");
|
2019-12-22 17:42:04 -05:00
|
|
|
assemble_candidates_from_predicates(
|
|
|
|
selcx,
|
|
|
|
obligation,
|
|
|
|
obligation_trait_ref,
|
|
|
|
candidate_set,
|
|
|
|
ProjectionTyCandidate::ParamEnv,
|
2020-07-02 20:52:40 -04:00
|
|
|
obligation.param_env.caller_bounds().iter(),
|
2020-07-24 19:10:22 +01:00
|
|
|
false,
|
2019-12-22 17:42:04 -05:00
|
|
|
);
|
2014-12-26 07:07:55 -05:00
|
|
|
}
|
|
|
|
|
2015-01-27 14:52:54 -05:00
|
|
|
/// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
|
|
|
|
/// that the definition of `Foo` has some clues:
|
|
|
|
///
|
2015-03-12 22:42:38 -04:00
|
|
|
/// ```
|
2015-01-27 14:52:54 -05:00
|
|
|
/// trait Foo {
|
|
|
|
/// type FooT : Bar<BarT=i32>
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Here, for example, we could conclude that the result is `i32`.
|
2019-06-14 00:48:52 +03:00
|
|
|
fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2015-01-27 14:52:54 -05:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2015-04-21 18:59:58 +03:00
|
|
|
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
2019-06-14 01:32:15 +03:00
|
|
|
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
|
|
|
) {
|
2015-10-22 12:28:47 -04:00
|
|
|
debug!("assemble_candidates_from_trait_def(..)");
|
|
|
|
|
2017-07-11 10:33:09 -04:00
|
|
|
let tcx = selcx.tcx();
|
2015-01-27 14:52:54 -05:00
|
|
|
// Check whether the self-type is itself a projection.
|
2020-05-30 17:19:31 +01:00
|
|
|
// If so, extract what we know from the trait and try to come up with a good answer.
|
2020-08-03 00:49:11 +02:00
|
|
|
let bounds = match *obligation_trait_ref.self_ty().kind() {
|
2020-06-23 17:57:24 +01:00
|
|
|
ty::Projection(ref data) => tcx.item_bounds(data.item_def_id).subst(tcx, data.substs),
|
|
|
|
ty::Opaque(def_id, substs) => tcx.item_bounds(def_id).subst(tcx, substs),
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Infer(ty::TyVar(_)) => {
|
2015-01-27 14:52:54 -05:00
|
|
|
// If the self-type is an inference variable, then it MAY wind up
|
|
|
|
// being a projected type, so induce an ambiguity.
|
2018-02-18 12:32:23 +09:00
|
|
|
candidate_set.mark_ambiguous();
|
2015-01-27 14:52:54 -05:00
|
|
|
return;
|
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
_ => return,
|
2015-01-27 14:52:54 -05:00
|
|
|
};
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
assemble_candidates_from_predicates(
|
|
|
|
selcx,
|
|
|
|
obligation,
|
|
|
|
obligation_trait_ref,
|
|
|
|
candidate_set,
|
|
|
|
ProjectionTyCandidate::TraitDef,
|
2020-05-30 17:19:31 +01:00
|
|
|
bounds.iter(),
|
2020-07-24 19:10:22 +01:00
|
|
|
true,
|
2019-12-22 17:42:04 -05:00
|
|
|
)
|
2015-01-27 14:52:54 -05:00
|
|
|
}
|
|
|
|
|
2020-07-24 21:59:43 +01:00
|
|
|
/// In the case of a trait object like
|
|
|
|
/// `<dyn Iterator<Item = ()> as Iterator>::Item` we can use the existential
|
|
|
|
/// predicate in the trait object.
|
|
|
|
///
|
|
|
|
/// We don't go through the select candidate for these bounds to avoid cycles:
|
|
|
|
/// In the above case, `dyn Iterator<Item = ()>: Iterator` would create a
|
|
|
|
/// nested obligation of `<dyn Iterator<Item = ()> as Iterator>::Item: Sized`,
|
|
|
|
/// this then has to be normalized without having to prove
|
|
|
|
/// `dyn Iterator<Item = ()>: Iterator` again.
|
|
|
|
fn assemble_candidates_from_object_ty<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
|
|
|
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
|
|
|
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
|
|
|
) {
|
|
|
|
debug!("assemble_candidates_from_object_ty(..)");
|
|
|
|
|
|
|
|
let tcx = selcx.tcx();
|
|
|
|
|
|
|
|
let self_ty = obligation_trait_ref.self_ty();
|
|
|
|
let object_ty = selcx.infcx().shallow_resolve(self_ty);
|
2020-09-06 20:04:52 +01:00
|
|
|
let data = match object_ty.kind() {
|
|
|
|
ty::Dynamic(data, ..) => data,
|
2020-07-24 21:59:43 +01:00
|
|
|
ty::Infer(ty::TyVar(_)) => {
|
|
|
|
// If the self-type is an inference variable, then it MAY wind up
|
|
|
|
// being an object type, so induce an ambiguity.
|
|
|
|
candidate_set.mark_ambiguous();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_ => return,
|
|
|
|
};
|
|
|
|
let env_predicates = data
|
|
|
|
.projection_bounds()
|
|
|
|
.filter(|bound| bound.item_def_id() == obligation.predicate.item_def_id)
|
|
|
|
.map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
|
|
|
|
|
|
|
|
assemble_candidates_from_predicates(
|
|
|
|
selcx,
|
|
|
|
obligation,
|
|
|
|
obligation_trait_ref,
|
|
|
|
candidate_set,
|
|
|
|
ProjectionTyCandidate::Object,
|
|
|
|
env_predicates,
|
|
|
|
false,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-04-17 18:31:25 -07:00
|
|
|
fn assemble_candidates_from_predicates<'cx, 'tcx>(
|
2019-06-14 00:48:52 +03:00
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2015-01-02 04:20:34 -05:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2015-04-21 18:59:58 +03:00
|
|
|
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
2014-12-26 07:07:55 -05:00
|
|
|
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
2015-10-22 12:28:47 -04:00
|
|
|
ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
|
2020-04-17 18:31:25 -07:00
|
|
|
env_predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
|
2020-07-24 19:10:22 +01:00
|
|
|
potentially_unnormalized_candidates: bool,
|
2020-04-17 18:31:25 -07:00
|
|
|
) {
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?obligation, "assemble_candidates_from_predicates");
|
|
|
|
|
2014-12-26 07:07:55 -05:00
|
|
|
let infcx = selcx.infcx();
|
2015-05-11 17:02:56 -04:00
|
|
|
for predicate in env_predicates {
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?predicate);
|
2020-10-07 20:02:06 -04:00
|
|
|
let bound_predicate = predicate.bound_atom(infcx.tcx);
|
2020-07-09 00:35:55 +02:00
|
|
|
if let ty::PredicateAtom::Projection(data) = predicate.skip_binders() {
|
2020-10-07 20:02:06 -04:00
|
|
|
let data = bound_predicate.map_bound_ref(|_| data);
|
2018-09-12 16:57:19 +02:00
|
|
|
let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
let is_match = same_def_id
|
|
|
|
&& infcx.probe(|_| {
|
2020-07-24 19:10:22 +01:00
|
|
|
selcx.match_projection_projections(
|
|
|
|
obligation,
|
|
|
|
obligation_trait_ref,
|
|
|
|
&data,
|
|
|
|
potentially_unnormalized_candidates,
|
|
|
|
)
|
2019-12-22 17:42:04 -05:00
|
|
|
});
|
|
|
|
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?data, ?is_match, ?same_def_id);
|
2018-09-12 16:57:19 +02:00
|
|
|
|
|
|
|
if is_match {
|
|
|
|
candidate_set.push_candidate(ctor(data));
|
2020-07-25 14:00:13 +01:00
|
|
|
|
2020-07-25 15:14:12 +01:00
|
|
|
if potentially_unnormalized_candidates
|
|
|
|
&& !obligation.predicate.has_infer_types_or_consts()
|
|
|
|
{
|
2020-07-25 14:00:13 +01:00
|
|
|
// HACK: Pick the first trait def candidate for a fully
|
|
|
|
// inferred predicate. This is to allow duplicates that
|
|
|
|
// differ only in normalization.
|
|
|
|
return;
|
|
|
|
}
|
2014-12-17 14:16:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn assemble_candidates_from_impls<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2014-12-30 17:42:02 -05:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2015-04-21 18:59:58 +03:00
|
|
|
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
2019-06-14 01:32:15 +03:00
|
|
|
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
|
|
|
) {
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!("assemble_candidates_from_impls");
|
|
|
|
|
2014-12-17 14:16:28 -05:00
|
|
|
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
|
|
|
|
// start out by selecting the predicate `T as TraitRef<...>`:
|
2015-01-02 04:20:34 -05:00
|
|
|
let poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
|
|
|
|
let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
|
2018-02-18 12:32:23 +09:00
|
|
|
let _ = selcx.infcx().commit_if_ok(|_| {
|
2020-05-11 15:25:33 +00:00
|
|
|
let impl_source = match selcx.select(&trait_obligation) {
|
|
|
|
Ok(Some(impl_source)) => impl_source,
|
2016-03-15 06:10:01 -04:00
|
|
|
Ok(None) => {
|
2018-02-18 12:32:23 +09:00
|
|
|
candidate_set.mark_ambiguous();
|
|
|
|
return Err(());
|
2016-03-15 06:10:01 -04:00
|
|
|
}
|
|
|
|
Err(e) => {
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(error = ?e, "selection error");
|
2018-02-18 12:32:23 +09:00
|
|
|
candidate_set.mark_error(e);
|
|
|
|
return Err(());
|
2016-03-15 06:10:01 -04:00
|
|
|
}
|
|
|
|
};
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2020-05-11 15:25:33 +00:00
|
|
|
let eligible = match &impl_source {
|
2020-09-24 19:22:36 +02:00
|
|
|
super::ImplSource::Closure(_)
|
|
|
|
| super::ImplSource::Generator(_)
|
|
|
|
| super::ImplSource::FnPointer(_)
|
|
|
|
| super::ImplSource::TraitAlias(_) => {
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?impl_source);
|
2018-02-18 12:32:23 +09:00
|
|
|
true
|
2016-03-15 06:10:01 -04:00
|
|
|
}
|
2020-09-24 19:22:36 +02:00
|
|
|
super::ImplSource::UserDefined(impl_data) => {
|
2016-03-15 06:10:01 -04:00
|
|
|
// We have to be careful when projecting out of an
|
|
|
|
// impl because of specialization. If we are not in
|
2018-05-08 16:10:16 +03:00
|
|
|
// codegen (i.e., projection mode is not "any"), and the
|
2016-03-15 06:10:01 -04:00
|
|
|
// impl's type is declared as default, then we disable
|
|
|
|
// projection (even if the trait ref is fully
|
|
|
|
// monomorphic). In the case where trait ref is not
|
|
|
|
// fully monomorphic (i.e., includes type parameters),
|
|
|
|
// this is because those type parameters may
|
|
|
|
// ultimately be bound to types from other crates that
|
|
|
|
// may have specialized impls we can't see. In the
|
|
|
|
// case where the trait ref IS fully monomorphic, this
|
|
|
|
// is a policy decision that we made in the RFC in
|
|
|
|
// order to preserve flexibility for the crate that
|
|
|
|
// defined the specializable impl to specialize later
|
|
|
|
// for existing types.
|
|
|
|
//
|
|
|
|
// In either case, we handle this by not adding a
|
|
|
|
// candidate for an impl if it contains a `default`
|
|
|
|
// type.
|
2019-12-27 11:44:36 -05:00
|
|
|
//
|
|
|
|
// NOTE: This should be kept in sync with the similar code in
|
2020-04-03 19:03:13 +09:00
|
|
|
// `rustc_ty::instance::resolve_associated_item()`.
|
2019-12-22 17:42:04 -05:00
|
|
|
let node_item =
|
2020-02-08 20:10:06 +00:00
|
|
|
assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id)
|
|
|
|
.map_err(|ErrorReported| ())?;
|
2017-05-16 17:31:18 +02:00
|
|
|
|
2020-03-29 00:57:49 +01:00
|
|
|
if node_item.is_final() {
|
2020-03-29 16:40:30 +02:00
|
|
|
// Non-specializable items are always projectable.
|
2020-03-29 00:57:49 +01:00
|
|
|
true
|
|
|
|
} else {
|
2019-06-13 21:36:15 +02:00
|
|
|
// Only reveal a specializable default if we're past type-checking
|
|
|
|
// and the obligation is monomorphic, otherwise passes such as
|
|
|
|
// transmute checking and polymorphic MIR optimizations could
|
|
|
|
// get a result which isn't correct for all monomorphizations.
|
2020-07-02 20:52:40 -04:00
|
|
|
if obligation.param_env.reveal() == Reveal::All {
|
2019-06-13 21:36:15 +02:00
|
|
|
// NOTE(eddyb) inference variables can resolve to parameters, so
|
|
|
|
// assume `poly_trait_ref` isn't monomorphic, if it contains any.
|
|
|
|
let poly_trait_ref =
|
|
|
|
selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
|
2020-04-01 16:20:27 +01:00
|
|
|
!poly_trait_ref.still_further_specializable()
|
2020-03-29 00:57:49 +01:00
|
|
|
} else {
|
2019-06-13 21:36:15 +02:00
|
|
|
debug!(
|
2020-10-11 11:37:56 +01:00
|
|
|
assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id),
|
|
|
|
?obligation.predicate,
|
|
|
|
"assemble_candidates_from_impls: not eligible due to default",
|
2019-06-13 21:36:15 +02:00
|
|
|
);
|
|
|
|
false
|
|
|
|
}
|
2018-02-18 12:32:23 +09:00
|
|
|
}
|
2016-03-15 06:10:01 -04:00
|
|
|
}
|
2020-09-24 19:22:36 +02:00
|
|
|
super::ImplSource::DiscriminantKind(..) => {
|
2020-04-05 19:57:32 +02:00
|
|
|
// While `DiscriminantKind` is automatically implemented for every type,
|
|
|
|
// the concrete discriminant may not be known yet.
|
|
|
|
//
|
|
|
|
// Any type with multiple potential discriminant types is therefore not eligible.
|
|
|
|
let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
|
|
|
|
|
2020-08-03 00:49:11 +02:00
|
|
|
match self_ty.kind() {
|
2020-04-05 19:57:32 +02:00
|
|
|
ty::Bool
|
|
|
|
| ty::Char
|
|
|
|
| ty::Int(_)
|
|
|
|
| ty::Uint(_)
|
|
|
|
| ty::Float(_)
|
|
|
|
| ty::Adt(..)
|
|
|
|
| ty::Foreign(_)
|
|
|
|
| ty::Str
|
|
|
|
| ty::Array(..)
|
|
|
|
| ty::Slice(_)
|
|
|
|
| ty::RawPtr(..)
|
|
|
|
| ty::Ref(..)
|
|
|
|
| ty::FnDef(..)
|
|
|
|
| ty::FnPtr(..)
|
|
|
|
| ty::Dynamic(..)
|
|
|
|
| ty::Closure(..)
|
|
|
|
| ty::Generator(..)
|
|
|
|
| ty::GeneratorWitness(..)
|
|
|
|
| ty::Never
|
|
|
|
| ty::Tuple(..)
|
|
|
|
// Integers and floats always have `u8` as their discriminant.
|
|
|
|
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
|
|
|
|
|
|
|
|
ty::Projection(..)
|
|
|
|
| ty::Opaque(..)
|
|
|
|
| ty::Param(..)
|
|
|
|
| ty::Bound(..)
|
|
|
|
| ty::Placeholder(..)
|
|
|
|
| ty::Infer(..)
|
2020-05-05 23:02:09 -05:00
|
|
|
| ty::Error(_) => false,
|
2020-04-05 19:57:32 +02:00
|
|
|
}
|
|
|
|
}
|
2020-09-24 19:22:36 +02:00
|
|
|
super::ImplSource::Param(..) => {
|
2016-03-15 06:10:01 -04:00
|
|
|
// This case tell us nothing about the value of an
|
|
|
|
// associated type. Consider:
|
|
|
|
//
|
|
|
|
// ```
|
|
|
|
// trait SomeTrait { type Foo; }
|
|
|
|
// fn foo<T:SomeTrait>(...) { }
|
|
|
|
// ```
|
|
|
|
//
|
|
|
|
// If the user writes `<T as SomeTrait>::Foo`, then the `T
|
|
|
|
// : SomeTrait` binding does not help us decide what the
|
|
|
|
// type `Foo` is (at least, not more specifically than
|
|
|
|
// what we already knew).
|
|
|
|
//
|
|
|
|
// But wait, you say! What about an example like this:
|
|
|
|
//
|
|
|
|
// ```
|
|
|
|
// fn bar<T:SomeTrait<Foo=usize>>(...) { ... }
|
|
|
|
// ```
|
|
|
|
//
|
|
|
|
// Doesn't the `T : Sometrait<Foo=usize>` predicate help
|
|
|
|
// resolve `T::Foo`? And of course it does, but in fact
|
|
|
|
// that single predicate is desugared into two predicates
|
|
|
|
// in the compiler: a trait predicate (`T : SomeTrait`) and a
|
|
|
|
// projection. And the projection where clause is handled
|
|
|
|
// in `assemble_candidates_from_param_env`.
|
2018-02-18 12:32:23 +09:00
|
|
|
false
|
2016-03-15 06:10:01 -04:00
|
|
|
}
|
2020-07-24 21:59:43 +01:00
|
|
|
super::ImplSource::Object(_) => {
|
|
|
|
// Handled by the `Object` projection candidate. See
|
|
|
|
// `assemble_candidates_from_object_ty` for an explanation of
|
|
|
|
// why we special case object types.
|
|
|
|
false
|
|
|
|
}
|
2020-09-24 19:22:36 +02:00
|
|
|
super::ImplSource::AutoImpl(..) | super::ImplSource::Builtin(..) => {
|
2016-03-15 06:10:01 -04:00
|
|
|
// These traits have no associated types.
|
2020-08-13 20:45:08 +01:00
|
|
|
selcx.tcx().sess.delay_span_bug(
|
2016-03-15 06:10:01 -04:00
|
|
|
obligation.cause.span,
|
2020-08-13 20:45:08 +01:00
|
|
|
&format!("Cannot project an associated type from `{:?}`", impl_source),
|
2019-12-22 17:42:04 -05:00
|
|
|
);
|
2020-08-13 20:45:08 +01:00
|
|
|
return Err(());
|
2016-03-15 06:10:01 -04:00
|
|
|
}
|
2018-02-18 12:32:23 +09:00
|
|
|
};
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2018-02-18 12:32:23 +09:00
|
|
|
if eligible {
|
2020-05-11 15:25:33 +00:00
|
|
|
if candidate_set.push_candidate(ProjectionTyCandidate::Select(impl_source)) {
|
2018-02-18 12:32:23 +09:00
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
});
|
2014-12-17 14:16:28 -05:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn confirm_candidate<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2014-12-30 17:42:02 -05:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2019-06-14 01:32:15 +03:00
|
|
|
candidate: ProjectionTyCandidate<'tcx>,
|
|
|
|
) -> Progress<'tcx> {
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?obligation, ?candidate, "confirm_candidate");
|
2020-06-16 18:27:40 +01:00
|
|
|
let mut progress = match candidate {
|
2020-07-24 21:59:43 +01:00
|
|
|
ProjectionTyCandidate::ParamEnv(poly_projection)
|
|
|
|
| ProjectionTyCandidate::Object(poly_projection) => {
|
2020-07-24 19:10:22 +01:00
|
|
|
confirm_param_env_candidate(selcx, obligation, poly_projection, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
ProjectionTyCandidate::TraitDef(poly_projection) => {
|
|
|
|
confirm_param_env_candidate(selcx, obligation, poly_projection, true)
|
2014-12-17 14:16:28 -05:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:25:33 +00:00
|
|
|
ProjectionTyCandidate::Select(impl_source) => {
|
2020-07-24 21:59:43 +01:00
|
|
|
confirm_select_candidate(selcx, obligation, impl_source)
|
2015-01-10 11:54:15 -05:00
|
|
|
}
|
2020-06-16 18:27:40 +01:00
|
|
|
};
|
|
|
|
// When checking for cycle during evaluation, we compare predicates with
|
|
|
|
// "syntactic" equality. Since normalization generally introduces a type
|
|
|
|
// with new region variables, we need to resolve them to existing variables
|
|
|
|
// when possible for this to work. See `auto-trait-projection-recursion.rs`
|
|
|
|
// for a case where this matters.
|
|
|
|
if progress.ty.has_infer_regions() {
|
|
|
|
progress.ty = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty);
|
2016-03-15 06:10:01 -04:00
|
|
|
}
|
2020-06-16 18:27:40 +01:00
|
|
|
progress
|
2016-03-15 06:10:01 -04:00
|
|
|
}
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn confirm_select_candidate<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2016-03-15 06:10:01 -04:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2020-05-11 15:25:33 +00:00
|
|
|
impl_source: Selection<'tcx>,
|
2019-06-14 01:32:15 +03:00
|
|
|
) -> Progress<'tcx> {
|
2020-05-11 15:25:33 +00:00
|
|
|
match impl_source {
|
2020-09-24 19:22:36 +02:00
|
|
|
super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
|
|
|
|
super::ImplSource::Generator(data) => confirm_generator_candidate(selcx, obligation, data),
|
|
|
|
super::ImplSource::Closure(data) => confirm_closure_candidate(selcx, obligation, data),
|
|
|
|
super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data),
|
|
|
|
super::ImplSource::DiscriminantKind(data) => {
|
2020-04-05 19:57:32 +02:00
|
|
|
confirm_discriminant_kind_candidate(selcx, obligation, data)
|
|
|
|
}
|
2020-07-24 21:59:43 +01:00
|
|
|
super::ImplSource::Object(_)
|
|
|
|
| super::ImplSource::AutoImpl(..)
|
2020-09-24 19:22:36 +02:00
|
|
|
| super::ImplSource::Param(..)
|
|
|
|
| super::ImplSource::Builtin(..)
|
2020-10-11 11:37:56 +01:00
|
|
|
| super::ImplSource::TraitAlias(..) => {
|
|
|
|
// we don't create Select candidates with this kind of resolution
|
2016-03-15 06:10:01 -04:00
|
|
|
span_bug!(
|
|
|
|
obligation.cause.span,
|
|
|
|
"Cannot project an associated type from `{:?}`",
|
2020-05-11 15:25:33 +00:00
|
|
|
impl_source
|
2019-12-22 17:42:04 -05:00
|
|
|
)
|
|
|
|
}
|
2015-01-10 11:54:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn confirm_generator_candidate<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2016-12-26 14:34:03 +01:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2020-05-11 15:25:33 +00:00
|
|
|
impl_source: ImplSourceGeneratorData<'tcx, PredicateObligation<'tcx>>,
|
2019-06-14 01:32:15 +03:00
|
|
|
) -> Progress<'tcx> {
|
2020-05-11 15:25:33 +00:00
|
|
|
let gen_sig = impl_source.substs.as_generator().poly_sig();
|
2019-12-22 17:42:04 -05:00
|
|
|
let Normalized { value: gen_sig, obligations } = normalize_with_depth(
|
|
|
|
selcx,
|
|
|
|
obligation.param_env,
|
|
|
|
obligation.cause.clone(),
|
|
|
|
obligation.recursion_depth + 1,
|
|
|
|
&gen_sig,
|
|
|
|
);
|
|
|
|
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?obligation, ?gen_sig, ?obligations, "confirm_generator_candidate");
|
2016-12-26 14:34:03 +01:00
|
|
|
|
|
|
|
let tcx = selcx.tcx();
|
|
|
|
|
2020-08-18 11:47:27 +01:00
|
|
|
let gen_def_id = tcx.require_lang_item(LangItem::Generator, None);
|
2016-12-26 14:34:03 +01:00
|
|
|
|
2020-01-05 20:27:00 +01:00
|
|
|
let predicate = super::util::generator_trait_ref_and_outputs(
|
|
|
|
tcx,
|
|
|
|
gen_def_id,
|
|
|
|
obligation.predicate.self_ty(),
|
|
|
|
gen_sig,
|
|
|
|
)
|
|
|
|
.map_bound(|(trait_ref, yield_ty, return_ty)| {
|
|
|
|
let name = tcx.associated_item(obligation.predicate.item_def_id).ident.name;
|
|
|
|
let ty = if name == sym::Return {
|
|
|
|
return_ty
|
|
|
|
} else if name == sym::Yield {
|
|
|
|
yield_ty
|
|
|
|
} else {
|
|
|
|
bug!()
|
|
|
|
};
|
2016-12-26 14:34:03 +01:00
|
|
|
|
2020-01-05 20:27:00 +01:00
|
|
|
ty::ProjectionPredicate {
|
|
|
|
projection_ty: ty::ProjectionTy {
|
|
|
|
substs: trait_ref.substs,
|
|
|
|
item_def_id: obligation.predicate.item_def_id,
|
|
|
|
},
|
2020-03-06 19:28:44 +01:00
|
|
|
ty,
|
2020-01-05 20:27:00 +01:00
|
|
|
}
|
|
|
|
});
|
2016-12-26 14:34:03 +01:00
|
|
|
|
2020-07-24 19:10:22 +01:00
|
|
|
confirm_param_env_candidate(selcx, obligation, predicate, false)
|
2020-05-11 15:25:33 +00:00
|
|
|
.with_addl_obligations(impl_source.nested)
|
2016-12-26 14:34:03 +01:00
|
|
|
.with_addl_obligations(obligations)
|
|
|
|
}
|
|
|
|
|
2020-04-05 19:57:32 +02:00
|
|
|
fn confirm_discriminant_kind_candidate<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2020-05-11 15:25:33 +00:00
|
|
|
_: ImplSourceDiscriminantKindData,
|
2020-04-05 19:57:32 +02:00
|
|
|
) -> Progress<'tcx> {
|
|
|
|
let tcx = selcx.tcx();
|
|
|
|
|
|
|
|
let self_ty = selcx.infcx().shallow_resolve(obligation.predicate.self_ty());
|
|
|
|
let substs = tcx.mk_substs([self_ty.into()].iter());
|
|
|
|
|
2020-08-18 11:47:27 +01:00
|
|
|
let discriminant_def_id = tcx.require_lang_item(LangItem::Discriminant, None);
|
2020-04-05 19:57:32 +02:00
|
|
|
|
|
|
|
let predicate = ty::ProjectionPredicate {
|
|
|
|
projection_ty: ty::ProjectionTy { substs, item_def_id: discriminant_def_id },
|
2020-07-15 09:59:08 +02:00
|
|
|
ty: self_ty.discriminant_ty(tcx),
|
2020-04-05 19:57:32 +02:00
|
|
|
};
|
|
|
|
|
2020-07-24 19:10:22 +01:00
|
|
|
confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate), false)
|
2020-04-05 19:57:32 +02:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn confirm_fn_pointer_candidate<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2015-01-10 11:54:15 -05:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2020-05-11 15:25:33 +00:00
|
|
|
fn_pointer_impl_source: ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>,
|
2019-06-14 01:32:15 +03:00
|
|
|
) -> Progress<'tcx> {
|
2020-05-11 15:25:33 +00:00
|
|
|
let fn_type = selcx.infcx().shallow_resolve(fn_pointer_impl_source.fn_ty);
|
2017-05-13 17:11:52 +03:00
|
|
|
let sig = fn_type.fn_sig(selcx.tcx());
|
2019-12-22 17:42:04 -05:00
|
|
|
let Normalized { value: sig, obligations } = normalize_with_depth(
|
|
|
|
selcx,
|
|
|
|
obligation.param_env,
|
|
|
|
obligation.cause.clone(),
|
|
|
|
obligation.recursion_depth + 1,
|
|
|
|
&sig,
|
|
|
|
);
|
2017-05-13 17:11:52 +03:00
|
|
|
|
2015-01-10 11:54:15 -05:00
|
|
|
confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
|
2020-05-11 15:25:33 +00:00
|
|
|
.with_addl_obligations(fn_pointer_impl_source.nested)
|
2017-05-13 17:11:52 +03:00
|
|
|
.with_addl_obligations(obligations)
|
2015-01-10 11:54:15 -05:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn confirm_closure_candidate<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2015-01-10 11:54:15 -05:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2020-05-11 15:25:33 +00:00
|
|
|
impl_source: ImplSourceClosureData<'tcx, PredicateObligation<'tcx>>,
|
2019-06-14 01:32:15 +03:00
|
|
|
) -> Progress<'tcx> {
|
2020-05-11 15:25:33 +00:00
|
|
|
let closure_sig = impl_source.substs.as_closure().sig();
|
2019-12-22 17:42:04 -05:00
|
|
|
let Normalized { value: closure_sig, obligations } = normalize_with_depth(
|
|
|
|
selcx,
|
|
|
|
obligation.param_env,
|
|
|
|
obligation.cause.clone(),
|
|
|
|
obligation.recursion_depth + 1,
|
|
|
|
&closure_sig,
|
|
|
|
);
|
|
|
|
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?obligation, ?closure_sig, ?obligations, "confirm_closure_candidate");
|
2019-12-22 17:42:04 -05:00
|
|
|
|
|
|
|
confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No)
|
2020-05-11 15:25:33 +00:00
|
|
|
.with_addl_obligations(impl_source.nested)
|
2016-11-29 00:12:07 +02:00
|
|
|
.with_addl_obligations(obligations)
|
2015-01-10 11:54:15 -05:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn confirm_callable_candidate<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2015-01-10 11:54:15 -05:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2017-02-13 10:51:06 +02:00
|
|
|
fn_sig: ty::PolyFnSig<'tcx>,
|
2019-06-14 01:32:15 +03:00
|
|
|
flag: util::TupleArgumentsFlag,
|
|
|
|
) -> Progress<'tcx> {
|
2015-01-10 11:54:15 -05:00
|
|
|
let tcx = selcx.tcx();
|
|
|
|
|
2020-10-11 11:37:56 +01:00
|
|
|
debug!(?obligation, ?fn_sig, "confirm_callable_candidate");
|
2015-01-10 11:54:15 -05:00
|
|
|
|
2020-08-18 11:47:27 +01:00
|
|
|
let fn_once_def_id = tcx.require_lang_item(LangItem::FnOnce, None);
|
|
|
|
let fn_once_output_def_id = tcx.require_lang_item(LangItem::FnOnceOutput, None);
|
2015-02-15 15:09:26 -05:00
|
|
|
|
2020-01-05 20:27:00 +01:00
|
|
|
let predicate = super::util::closure_trait_ref_and_return_type(
|
|
|
|
tcx,
|
|
|
|
fn_once_def_id,
|
|
|
|
obligation.predicate.self_ty(),
|
|
|
|
fn_sig,
|
|
|
|
flag,
|
|
|
|
)
|
|
|
|
.map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
|
2020-05-24 23:07:55 -04:00
|
|
|
projection_ty: ty::ProjectionTy {
|
|
|
|
substs: trait_ref.substs,
|
|
|
|
item_def_id: fn_once_output_def_id,
|
|
|
|
},
|
2020-01-05 20:27:00 +01:00
|
|
|
ty: ret_type,
|
|
|
|
});
|
2015-01-10 11:54:15 -05:00
|
|
|
|
2020-07-24 19:10:22 +01:00
|
|
|
confirm_param_env_candidate(selcx, obligation, predicate, false)
|
2015-01-10 11:54:15 -05:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn confirm_param_env_candidate<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2015-01-10 11:54:15 -05:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2019-02-20 05:22:23 -05:00
|
|
|
poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
|
2020-07-24 19:10:22 +01:00
|
|
|
potentially_unnormalized_candidate: bool,
|
2019-02-20 05:22:23 -05:00
|
|
|
) -> Progress<'tcx> {
|
2015-01-10 11:54:15 -05:00
|
|
|
let infcx = selcx.infcx();
|
2018-09-07 20:11:23 -04:00
|
|
|
let cause = &obligation.cause;
|
2017-05-23 04:19:47 -04:00
|
|
|
let param_env = obligation.param_env;
|
2018-09-07 20:11:23 -04:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
let (cache_entry, _) = infcx.replace_bound_vars_with_fresh_vars(
|
|
|
|
cause.span,
|
|
|
|
LateBoundRegionConversionTime::HigherRankedType,
|
|
|
|
&poly_cache_entry,
|
|
|
|
);
|
2018-09-07 20:11:23 -04:00
|
|
|
|
|
|
|
let cache_trait_ref = cache_entry.projection_ty.trait_ref(infcx.tcx);
|
|
|
|
let obligation_trait_ref = obligation.predicate.trait_ref(infcx.tcx);
|
2020-07-24 19:10:22 +01:00
|
|
|
let mut nested_obligations = Vec::new();
|
|
|
|
let cache_trait_ref = if potentially_unnormalized_candidate {
|
|
|
|
ensure_sufficient_stack(|| {
|
|
|
|
normalize_with_depth_to(
|
|
|
|
selcx,
|
|
|
|
obligation.param_env,
|
|
|
|
obligation.cause.clone(),
|
|
|
|
obligation.recursion_depth + 1,
|
|
|
|
&cache_trait_ref,
|
|
|
|
&mut nested_obligations,
|
|
|
|
)
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
cache_trait_ref
|
|
|
|
};
|
|
|
|
|
2018-09-07 20:11:23 -04:00
|
|
|
match infcx.at(cause, param_env).eq(cache_trait_ref, obligation_trait_ref) {
|
2020-07-24 19:10:22 +01:00
|
|
|
Ok(InferOk { value: _, obligations }) => {
|
|
|
|
nested_obligations.extend(obligations);
|
2020-07-25 13:41:53 +01:00
|
|
|
assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations);
|
2020-07-24 19:10:22 +01:00
|
|
|
Progress { ty: cache_entry.ty, obligations: nested_obligations }
|
|
|
|
}
|
2015-01-10 11:54:15 -05:00
|
|
|
Err(e) => {
|
2019-05-08 11:42:47 -07:00
|
|
|
let msg = format!(
|
|
|
|
"Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}",
|
2019-12-22 17:42:04 -05:00
|
|
|
obligation, poly_cache_entry, e,
|
2019-05-08 11:42:47 -07:00
|
|
|
);
|
|
|
|
debug!("confirm_param_env_candidate: {}", msg);
|
2020-05-05 23:02:09 -05:00
|
|
|
let err = infcx.tcx.ty_error_with_message(obligation.cause.span, &msg);
|
|
|
|
Progress { ty: err, obligations: vec![] }
|
2015-01-10 11:54:15 -05:00
|
|
|
}
|
2016-05-21 08:29:50 -04:00
|
|
|
}
|
2015-01-10 11:54:15 -05:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn confirm_impl_candidate<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2015-01-10 11:54:15 -05:00
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
2020-06-02 15:54:24 +00:00
|
|
|
impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
|
2019-06-14 01:32:15 +03:00
|
|
|
) -> Progress<'tcx> {
|
2019-12-08 17:19:30 +00:00
|
|
|
let tcx = selcx.tcx();
|
|
|
|
|
2020-07-25 13:41:53 +01:00
|
|
|
let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source;
|
2019-12-08 17:19:30 +00:00
|
|
|
let assoc_item_id = obligation.predicate.item_def_id;
|
|
|
|
let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
|
2015-01-10 11:54:15 -05:00
|
|
|
|
2017-05-23 04:19:47 -04:00
|
|
|
let param_env = obligation.param_env;
|
2020-02-08 20:10:06 +00:00
|
|
|
let assoc_ty = match assoc_ty_def(selcx, impl_def_id, assoc_item_id) {
|
|
|
|
Ok(assoc_ty) => assoc_ty,
|
2020-05-05 23:02:09 -05:00
|
|
|
Err(ErrorReported) => return Progress { ty: tcx.ty_error(), obligations: nested },
|
2020-02-08 20:10:06 +00:00
|
|
|
};
|
2016-02-16 10:36:47 -08:00
|
|
|
|
2018-07-23 17:38:45 +02:00
|
|
|
if !assoc_ty.item.defaultness.has_value() {
|
2017-05-16 17:31:18 +02:00
|
|
|
// This means that the impl is missing a definition for the
|
|
|
|
// associated type. This error will be reported by the type
|
|
|
|
// checker method `check_impl_items_against_trait`, so here we
|
2018-08-22 01:35:02 +01:00
|
|
|
// just return Error.
|
2019-12-22 17:42:04 -05:00
|
|
|
debug!(
|
|
|
|
"confirm_impl_candidate: no associated type {:?} for {:?}",
|
|
|
|
assoc_ty.item.ident, obligation.predicate
|
|
|
|
);
|
2020-05-05 23:02:09 -05:00
|
|
|
return Progress { ty: tcx.ty_error(), obligations: nested };
|
2018-07-23 17:38:45 +02:00
|
|
|
}
|
2020-05-30 17:19:31 +01:00
|
|
|
// If we're trying to normalize `<Vec<u32> as X>::A<S>` using
|
|
|
|
//`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
|
|
|
|
//
|
|
|
|
// * `obligation.predicate.substs` is `[Vec<u32>, S]`
|
|
|
|
// * `substs` is `[u32]`
|
|
|
|
// * `substs` ends up as `[u32, S]`
|
2019-12-08 17:19:30 +00:00
|
|
|
let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
|
2020-03-29 00:57:49 +01:00
|
|
|
let substs =
|
|
|
|
translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node);
|
2020-05-10 12:15:51 +01:00
|
|
|
let ty = tcx.type_of(assoc_ty.item.def_id);
|
2019-12-08 17:19:30 +00:00
|
|
|
if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
|
2020-05-05 23:02:09 -05:00
|
|
|
let err = tcx.ty_error_with_message(
|
2020-07-25 13:41:53 +01:00
|
|
|
obligation.cause.span,
|
2020-05-05 23:02:09 -05:00
|
|
|
"impl item and trait item have different parameter counts",
|
|
|
|
);
|
|
|
|
Progress { ty: err, obligations: nested }
|
2019-12-08 17:19:30 +00:00
|
|
|
} else {
|
2020-07-25 13:41:53 +01:00
|
|
|
assoc_ty_own_obligations(selcx, obligation, &mut nested);
|
2019-12-22 17:42:04 -05:00
|
|
|
Progress { ty: ty.subst(tcx, substs), obligations: nested }
|
2016-02-16 10:36:47 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-25 13:41:53 +01:00
|
|
|
// Get obligations corresponding to the predicates from the where-clause of the
|
|
|
|
// associated type itself.
|
|
|
|
// Note: `feature(generic_associated_types)` is required to write such
|
|
|
|
// predicates, even for non-generic associcated types.
|
|
|
|
fn assoc_ty_own_obligations<'cx, 'tcx>(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
|
|
|
obligation: &ProjectionTyObligation<'tcx>,
|
|
|
|
nested: &mut Vec<PredicateObligation<'tcx>>,
|
|
|
|
) {
|
|
|
|
let tcx = selcx.tcx();
|
|
|
|
for predicate in tcx
|
|
|
|
.predicates_of(obligation.predicate.item_def_id)
|
|
|
|
.instantiate_own(tcx, obligation.predicate.substs)
|
|
|
|
.predicates
|
|
|
|
{
|
|
|
|
let normalized = normalize_with_depth_to(
|
|
|
|
selcx,
|
|
|
|
obligation.param_env,
|
|
|
|
obligation.cause.clone(),
|
|
|
|
obligation.recursion_depth + 1,
|
|
|
|
&predicate,
|
|
|
|
nested,
|
|
|
|
);
|
|
|
|
nested.push(Obligation::with_depth(
|
|
|
|
obligation.cause.clone(),
|
|
|
|
obligation.recursion_depth + 1,
|
|
|
|
obligation.param_env,
|
|
|
|
normalized,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-16 10:36:47 -08:00
|
|
|
/// Locate the definition of an associated type in the specialization hierarchy,
|
|
|
|
/// starting from the given impl.
|
|
|
|
///
|
|
|
|
/// Based on the "projection mode", this lookup may in fact only examine the
|
2016-06-30 21:22:47 +03:00
|
|
|
/// topmost impl. See the comments for `Reveal` for more details.
|
2019-06-21 18:12:39 +02:00
|
|
|
fn assoc_ty_def(
|
|
|
|
selcx: &SelectionContext<'_, '_>,
|
2016-04-29 06:00:23 +03:00
|
|
|
impl_def_id: DefId,
|
2019-06-14 01:32:15 +03:00
|
|
|
assoc_ty_def_id: DefId,
|
2020-03-29 00:57:49 +01:00
|
|
|
) -> Result<specialization_graph::LeafDef, ErrorReported> {
|
2017-05-15 12:21:28 +02:00
|
|
|
let tcx = selcx.tcx();
|
2018-06-10 22:24:24 +03:00
|
|
|
let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident;
|
2017-05-15 12:21:28 +02:00
|
|
|
let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id;
|
|
|
|
let trait_def = tcx.trait_def(trait_def_id);
|
|
|
|
|
|
|
|
// This function may be called while we are still building the
|
2020-02-08 20:10:06 +00:00
|
|
|
// specialization graph that is queried below (via TraitDef::ancestors()),
|
2017-05-16 15:03:20 +02:00
|
|
|
// so, in order to avoid unnecessary infinite recursion, we manually look
|
|
|
|
// for the associated item at the given impl.
|
|
|
|
// If there is no such item in that impl, this function will fail with a
|
|
|
|
// cycle error if the specialization graph is currently being built.
|
|
|
|
let impl_node = specialization_graph::Node::Impl(impl_def_id);
|
|
|
|
for item in impl_node.items(tcx) {
|
2020-05-10 12:15:51 +01:00
|
|
|
if matches!(item.kind, ty::AssocKind::Type)
|
2019-12-22 17:42:04 -05:00
|
|
|
&& tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
|
|
|
|
{
|
2020-03-29 00:57:49 +01:00
|
|
|
return Ok(specialization_graph::LeafDef {
|
2020-02-06 23:21:44 +01:00
|
|
|
item: *item,
|
2020-03-29 00:57:49 +01:00
|
|
|
defining_node: impl_node,
|
|
|
|
finalizing_node: if item.defaultness.is_default() { None } else { Some(impl_node) },
|
2020-02-08 20:10:06 +00:00
|
|
|
});
|
2017-05-15 12:21:28 +02:00
|
|
|
}
|
|
|
|
}
|
2017-05-16 15:03:20 +02:00
|
|
|
|
2020-02-08 20:10:06 +00:00
|
|
|
let ancestors = trait_def.ancestors(tcx, impl_def_id)?;
|
|
|
|
if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) {
|
|
|
|
Ok(assoc_item)
|
2017-05-16 17:31:18 +02:00
|
|
|
} else {
|
|
|
|
// This is saying that neither the trait nor
|
|
|
|
// the impl contain a definition for this
|
|
|
|
// associated type. Normally this situation
|
|
|
|
// could only arise through a compiler bug --
|
|
|
|
// if the user wrote a bad item name, it
|
|
|
|
// should have failed in astconv.
|
2019-12-22 17:42:04 -05:00
|
|
|
bug!("No associated type `{}` for {}", assoc_ty_name, tcx.def_path_str(impl_def_id))
|
2017-05-16 17:31:18 +02:00
|
|
|
}
|
2014-12-17 14:16:28 -05:00
|
|
|
}
|
2016-05-21 08:18:52 -04:00
|
|
|
|
2020-02-22 11:44:18 +01:00
|
|
|
crate trait ProjectionCacheKeyExt<'tcx>: Sized {
|
|
|
|
fn from_poly_projection_predicate(
|
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2020-05-23 11:09:32 +02:00
|
|
|
predicate: ty::PolyProjectionPredicate<'tcx>,
|
2020-02-22 11:44:18 +01:00
|
|
|
) -> Option<Self>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> ProjectionCacheKeyExt<'tcx> for ProjectionCacheKey<'tcx> {
|
|
|
|
fn from_poly_projection_predicate(
|
2019-06-14 01:32:15 +03:00
|
|
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
2020-05-23 11:09:32 +02:00
|
|
|
predicate: ty::PolyProjectionPredicate<'tcx>,
|
2019-06-14 01:32:15 +03:00
|
|
|
) -> Option<Self> {
|
2017-08-20 19:16:36 +03:00
|
|
|
let infcx = selcx.infcx();
|
|
|
|
// We don't do cross-snapshot caching of obligations with escaping regions,
|
|
|
|
// so there's no cache key to use
|
2020-02-22 11:44:18 +01:00
|
|
|
predicate.no_bound_vars().map(|predicate| {
|
|
|
|
ProjectionCacheKey::new(
|
|
|
|
// We don't attempt to match up with a specific type-variable state
|
|
|
|
// from a specific call to `opt_normalize_projection_type` - if
|
|
|
|
// there's no precise match, the original cache entry is "stranded"
|
|
|
|
// anyway.
|
|
|
|
infcx.resolve_vars_if_possible(&predicate.projection_ty),
|
|
|
|
)
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
2017-08-20 19:16:36 +03:00
|
|
|
}
|
2016-05-21 08:18:52 -04:00
|
|
|
}
|