From 20431706a863f92cb37dc512fef6e48d192aaf2c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:11:38 +0200 Subject: Merging upstream version 1.66.0+dfsg1. Signed-off-by: Daniel Baumann --- .../src/traits/select/candidate_assembly.rs | 29 ++-- .../src/traits/select/confirmation.rs | 72 +++++++--- .../rustc_trait_selection/src/traits/select/mod.rs | 149 ++++++++------------- 3 files changed, 120 insertions(+), 130 deletions(-) (limited to 'compiler/rustc_trait_selection/src/traits/select') 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 ``, 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> { - 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 { data: T, next: Option>> } + /// struct List { data: T, next: Option>> } /// /// `Box>` will be `Send` if `T` is `Send` and /// `Option>>` 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, } } -- cgit v1.2.3