Skip to content

Commit d87c82e

Browse files
Rollup merge of rust-lang#87375 - fee1-dead:move-constness-to-traitpred, r=oli-obk
Try filtering out non-const impls when we expect const impls **TL;DR**: Associated types on const impls are now bounded; we now disallow calling a const function with bounds when the specified type param only has a non-const impl. r? `@oli-obk`
2 parents e5aca25 + b5e781a commit d87c82e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+517
-211
lines changed

compiler/rustc_hir/src/hir.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2709,6 +2709,15 @@ pub enum Constness {
27092709
NotConst,
27102710
}
27112711

2712+
impl fmt::Display for Constness {
2713+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2714+
f.write_str(match *self {
2715+
Self::Const => "const",
2716+
Self::NotConst => "non-const",
2717+
})
2718+
}
2719+
}
2720+
27122721
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
27132722
pub struct FnHeader {
27142723
pub unsafety: Unsafety,
@@ -3207,8 +3216,13 @@ impl<'hir> Node<'hir> {
32073216
}
32083217
}
32093218

3210-
/// Returns `Constness::Const` when this node is a const fn/impl.
3211-
pub fn constness(&self) -> Constness {
3219+
/// Returns `Constness::Const` when this node is a const fn/impl/item,
3220+
///
3221+
/// HACK(fee1-dead): or an associated type in a trait. This works because
3222+
/// only typeck cares about const trait predicates, so although the predicates
3223+
/// query would return const predicates when it does not need to be const,
3224+
/// it wouldn't have any effect.
3225+
pub fn constness_for_typeck(&self) -> Constness {
32123226
match self {
32133227
Node::Item(Item {
32143228
kind: ItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..),
@@ -3224,6 +3238,11 @@ impl<'hir> Node<'hir> {
32243238
})
32253239
| Node::Item(Item { kind: ItemKind::Impl(Impl { constness, .. }), .. }) => *constness,
32263240

3241+
Node::Item(Item { kind: ItemKind::Const(..), .. })
3242+
| Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. })
3243+
| Node::TraitItem(TraitItem { kind: TraitItemKind::Type(..), .. })
3244+
| Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const,
3245+
32273246
_ => Constness::NotConst,
32283247
}
32293248
}

compiler/rustc_infer/src/traits/engine.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::infer::InferCtxt;
22
use crate::traits::Obligation;
3+
use rustc_hir as hir;
34
use rustc_hir::def_id::DefId;
45
use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness};
56

@@ -49,11 +50,28 @@ pub trait TraitEngine<'tcx>: 'tcx {
4950
infcx: &InferCtxt<'_, 'tcx>,
5051
) -> Result<(), Vec<FulfillmentError<'tcx>>>;
5152

53+
fn select_all_with_constness_or_error(
54+
&mut self,
55+
infcx: &InferCtxt<'_, 'tcx>,
56+
_constness: hir::Constness,
57+
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
58+
self.select_all_or_error(infcx)
59+
}
60+
5261
fn select_where_possible(
5362
&mut self,
5463
infcx: &InferCtxt<'_, 'tcx>,
5564
) -> Result<(), Vec<FulfillmentError<'tcx>>>;
5665

66+
// FIXME this should not provide a default body for chalk as chalk should be updated
67+
fn select_with_constness_where_possible(
68+
&mut self,
69+
infcx: &InferCtxt<'_, 'tcx>,
70+
_constness: hir::Constness,
71+
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
72+
self.select_where_possible(infcx)
73+
}
74+
5775
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
5876
}
5977

compiler/rustc_infer/src/traits/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ impl Elaborator<'tcx> {
124124

125125
let bound_predicate = obligation.predicate.kind();
126126
match bound_predicate.skip_binder() {
127-
ty::PredicateKind::Trait(data, _) => {
127+
ty::PredicateKind::Trait(data) => {
128128
// Get predicates declared on the trait.
129129
let predicates = tcx.super_predicates_of(data.def_id());
130130

compiler/rustc_lint/src/traits.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
8787
let predicates = cx.tcx.explicit_predicates_of(item.def_id);
8888
for &(predicate, span) in predicates.predicates {
8989
let trait_predicate = match predicate.kind().skip_binder() {
90-
Trait(trait_predicate, _constness) => trait_predicate,
90+
Trait(trait_predicate) => trait_predicate,
9191
_ => continue,
9292
};
9393
let def_id = trait_predicate.trait_ref.def_id;

compiler/rustc_lint/src/unused.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
203203
let mut has_emitted = false;
204204
for &(predicate, _) in cx.tcx.explicit_item_bounds(def) {
205205
// We only look at the `DefId`, so it is safe to skip the binder here.
206-
if let ty::PredicateKind::Trait(ref poly_trait_predicate, _) =
206+
if let ty::PredicateKind::Trait(ref poly_trait_predicate) =
207207
predicate.kind().skip_binder()
208208
{
209209
let def_id = poly_trait_predicate.trait_ref.def_id;

compiler/rustc_middle/src/traits/select.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ use rustc_hir::def_id::DefId;
1212
use rustc_query_system::cache::Cache;
1313

1414
pub type SelectionCache<'tcx> = Cache<
15-
ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>,
15+
ty::ConstnessAnd<ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>>,
1616
SelectionResult<'tcx, SelectionCandidate<'tcx>>,
1717
>;
1818

1919
pub type EvaluationCache<'tcx> =
20-
Cache<ty::ParamEnvAnd<'tcx, ty::PolyTraitRef<'tcx>>, EvaluationResult>;
20+
Cache<ty::ParamEnvAnd<'tcx, ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>>, EvaluationResult>;
2121

2222
/// The selection process begins by considering all impls, where
2323
/// clauses, and so forth that might resolve an obligation. Sometimes

compiler/rustc_middle/src/ty/assoc.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ pub enum AssocItemContainer {
1616
}
1717

1818
impl AssocItemContainer {
19+
pub fn impl_def_id(&self) -> Option<DefId> {
20+
match *self {
21+
ImplContainer(id) => Some(id),
22+
_ => None,
23+
}
24+
}
25+
1926
/// Asserts that this is the `DefId` of an associated item declared
2027
/// in a trait, and returns the trait `DefId`.
2128
pub fn assert_trait(&self) -> DefId {

compiler/rustc_middle/src/ty/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2171,7 +2171,7 @@ impl<'tcx> TyCtxt<'tcx> {
21712171
let generic_predicates = self.super_predicates_of(trait_did);
21722172

21732173
for (predicate, _) in generic_predicates.predicates {
2174-
if let ty::PredicateKind::Trait(data, _) = predicate.kind().skip_binder() {
2174+
if let ty::PredicateKind::Trait(data) = predicate.kind().skip_binder() {
21752175
if set.insert(data.def_id()) {
21762176
stack.push(data.def_id());
21772177
}

compiler/rustc_middle/src/ty/error.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ impl<T> ExpectedFound<T> {
3333
#[derive(Clone, Debug, TypeFoldable)]
3434
pub enum TypeError<'tcx> {
3535
Mismatch,
36+
ConstnessMismatch(ExpectedFound<hir::Constness>),
3637
UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
3738
AbiMismatch(ExpectedFound<abi::Abi>),
3839
Mutability,
@@ -106,6 +107,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
106107
CyclicTy(_) => write!(f, "cyclic type of infinite size"),
107108
CyclicConst(_) => write!(f, "encountered a self-referencing constant"),
108109
Mismatch => write!(f, "types differ"),
110+
ConstnessMismatch(values) => {
111+
write!(f, "expected {} fn, found {} fn", values.expected, values.found)
112+
}
109113
UnsafetyMismatch(values) => {
110114
write!(f, "expected {} fn, found {} fn", values.expected, values.found)
111115
}
@@ -213,9 +217,11 @@ impl<'tcx> TypeError<'tcx> {
213217
pub fn must_include_note(&self) -> bool {
214218
use self::TypeError::*;
215219
match self {
216-
CyclicTy(_) | CyclicConst(_) | UnsafetyMismatch(_) | Mismatch | AbiMismatch(_)
217-
| FixedArraySize(_) | ArgumentSorts(..) | Sorts(_) | IntMismatch(_)
218-
| FloatMismatch(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false,
220+
CyclicTy(_) | CyclicConst(_) | UnsafetyMismatch(_) | ConstnessMismatch(_)
221+
| Mismatch | AbiMismatch(_) | FixedArraySize(_) | ArgumentSorts(..) | Sorts(_)
222+
| IntMismatch(_) | FloatMismatch(_) | VariadicMismatch(_) | TargetFeatureCast(_) => {
223+
false
224+
}
219225

220226
Mutability
221227
| ArgumentMutability(_)

compiler/rustc_middle/src/ty/flags.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ impl FlagComputation {
216216

217217
fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
218218
match atom {
219-
ty::PredicateKind::Trait(trait_pred, _constness) => {
219+
ty::PredicateKind::Trait(trait_pred) => {
220220
self.add_substs(trait_pred.trait_ref.substs);
221221
}
222222
ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ pub enum PredicateKind<'tcx> {
456456
/// A trait predicate will have `Constness::Const` if it originates
457457
/// from a bound on a `const fn` without the `?const` opt-out (e.g.,
458458
/// `const fn foobar<Foo: Bar>() {}`).
459-
Trait(TraitPredicate<'tcx>, Constness),
459+
Trait(TraitPredicate<'tcx>),
460460

461461
/// `where 'a: 'b`
462462
RegionOutlives(RegionOutlivesPredicate<'tcx>),
@@ -612,6 +612,11 @@ impl<'tcx> Predicate<'tcx> {
612612
#[derive(HashStable, TypeFoldable)]
613613
pub struct TraitPredicate<'tcx> {
614614
pub trait_ref: TraitRef<'tcx>,
615+
616+
/// A trait predicate will have `Constness::Const` if it originates
617+
/// from a bound on a `const fn` without the `?const` opt-out (e.g.,
618+
/// `const fn foobar<Foo: Bar>() {}`).
619+
pub constness: hir::Constness,
615620
}
616621

617622
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
@@ -745,24 +750,27 @@ impl ToPredicate<'tcx> for PredicateKind<'tcx> {
745750

746751
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
747752
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
748-
PredicateKind::Trait(ty::TraitPredicate { trait_ref: self.value }, self.constness)
749-
.to_predicate(tcx)
753+
PredicateKind::Trait(ty::TraitPredicate {
754+
trait_ref: self.value,
755+
constness: self.constness,
756+
})
757+
.to_predicate(tcx)
750758
}
751759
}
752760

753761
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
754762
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
755763
self.value
756764
.map_bound(|trait_ref| {
757-
PredicateKind::Trait(ty::TraitPredicate { trait_ref }, self.constness)
765+
PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: self.constness })
758766
})
759767
.to_predicate(tcx)
760768
}
761769
}
762770

763-
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitPredicate<'tcx>> {
771+
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
764772
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
765-
self.value.map_bound(|value| PredicateKind::Trait(value, self.constness)).to_predicate(tcx)
773+
self.map_bound(PredicateKind::Trait).to_predicate(tcx)
766774
}
767775
}
768776

@@ -788,8 +796,8 @@ impl<'tcx> Predicate<'tcx> {
788796
pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> {
789797
let predicate = self.kind();
790798
match predicate.skip_binder() {
791-
PredicateKind::Trait(t, constness) => {
792-
Some(ConstnessAnd { constness, value: predicate.rebind(t.trait_ref) })
799+
PredicateKind::Trait(t) => {
800+
Some(ConstnessAnd { constness: t.constness, value: predicate.rebind(t.trait_ref) })
793801
}
794802
PredicateKind::Projection(..)
795803
| PredicateKind::Subtype(..)

compiler/rustc_middle/src/ty/print/pretty.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ pub trait PrettyPrinter<'tcx>:
630630
for (predicate, _) in bounds {
631631
let predicate = predicate.subst(self.tcx(), substs);
632632
let bound_predicate = predicate.kind();
633-
if let ty::PredicateKind::Trait(pred, _) = bound_predicate.skip_binder() {
633+
if let ty::PredicateKind::Trait(pred) = bound_predicate.skip_binder() {
634634
let trait_ref = bound_predicate.rebind(pred.trait_ref);
635635
// Don't print +Sized, but rather +?Sized if absent.
636636
if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
@@ -2264,10 +2264,7 @@ define_print_and_forward_display! {
22642264

22652265
ty::PredicateKind<'tcx> {
22662266
match *self {
2267-
ty::PredicateKind::Trait(ref data, constness) => {
2268-
if let hir::Constness::Const = constness {
2269-
p!("const ");
2270-
}
2267+
ty::PredicateKind::Trait(ref data) => {
22712268
p!(print(data))
22722269
}
22732270
ty::PredicateKind::Subtype(predicate) => p!(print(predicate)),

compiler/rustc_middle/src/ty/relate.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,33 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
200200
}
201201
}
202202

203+
impl<'tcx> Relate<'tcx> for ast::Constness {
204+
fn relate<R: TypeRelation<'tcx>>(
205+
relation: &mut R,
206+
a: ast::Constness,
207+
b: ast::Constness,
208+
) -> RelateResult<'tcx, ast::Constness> {
209+
if a != b {
210+
Err(TypeError::ConstnessMismatch(expected_found(relation, a, b)))
211+
} else {
212+
Ok(a)
213+
}
214+
}
215+
}
216+
217+
impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::ConstnessAnd<T> {
218+
fn relate<R: TypeRelation<'tcx>>(
219+
relation: &mut R,
220+
a: ty::ConstnessAnd<T>,
221+
b: ty::ConstnessAnd<T>,
222+
) -> RelateResult<'tcx, ty::ConstnessAnd<T>> {
223+
Ok(ty::ConstnessAnd {
224+
constness: relation.relate(a.constness, b.constness)?,
225+
value: relation.relate(a.value, b.value)?,
226+
})
227+
}
228+
}
229+
203230
impl<'tcx> Relate<'tcx> for ast::Unsafety {
204231
fn relate<R: TypeRelation<'tcx>>(
205232
relation: &mut R,
@@ -767,7 +794,10 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
767794
a: ty::TraitPredicate<'tcx>,
768795
b: ty::TraitPredicate<'tcx>,
769796
) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> {
770-
Ok(ty::TraitPredicate { trait_ref: relation.relate(a.trait_ref, b.trait_ref)? })
797+
Ok(ty::TraitPredicate {
798+
trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
799+
constness: relation.relate(a.constness, b.constness)?,
800+
})
771801
}
772802
}
773803

compiler/rustc_middle/src/ty/structural_impls.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ impl fmt::Debug for ty::ParamConst {
155155

156156
impl fmt::Debug for ty::TraitPredicate<'tcx> {
157157
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158+
if let hir::Constness::Const = self.constness {
159+
write!(f, "const ")?;
160+
}
158161
write!(f, "TraitPredicate({:?})", self.trait_ref)
159162
}
160163
}
@@ -174,12 +177,7 @@ impl fmt::Debug for ty::Predicate<'tcx> {
174177
impl fmt::Debug for ty::PredicateKind<'tcx> {
175178
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176179
match *self {
177-
ty::PredicateKind::Trait(ref a, constness) => {
178-
if let hir::Constness::Const = constness {
179-
write!(f, "const ")?;
180-
}
181-
a.fmt(f)
182-
}
180+
ty::PredicateKind::Trait(ref a) => a.fmt(f),
183181
ty::PredicateKind::Subtype(ref pair) => pair.fmt(f),
184182
ty::PredicateKind::RegionOutlives(ref pair) => pair.fmt(f),
185183
ty::PredicateKind::TypeOutlives(ref pair) => pair.fmt(f),
@@ -366,7 +364,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialPredicate<'a> {
366364
impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
367365
type Lifted = ty::TraitPredicate<'tcx>;
368366
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::TraitPredicate<'tcx>> {
369-
tcx.lift(self.trait_ref).map(|trait_ref| ty::TraitPredicate { trait_ref })
367+
tcx.lift(self.trait_ref)
368+
.map(|trait_ref| ty::TraitPredicate { trait_ref, constness: self.constness })
370369
}
371370
}
372371

@@ -419,9 +418,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
419418
type Lifted = ty::PredicateKind<'tcx>;
420419
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
421420
match self {
422-
ty::PredicateKind::Trait(data, constness) => {
423-
tcx.lift(data).map(|data| ty::PredicateKind::Trait(data, constness))
424-
}
421+
ty::PredicateKind::Trait(data) => tcx.lift(data).map(ty::PredicateKind::Trait),
425422
ty::PredicateKind::Subtype(data) => tcx.lift(data).map(ty::PredicateKind::Subtype),
426423
ty::PredicateKind::RegionOutlives(data) => {
427424
tcx.lift(data).map(ty::PredicateKind::RegionOutlives)
@@ -584,6 +581,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
584581

585582
Some(match self {
586583
Mismatch => Mismatch,
584+
ConstnessMismatch(x) => ConstnessMismatch(x),
587585
UnsafetyMismatch(x) => UnsafetyMismatch(x),
588586
AbiMismatch(x) => AbiMismatch(x),
589587
Mutability => Mutability,

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,10 @@ impl<'tcx> PolyTraitRef<'tcx> {
876876
}
877877

878878
pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
879-
self.map_bound(|trait_ref| ty::TraitPredicate { trait_ref })
879+
self.map_bound(|trait_ref| ty::TraitPredicate {
880+
trait_ref,
881+
constness: hir::Constness::NotConst,
882+
})
880883
}
881884
}
882885

0 commit comments

Comments
 (0)