Skip to content

Commit

Permalink
Fully fledged Clause type
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jun 19, 2023
1 parent fca56a8 commit 21226ee
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 96 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -945,8 +945,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {

let mut trait_bounds = vec![];
let mut projection_bounds = vec![];
for (clause, span) in bounds.predicates() {
let pred: ty::Predicate<'tcx> = clause.to_predicate(tcx);
for (clause, span) in bounds.clauses() {
let pred: ty::Predicate<'tcx> = clause.as_predicate();
let bound_pred = pred.kind();
match bound_pred.skip_binder() {
ty::PredicateKind::Clause(clause) => match clause {
Expand Down
43 changes: 19 additions & 24 deletions compiler/rustc_hir_analysis/src/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
//! `ty` form from the HIR.

use rustc_hir::LangItem;
use rustc_middle::ty::Binder;
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
use rustc_span::Span;

Expand All @@ -24,62 +23,58 @@ use rustc_span::Span;
/// include the self type (e.g., `trait_bounds`) but in others we do not
#[derive(Default, PartialEq, Eq, Clone, Debug)]
pub struct Bounds<'tcx> {
pub predicates: Vec<(Binder<'tcx, ty::ClauseKind<'tcx>>, Span)>,
pub clauses: Vec<(ty::Clause<'tcx>, Span)>,
}

impl<'tcx> Bounds<'tcx> {
pub fn push_region_bound(
&mut self,
_tcx: TyCtxt<'tcx>,
tcx: TyCtxt<'tcx>,
region: ty::PolyTypeOutlivesPredicate<'tcx>,
span: Span,
) {
self.predicates.push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)), span));
self.clauses
.push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).to_predicate(tcx), span));
}

pub fn push_trait_bound(
&mut self,
_tcx: TyCtxt<'tcx>,
tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
span: Span,
constness: ty::BoundConstness,
polarity: ty::ImplPolarity,
) {
self.predicates.push((
trait_ref.map_bound(|trait_ref| {
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness, polarity })
}),
self.clauses.push((
trait_ref
.map_bound(|trait_ref| {
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness, polarity })
})
.to_predicate(tcx),
span,
));
}

pub fn push_projection_bound(
&mut self,
_tcx: TyCtxt<'tcx>,
tcx: TyCtxt<'tcx>,
projection: ty::PolyProjectionPredicate<'tcx>,
span: Span,
) {
self.predicates.push((projection.map_bound(|proj| ty::ClauseKind::Projection(proj)), span));
self.clauses.push((
projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).to_predicate(tcx),
span,
));
}

pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
self.predicates.insert(
0,
(
ty::Binder::dummy(ty::ClauseKind::Trait(
trait_ref.without_const().to_predicate(tcx),
)),
span,
),
);
self.clauses.insert(0, (trait_ref.to_predicate(tcx), span));
}

pub fn predicates(
&self,
) -> impl Iterator<Item = (Binder<'tcx, ty::ClauseKind<'tcx>>, Span)> + '_ {
self.predicates.iter().cloned()
pub fn clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ {
self.clauses.iter().cloned()
}
}
10 changes: 4 additions & 6 deletions compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::astconv::{AstConv, OnlySelfBounds};
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::Span;
Expand Down Expand Up @@ -49,8 +48,8 @@ fn associated_type_bounds<'tcx>(

let all_bounds = tcx.arena.alloc_from_iter(
bounds
.predicates()
.map(|(clause, span)| (clause.to_predicate(tcx), span))
.clauses()
.map(|(clause, span)| (clause.as_predicate(), span))
.chain(bounds_from_parent),
);
debug!(
Expand Down Expand Up @@ -80,9 +79,8 @@ fn opaque_type_bounds<'tcx>(
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
debug!(?bounds);

tcx.arena.alloc_from_iter(
bounds.predicates().map(|(clause, span)| (clause.to_predicate(tcx), span)),
)
tcx.arena
.alloc_from_iter(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)))
})
}

Expand Down
20 changes: 9 additions & 11 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
predicates.extend(
icx.astconv()
.compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false))
.predicates()
.map(|(clause, span)| (clause.to_predicate(tcx), span)),
.clauses()
.map(|(clause, span)| (clause.as_predicate(), span)),
);
}

Expand Down Expand Up @@ -176,9 +176,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
param.span,
);
trace!(?bounds);
predicates.extend(
bounds.predicates().map(|(clause, span)| (clause.to_predicate(tcx), span)),
);
predicates
.extend(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)));
trace!(?predicates);
}
GenericParamKind::Const { .. } => {
Expand Down Expand Up @@ -237,9 +236,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
bound_vars,
OnlySelfBounds(false),
);
predicates.extend(
bounds.predicates().map(|(clause, span)| (clause.to_predicate(tcx), span)),
);
predicates
.extend(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)));
}

hir::WherePredicate::RegionPredicate(region_pred) => {
Expand Down Expand Up @@ -669,8 +667,8 @@ pub(super) fn implied_predicates_with_filter(
// Combine the two lists to form the complete set of superbounds:
let implied_bounds = &*tcx.arena.alloc_from_iter(
superbounds
.predicates()
.map(|(clause, span)| (clause.to_predicate(tcx), span))
.clauses()
.map(|(clause, span)| (clause.as_predicate(), span))
.chain(where_bounds_that_match),
);
debug!(?implied_bounds);
Expand Down Expand Up @@ -831,7 +829,7 @@ impl<'tcx> ItemCtxt<'tcx> {
);
}

bounds.predicates().map(|(clause, span)| (clause.to_predicate(self.tcx), span)).collect()
bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)).collect()
}

#[instrument(level = "trace", skip(self))]
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_infer/src/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,26 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) {
}
}

impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> {
fn predicate(&self) -> ty::Predicate<'tcx> {
self.as_predicate()
}

fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
predicate.as_clause().unwrap()
}

fn child_with_derived_cause(
&self,
predicate: ty::Predicate<'tcx>,
_span: Span,
_parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
_index: usize,
) -> Self {
predicate.as_clause().unwrap()
}
}

pub fn elaborate<'tcx, O: Elaboratable<'tcx>>(
tcx: TyCtxt<'tcx>,
obligations: impl IntoIterator<Item = O>,
Expand Down
113 changes: 68 additions & 45 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,42 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
}
}

/// TODO: doc
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>);

impl<'tcx> Clause<'tcx> {
pub fn as_predicate(self) -> Predicate<'tcx> {
Predicate(self.0)
}

pub fn kind(self) -> Binder<'tcx, ClauseKind<'tcx>> {
self.0.internee.map_bound(|kind| match kind {
PredicateKind::Clause(clause) => clause,
_ => unreachable!(),
})
}

pub fn as_trait_clause(self) -> Option<Binder<'tcx, TraitPredicate<'tcx>>> {
let clause = self.kind();
if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() {
Some(clause.rebind(trait_clause))
} else {
None
}
}

pub fn as_projection_clause(self) -> Option<Binder<'tcx, ProjectionPredicate<'tcx>>> {
let clause = self.kind();
if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() {
Some(clause.rebind(projection_clause))
} else {
None
}
}
}

#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
/// A clause is something that can appear in where bounds or be inferred
Expand Down Expand Up @@ -592,24 +628,6 @@ pub enum ClauseKind<'tcx> {
ConstEvaluatable(ty::Const<'tcx>),
}

impl<'tcx> Binder<'tcx, ClauseKind<'tcx>> {
pub fn as_trait_clause(self) -> Option<Binder<'tcx, TraitPredicate<'tcx>>> {
if let ty::ClauseKind::Trait(trait_clause) = self.skip_binder() {
Some(self.rebind(trait_clause))
} else {
None
}
}

pub fn as_projection_clause(self) -> Option<Binder<'tcx, ProjectionPredicate<'tcx>>> {
if let ty::ClauseKind::Projection(projection_clause) = self.skip_binder() {
Some(self.rebind(projection_clause))
} else {
None
}
}
}

#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub enum PredicateKind<'tcx> {
Expand Down Expand Up @@ -1222,21 +1240,25 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> {
}
}

impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause()
}
}

impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
ty::Binder::dummy(self).to_predicate(tcx)
}
}

impl<'tcx> ToPredicate<'tcx, Binder<'tcx, ClauseKind<'tcx>>> for TraitRef<'tcx> {
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, ClauseKind<'tcx>> {
Binder::dummy(ClauseKind::Trait(TraitPredicate {
trait_ref: self,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}))
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}

Expand All @@ -1248,9 +1270,9 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
}
}

impl<'tcx> ToPredicate<'tcx, Binder<'tcx, ClauseKind<'tcx>>> for Binder<'tcx, TraitRef<'tcx>> {
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Binder<'tcx, ClauseKind<'tcx>> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
pred.to_predicate(tcx)
}
Expand Down Expand Up @@ -1285,9 +1307,10 @@ impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
}
}

impl<'tcx> ToPredicate<'tcx, Binder<'tcx, ClauseKind<'tcx>>> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, ClauseKind<'tcx>> {
self.map_bound(|p| ClauseKind::Trait(p))
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}

Expand All @@ -1309,9 +1332,10 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
}
}

impl<'tcx> ToPredicate<'tcx, Binder<'tcx, ClauseKind<'tcx>>> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, ClauseKind<'tcx>> {
self.map_bound(|p| ClauseKind::Projection(p))
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}

Expand Down Expand Up @@ -1385,18 +1409,17 @@ impl<'tcx> Predicate<'tcx> {
}
}

pub fn as_clause(self) -> Option<Binder<'tcx, ClauseKind<'tcx>>> {
let predicate = self.kind();
match predicate.skip_binder() {
PredicateKind::Clause(clause) => Some(predicate.rebind(clause)),
PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
| PredicateKind::ConstEquate(..)
| PredicateKind::Ambiguous
| PredicateKind::TypeWellFormedFromEnv(..) => None,
pub fn as_clause(self) -> Option<Clause<'tcx>> {
match self.kind().skip_binder() {
PredicateKind::Clause(..) => Some(self.expect_clause()),
_ => None,
}
}

pub fn expect_clause(self) -> Clause<'tcx> {
match self.kind().skip_binder() {
PredicateKind::Clause(..) => Clause(self.0),
_ => bug!(),
}
}
}
Expand Down
Loading

0 comments on commit 21226ee

Please sign in to comment.