From 5b5a2e600ebf15aa06dae1c35b7ee9f6c8f74176 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 22 Oct 2021 10:56:32 -0300 Subject: [PATCH] Move const filter to filter_impls --- .../src/traits/select/candidate_assembly.rs | 4 +- .../src/traits/select/mod.rs | 81 ++++++++++--------- 2 files changed, 47 insertions(+), 38 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 8bb7ed8de23..77b1c279efa 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -121,7 +121,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Ok(None); } - let mut candidates = candidate_set.vec; + let candidates = candidate_set.vec; debug!(?stack, ?candidates, "assembled {} candidates", candidates.len()); @@ -134,7 +134,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // candidate which assumes $0 == int, one that assumes `$0 == // usize`, etc. This spells an ambiguity. - self.filter_impls(&mut candidates, stack); + let mut candidates = self.filter_impls(candidates, stack.obligation); // If there is more than one candidate, first winnow them down // by considering extra conditions (nested obligations and so diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 94c4bc55f79..dfadf693872 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::ObligationCauseCode; use super::Selection; use super::SelectionResult; use super::TraitQueryMode; -use super::{ErrorReporting, Overflow, SelectionError, Unimplemented}; +use super::{ErrorReporting, Overflow, SelectionError}; use super::{ObligationCause, PredicateObligation, TraitObligation}; use crate::infer::{InferCtxt, InferOk, TypeFreshener}; @@ -1122,19 +1122,52 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(level = "debug", skip(self))] fn filter_impls( &mut self, - candidates: &mut Vec>, - stack: &TraitObligationStack<'o, 'tcx>, - ) { + candidates: Vec>, + obligation: &TraitObligation<'tcx>, + ) -> Vec> { let tcx = self.tcx(); - candidates.retain(|candidate| { - if let ImplCandidate(def_id) = candidate { - ty::ImplPolarity::Reservation == tcx.impl_polarity(*def_id) - || stack.obligation.polarity() == tcx.impl_polarity(*def_id) - || self.allow_negative_impls - } else { - true + let mut result = Vec::with_capacity(candidates.len()); + + for candidate in candidates { + // Respect const trait obligations + if self.is_trait_predicate_const(obligation.predicate.skip_binder()) { + match candidate { + // const impl + ImplCandidate(def_id) + if tcx.impl_constness(def_id) == hir::Constness::Const => {} + // const param + ParamCandidate(( + ty::ConstnessAnd { constness: ty::BoundConstness::ConstIfConst, .. }, + _, + )) => {} + // auto trait impl + AutoImplCandidate(..) => {} + // generator, this will raise error in other places + // or ignore error with const_async_blocks feature + GeneratorCandidate => {} + // FnDef where the function is const + FnPointerCandidate { is_const: true } => {} + ConstDropCandidate => {} + _ => { + // reject all other types of candidates + continue; + } + } } - }); + + if let ImplCandidate(def_id) = candidate { + if ty::ImplPolarity::Reservation == tcx.impl_polarity(def_id) + || obligation.polarity() == tcx.impl_polarity(def_id) + || self.allow_negative_impls + { + result.push(candidate); + } + } else { + result.push(candidate); + } + } + + result } /// filter_reservation_impls filter reservation impl for any goal as ambiguous @@ -1145,30 +1178,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { let tcx = self.tcx(); - // Respect const trait obligations - if self.is_trait_predicate_const(obligation.predicate.skip_binder()) { - match candidate { - // const impl - ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {} - // const param - ParamCandidate(( - ty::ConstnessAnd { constness: ty::BoundConstness::ConstIfConst, .. }, - _, - )) => {} - // auto trait impl - AutoImplCandidate(..) => {} - // generator, this will raise error in other places - // or ignore error with const_async_blocks feature - GeneratorCandidate => {} - // FnDef where the function is const - FnPointerCandidate { is_const: true } => {} - ConstDropCandidate => {} - _ => { - // reject all other types of candidates - return Err(Unimplemented); - } - } - } // Treat reservation impls as ambiguity. if let ImplCandidate(def_id) = candidate { if let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id) {