summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/select
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:11:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:13:23 +0000
commit20431706a863f92cb37dc512fef6e48d192aaf2c (patch)
tree2867f13f5fd5437ba628c67d7f87309ccadcd286 /compiler/rustc_trait_selection/src/traits/select
parentReleasing progress-linux version 1.65.0+dfsg1-2~progress7.99u1. (diff)
downloadrustc-20431706a863f92cb37dc512fef6e48d192aaf2c.tar.xz
rustc-20431706a863f92cb37dc512fef6e48d192aaf2c.zip
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/select')
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs29
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs72
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs149
3 files changed, 120 insertions, 130 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index a80527f63..4c5bc3339 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -6,6 +6,7 @@
//!
//! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
use hir::LangItem;
+use rustc_errors::DelayDm;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::traits::ObligationCause;
@@ -173,7 +174,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?stack, ?candidates, "winnowed to {} candidates", candidates.len());
- let needs_infer = stack.obligation.predicate.has_infer_types_or_consts();
+ let needs_infer = stack.obligation.predicate.has_non_region_infer();
// If there are STILL multiple candidates, we can further
// reduce the list by dropping duplicates -- including
@@ -362,7 +363,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.infcx
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));
- candidates.vec.extend(result.into_iter().map(ProjectionCandidate));
+ candidates
+ .vec
+ .extend(result.into_iter().map(|(idx, constness)| ProjectionCandidate(idx, constness)));
}
/// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller
@@ -622,7 +625,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- _ => candidates.vec.push(AutoImplCandidate(def_id)),
+ _ => candidates.vec.push(AutoImplCandidate),
}
}
}
@@ -823,13 +826,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
DEREF_INTO_DYN_SUPERTRAIT,
obligation.cause.body_id,
obligation.cause.span,
- |lint| {
- lint.build(&format!(
- "`{}` implements `Deref` with supertrait `{}` as output",
- source,
- deref_output_ty
- )).emit();
- },
+ DelayDm(|| format!(
+ "`{}` implements `Deref` with supertrait `{}` as output",
+ source, deref_output_ty
+ )),
+ |lint| lint,
);
return;
}
@@ -888,11 +889,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &TraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
- if obligation.has_param_types_or_consts() {
+ if obligation.has_non_region_param() {
return;
}
- if obligation.has_infer_types_or_consts() {
+ if obligation.has_non_region_infer() {
candidates.ambiguous = true;
return;
}
@@ -913,7 +914,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let def_id = obligation.predicate.def_id();
if self.tcx().is_trait_alias(def_id) {
- candidates.vec.push(TraitAliasCandidate(def_id));
+ candidates.vec.push(TraitAliasCandidate);
}
}
@@ -1020,7 +1021,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let self_ty = self.infcx().shallow_resolve(obligation.self_ty().skip_binder());
match self_ty.kind() {
ty::Tuple(_) => {
- candidates.vec.push(TupleCandidate);
+ candidates.vec.push(BuiltinCandidate { has_nested: false });
}
ty::Infer(ty::TyVar(_)) => {
candidates.ambiguous = true;
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index d1deef784..ed22058c6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -11,9 +11,10 @@ use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::InferOk;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
-use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt};
-use rustc_middle::ty::{ToPolyTraitRef, ToPredicate};
+use rustc_middle::ty::{
+ self, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef,
+ ToPolyTraitRef, ToPredicate, Ty, TyCtxt,
+};
use rustc_span::def_id::DefId;
use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
@@ -63,15 +64,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id))
}
- AutoImplCandidate(trait_def_id) => {
- let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
+ AutoImplCandidate => {
+ let data = self.confirm_auto_impl_candidate(obligation);
ImplSource::AutoImpl(data)
}
- ProjectionCandidate(idx) => {
+ ProjectionCandidate(idx, constness) => {
let obligations = self.confirm_projection_candidate(obligation, idx)?;
- // FIXME(jschievink): constness
- ImplSource::Param(obligations, ty::BoundConstness::NotConst)
+ ImplSource::Param(obligations, constness)
}
ObjectCandidate(idx) => {
@@ -100,8 +100,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
PointeeCandidate => ImplSource::Pointee(ImplSourcePointeeData),
- TraitAliasCandidate(alias_def_id) => {
- let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
+ TraitAliasCandidate => {
+ let data = self.confirm_trait_alias_candidate(obligation);
ImplSource::TraitAlias(data)
}
@@ -126,8 +126,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
ImplSource::ConstDestruct(data)
}
-
- TupleCandidate => ImplSource::Tuple,
};
if !obligation.predicate.is_const_if_const() {
@@ -290,8 +288,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let scope = type_at(2).skip_binder();
- let assume =
- rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, const_at(3));
+ let Some(assume) =
+ rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, const_at(3)) else {
+ return Err(Unimplemented);
+ };
let cause = obligation.cause.clone();
@@ -315,13 +315,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn confirm_auto_impl_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
- trait_def_id: DefId,
) -> ImplSourceAutoImplData<PredicateObligation<'tcx>> {
- debug!(?obligation, ?trait_def_id, "confirm_auto_impl_candidate");
+ debug!(?obligation, "confirm_auto_impl_candidate");
let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
let types = self.constituent_types_for_ty(self_ty);
- self.vtable_auto_impl(obligation, trait_def_id, types)
+ self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types)
}
/// See `confirm_auto_impl_candidate`.
@@ -619,17 +618,47 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)
.map_bound(|(trait_ref, _)| trait_ref);
- let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+ let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+
+ // Confirm the `type Output: Sized;` bound that is present on `FnOnce`
+ let cause = obligation.derived_cause(BuiltinDerivedObligation);
+ // The binder on the Fn obligation is "less" important than the one on
+ // the signature, as evidenced by how we treat it during projection.
+ // The safe thing to do here is to liberate it, though, which should
+ // have no worse effect than skipping the binder here.
+ let liberated_fn_ty =
+ self.infcx.replace_bound_vars_with_placeholders(obligation.predicate.rebind(self_ty));
+ let output_ty = self
+ .infcx
+ .replace_bound_vars_with_placeholders(liberated_fn_ty.fn_sig(self.tcx()).output());
+ let output_ty = normalize_with_depth_to(
+ self,
+ obligation.param_env,
+ cause.clone(),
+ obligation.recursion_depth,
+ output_ty,
+ &mut nested,
+ );
+ let tr = ty::Binder::dummy(ty::TraitRef::new(
+ self.tcx().require_lang_item(LangItem::Sized, None),
+ self.tcx().mk_substs_trait(output_ty, &[]),
+ ));
+ nested.push(Obligation::new(
+ cause,
+ obligation.param_env,
+ tr.to_poly_trait_predicate().to_predicate(self.tcx()),
+ ));
+
Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested })
}
fn confirm_trait_alias_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
- alias_def_id: DefId,
) -> ImplSourceTraitAliasData<'tcx, PredicateObligation<'tcx>> {
- debug!(?obligation, ?alias_def_id, "confirm_trait_alias_candidate");
+ debug!(?obligation, "confirm_trait_alias_candidate");
+ let alias_def_id = obligation.predicate.def_id();
let predicate = self.infcx().replace_bound_vars_with_placeholders(obligation.predicate);
let trait_ref = predicate.trait_ref;
let trait_def_id = trait_ref.def_id;
@@ -1196,6 +1225,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Never
| ty::Foreign(_) => {}
+ // `ManuallyDrop` is trivially drop
+ ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().manually_drop() => {}
+
// These types are built-in, so we can fast-track by registering
// nested predicates for their constituent type(s)
ty::Array(ty, _) | ty::Slice(ty) => {
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 75bd2c89f..9ebff4892 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -20,7 +20,7 @@ use super::{
};
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
-use crate::traits::error_reporting::InferCtxtExt;
+use crate::traits::error_reporting::TypeErrCtxtExt;
use crate::traits::project::ProjectAndUnifyResult;
use crate::traits::project::ProjectionCacheKeyExt;
use crate::traits::ProjectionCacheKey;
@@ -35,9 +35,8 @@ use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
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::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitable};
use rustc_span::symbol::sym;
@@ -94,7 +93,7 @@ impl IntercrateAmbiguityCause {
}
pub struct SelectionContext<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
/// Freshener used specifically for entries on the obligation
/// stack. This ensures that all entries on the stack at one time
@@ -215,7 +214,7 @@ enum BuiltinImplConditions<'tcx> {
}
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
- pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
+ pub fn new(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
SelectionContext {
infcx,
freshener: infcx.freshener_keep_static(),
@@ -225,28 +224,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
- SelectionContext {
- infcx,
- freshener: infcx.freshener_keep_static(),
- intercrate: true,
- intercrate_ambiguity_causes: None,
- query_mode: TraitQueryMode::Standard,
- }
+ pub fn intercrate(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
+ SelectionContext { intercrate: true, ..SelectionContext::new(infcx) }
}
pub fn with_query_mode(
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
query_mode: TraitQueryMode,
) -> SelectionContext<'cx, 'tcx> {
debug!(?query_mode, "with_query_mode");
- SelectionContext {
- infcx,
- freshener: infcx.freshener_keep_static(),
- intercrate: false,
- intercrate_ambiguity_causes: None,
- query_mode,
- }
+ SelectionContext { query_mode, ..SelectionContext::new(infcx) }
}
/// Enables tracking of intercrate ambiguity causes. See
@@ -266,7 +253,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.intercrate_ambiguity_causes.take().unwrap_or_default()
}
- pub fn infcx(&self) -> &'cx InferCtxt<'cx, 'tcx> {
+ pub fn infcx(&self) -> &'cx InferCtxt<'tcx> {
self.infcx
}
@@ -689,19 +676,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
ty::PredicateKind::ConstEquate(c1, c2) => {
+ assert!(
+ self.tcx().features().generic_const_exprs,
+ "`ConstEquate` without a feature gate: {c1:?} {c2:?}",
+ );
debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");
- if self.tcx().features().generic_const_exprs {
- // FIXME: we probably should only try to unify abstract constants
- // if the constants depend on generic parameters.
- //
- // Let's just see where this breaks :shrug:
- if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
- (c1.kind(), c2.kind())
- {
- if self.infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
- return Ok(EvaluatedToOk);
- }
+ // FIXME: we probably should only try to unify abstract constants
+ // if the constants depend on generic parameters.
+ //
+ // Let's just see where this breaks :shrug:
+ if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
+ (c1.kind(), c2.kind())
+ {
+ if self.infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
+ return Ok(EvaluatedToOk);
}
}
@@ -741,7 +730,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)
}
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
- if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
+ if c1.has_non_region_infer() || c2.has_non_region_infer() {
Ok(EvaluatedToAmbig)
} else {
// Two different constants using generic parameters ~> error.
@@ -839,7 +828,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// must be met of course). One obvious case this comes up is
/// marker traits like `Send`. Think of a linked list:
///
- /// struct List<T> { data: T, next: Option<Box<List<T>>> }
+ /// struct List<T> { data: T, next: Option<Box<List<T>>> }
///
/// `Box<List<T>>` will be `Send` if `T` is `Send` and
/// `Option<Box<List<T>>>` is `Send`, and in turn
@@ -926,38 +915,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let unbound_input_types =
stack.fresh_trait_pred.skip_binder().trait_ref.substs.types().any(|ty| ty.is_fresh());
- if stack.obligation.polarity() != ty::ImplPolarity::Negative {
- // This check was an imperfect workaround for a bug in the old
- // intercrate mode; it should be removed when that goes away.
- if unbound_input_types && self.intercrate {
- debug!("evaluate_stack --> unbound argument, intercrate --> ambiguous",);
- // Heuristics: show the diagnostics when there are no candidates in crate.
- if self.intercrate_ambiguity_causes.is_some() {
- debug!("evaluate_stack: intercrate_ambiguity_causes is some");
- if let Ok(candidate_set) = self.assemble_candidates(stack) {
- if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
- let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
- let self_ty = trait_ref.self_ty();
- let cause = with_no_trimmed_paths!({
- IntercrateAmbiguityCause::DownstreamCrate {
- trait_desc: trait_ref.print_only_trait_path().to_string(),
- self_desc: if self_ty.has_concrete_skeleton() {
- Some(self_ty.to_string())
- } else {
- None
- },
- }
- });
-
- debug!(?cause, "evaluate_stack: pushing cause");
- self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause);
- }
- }
- }
- return Ok(EvaluatedToAmbig);
- }
- }
-
if unbound_input_types
&& stack.iter().skip(1).any(|prev| {
stack.obligation.param_env == prev.obligation.param_env
@@ -1140,7 +1097,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ErrorGuaranteed::unchecked_claim_error_was_emitted(),
));
}
- self.infcx.report_overflow_error(error_obligation, true);
+ self.infcx.err_ctxt().report_overflow_error(error_obligation, true);
}
TraitQueryMode::Canonical => {
return Err(OverflowError::Canonical);
@@ -1192,8 +1149,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplCandidate(def_id) if tcx.constness(def_id) == hir::Constness::Const => {}
// const param
ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {}
+ // const projection
+ ProjectionCandidate(_, ty::BoundConstness::ConstIfConst) => {}
// auto trait impl
- AutoImplCandidate(..) => {}
+ AutoImplCandidate => {}
// generator, this will raise error in other places
// or ignore error with const_async_blocks feature
GeneratorCandidate => {}
@@ -1399,7 +1358,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &TraitObligation<'tcx>,
- ) -> smallvec::SmallVec<[usize; 2]> {
+ ) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> {
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);
@@ -1447,7 +1406,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => false,
}
}) {
- return Some(idx);
+ return Some((idx, pred.constness));
}
}
None
@@ -1563,7 +1522,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if !generics.params.is_empty()
&& obligation.predicate.substs[generics.parent_count..]
.iter()
- .any(|&p| p.has_infer_types_or_consts() && self.infcx.shallow_resolve(p) != p)
+ .any(|&p| p.has_non_region_infer() && self.infcx.shallow_resolve(p) != p)
{
ProjectionMatchesProjection::Ambiguous
} else {
@@ -1605,13 +1564,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
};
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
- // `DiscriminantKindCandidate`, `ConstDestructCandidate`, and `TupleCandidate`
+ // `DiscriminantKindCandidate`, `ConstDestructCandidate`
// to anything else.
//
// This is a fix for #53123 and prevents winnowing from accidentally extending the
// lifetime of a variable.
match (&other.candidate, &victim.candidate) {
- (_, AutoImplCandidate(..)) | (AutoImplCandidate(..), _) => {
+ (_, AutoImplCandidate) | (AutoImplCandidate, _) => {
bug!(
"default implementations shouldn't be recorded \
when there are other valid candidates"
@@ -1626,8 +1585,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
BuiltinCandidate { has_nested: false }
| DiscriminantKindCandidate
| PointeeCandidate
- | ConstDestructCandidate(_)
- | TupleCandidate,
+ | ConstDestructCandidate(_),
_,
) => true,
(
@@ -1635,8 +1593,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
BuiltinCandidate { has_nested: false }
| DiscriminantKindCandidate
| PointeeCandidate
- | ConstDestructCandidate(_)
- | TupleCandidate,
+ | ConstDestructCandidate(_),
) => false,
(ParamCandidate(other), ParamCandidate(victim)) => {
@@ -1681,11 +1638,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { .. }
- | TraitAliasCandidate(..)
+ | TraitAliasCandidate
| ObjectCandidate(_)
- | ProjectionCandidate(_),
+ | ProjectionCandidate(..),
) => !is_global(cand),
- (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => {
+ (ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref cand)) => {
// Prefer these to a global where-clause bound
// (see issue #50825).
is_global(cand)
@@ -1699,7 +1656,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { has_nested: true }
- | TraitAliasCandidate(..),
+ | TraitAliasCandidate,
ParamCandidate(ref cand),
) => {
// Prefer these to a global where-clause bound
@@ -1707,20 +1664,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
is_global(cand) && other.evaluation.must_apply_modulo_regions()
}
- (ProjectionCandidate(i), ProjectionCandidate(j))
+ (ProjectionCandidate(i, _), ProjectionCandidate(j, _))
| (ObjectCandidate(i), ObjectCandidate(j)) => {
// Arbitrarily pick the lower numbered candidate for backwards
// compatibility reasons. Don't let this affect inference.
i < j && !needs_infer
}
- (ObjectCandidate(_), ProjectionCandidate(_))
- | (ProjectionCandidate(_), ObjectCandidate(_)) => {
+ (ObjectCandidate(_), ProjectionCandidate(..))
+ | (ProjectionCandidate(..), ObjectCandidate(_)) => {
bug!("Have both object and projection candidate")
}
// Arbitrarily give projection and object candidates priority.
(
- ObjectCandidate(_) | ProjectionCandidate(_),
+ ObjectCandidate(_) | ProjectionCandidate(..),
ImplCandidate(..)
| ClosureCandidate
| GeneratorCandidate
@@ -1729,7 +1686,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { .. }
- | TraitAliasCandidate(..),
+ | TraitAliasCandidate,
) => true,
(
@@ -1741,18 +1698,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { .. }
- | TraitAliasCandidate(..),
- ObjectCandidate(_) | ProjectionCandidate(_),
+ | TraitAliasCandidate,
+ ObjectCandidate(_) | ProjectionCandidate(..),
) => false,
(&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {
// See if we can toss out `victim` based on specialization.
- // This requires us to know *for sure* that the `other` impl applies
- // i.e., `EvaluatedToOk`.
+ // While this requires us to know *for sure* that the `other` impl applies
+ // we still use modulo regions here.
//
- // FIXME(@lcnr): Using `modulo_regions` here seems kind of scary
- // to me but is required for `std` to compile, so I didn't change it
- // for now.
+ // This is fine as specialization currently assumes that specializing
+ // impls have to be always applicable, meaning that the only allowed
+ // region constraints may be constraints also present on the default impl.
let tcx = self.tcx();
if other.evaluation.must_apply_modulo_regions() {
if tcx.specializes((other_def, victim_def)) {
@@ -1822,7 +1779,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { has_nested: true }
- | TraitAliasCandidate(..),
+ | TraitAliasCandidate,
ImplCandidate(_)
| ClosureCandidate
| GeneratorCandidate
@@ -1831,7 +1788,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { has_nested: true }
- | TraitAliasCandidate(..),
+ | TraitAliasCandidate,
) => false,
}
}