make projection bounds with const bounds satisfy const

This commit is contained in:
Deadbeef 2022-09-18 17:38:18 +00:00
parent 4af79ccd5e
commit ee96ae0a32
5 changed files with 33 additions and 15 deletions

View file

@ -119,8 +119,9 @@ pub enum SelectionCandidate<'tcx> {
/// This is a trait matching with a projected type as `Self`, and we found /// This is a trait matching with a projected type as `Self`, and we found
/// an applicable bound in the trait definition. The `usize` is an index /// an applicable bound in the trait definition. The `usize` is an index
/// into the list returned by `tcx.item_bounds`. /// into the list returned by `tcx.item_bounds`. The constness is the
ProjectionCandidate(usize), /// constness of the bound in the trait.
ProjectionCandidate(usize, ty::BoundConstness),
/// Implementation of a `Fn`-family trait by one of the anonymous types /// Implementation of a `Fn`-family trait by one of the anonymous types
/// generated for an `||` expression. /// generated for an `||` expression.

View file

@ -362,7 +362,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.infcx .infcx
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); .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 /// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller

View file

@ -68,10 +68,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplSource::AutoImpl(data) ImplSource::AutoImpl(data)
} }
ProjectionCandidate(idx) => { ProjectionCandidate(idx, constness) => {
let obligations = self.confirm_projection_candidate(obligation, idx)?; let obligations = self.confirm_projection_candidate(obligation, idx)?;
// FIXME(jschievink): constness ImplSource::Param(obligations, constness)
ImplSource::Param(obligations, ty::BoundConstness::NotConst)
} }
ObjectCandidate(idx) => { ObjectCandidate(idx) => {

View file

@ -1192,6 +1192,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplCandidate(def_id) if tcx.constness(def_id) == hir::Constness::Const => {} ImplCandidate(def_id) if tcx.constness(def_id) == hir::Constness::Const => {}
// const param // const param
ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {} ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {}
// const projection
ProjectionCandidate(_, ty::BoundConstness::ConstIfConst) => {}
// auto trait impl // auto trait impl
AutoImplCandidate(..) => {} AutoImplCandidate(..) => {}
// generator, this will raise error in other places // generator, this will raise error in other places
@ -1399,7 +1401,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn match_projection_obligation_against_definition_bounds( fn match_projection_obligation_against_definition_bounds(
&mut self, &mut self,
obligation: &TraitObligation<'tcx>, 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 poly_trait_predicate = self.infcx().resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate = let placeholder_trait_predicate =
self.infcx().replace_bound_vars_with_placeholders(poly_trait_predicate); self.infcx().replace_bound_vars_with_placeholders(poly_trait_predicate);
@ -1447,7 +1449,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => false, _ => false,
} }
}) { }) {
return Some(idx); return Some((idx, pred.constness));
} }
} }
None None
@ -1683,9 +1685,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinCandidate { .. } | BuiltinCandidate { .. }
| TraitAliasCandidate(..) | TraitAliasCandidate(..)
| ObjectCandidate(_) | ObjectCandidate(_)
| ProjectionCandidate(_), | ProjectionCandidate(..),
) => !is_global(cand), ) => !is_global(cand),
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => { (ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref cand)) => {
// Prefer these to a global where-clause bound // Prefer these to a global where-clause bound
// (see issue #50825). // (see issue #50825).
is_global(cand) is_global(cand)
@ -1707,20 +1709,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
is_global(cand) && other.evaluation.must_apply_modulo_regions() is_global(cand) && other.evaluation.must_apply_modulo_regions()
} }
(ProjectionCandidate(i), ProjectionCandidate(j)) (ProjectionCandidate(i, _), ProjectionCandidate(j, _))
| (ObjectCandidate(i), ObjectCandidate(j)) => { | (ObjectCandidate(i), ObjectCandidate(j)) => {
// Arbitrarily pick the lower numbered candidate for backwards // Arbitrarily pick the lower numbered candidate for backwards
// compatibility reasons. Don't let this affect inference. // compatibility reasons. Don't let this affect inference.
i < j && !needs_infer i < j && !needs_infer
} }
(ObjectCandidate(_), ProjectionCandidate(_)) (ObjectCandidate(_), ProjectionCandidate(..))
| (ProjectionCandidate(_), ObjectCandidate(_)) => { | (ProjectionCandidate(..), ObjectCandidate(_)) => {
bug!("Have both object and projection candidate") bug!("Have both object and projection candidate")
} }
// Arbitrarily give projection and object candidates priority. // Arbitrarily give projection and object candidates priority.
( (
ObjectCandidate(_) | ProjectionCandidate(_), ObjectCandidate(_) | ProjectionCandidate(..),
ImplCandidate(..) ImplCandidate(..)
| ClosureCandidate | ClosureCandidate
| GeneratorCandidate | GeneratorCandidate
@ -1742,7 +1744,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| TraitUpcastingUnsizeCandidate(_) | TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { .. } | BuiltinCandidate { .. }
| TraitAliasCandidate(..), | TraitAliasCandidate(..),
ObjectCandidate(_) | ProjectionCandidate(_), ObjectCandidate(_) | ProjectionCandidate(..),
) => false, ) => false,
(&ImplCandidate(other_def), &ImplCandidate(victim_def)) => { (&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {

View file

@ -0,0 +1,14 @@
// check-pass
#![feature(const_trait_impl)]
#[const_trait]
trait Foo {
type Assoc: ~const Foo;
fn foo() {}
}
const fn foo<T: ~const Foo>() {
<T as Foo>::Assoc::foo();
}
fn main() {}