Skip to content

Commit 136eaa1

Browse files
committed
Auto merge of #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 fa26929 + 74627c1 commit 136eaa1

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

Diff for: compiler/rustc_hir/src/hir.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -2751,6 +2751,15 @@ pub enum Constness {
27512751
NotConst,
27522752
}
27532753

2754+
impl fmt::Display for Constness {
2755+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2756+
f.write_str(match *self {
2757+
Self::Const => "const",
2758+
Self::NotConst => "non-const",
2759+
})
2760+
}
2761+
}
2762+
27542763
#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
27552764
pub struct FnHeader {
27562765
pub unsafety: Unsafety,
@@ -3252,8 +3261,13 @@ impl<'hir> Node<'hir> {
32523261
}
32533262
}
32543263

3255-
/// Returns `Constness::Const` when this node is a const fn/impl.
3256-
pub fn constness(&self) -> Constness {
3264+
/// Returns `Constness::Const` when this node is a const fn/impl/item,
3265+
///
3266+
/// HACK(fee1-dead): or an associated type in a trait. This works because
3267+
/// only typeck cares about const trait predicates, so although the predicates
3268+
/// query would return const predicates when it does not need to be const,
3269+
/// it wouldn't have any effect.
3270+
pub fn constness_for_typeck(&self) -> Constness {
32573271
match self {
32583272
Node::Item(Item {
32593273
kind: ItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..),
@@ -3269,6 +3283,11 @@ impl<'hir> Node<'hir> {
32693283
})
32703284
| Node::Item(Item { kind: ItemKind::Impl(Impl { constness, .. }), .. }) => *constness,
32713285

3286+
Node::Item(Item { kind: ItemKind::Const(..), .. })
3287+
| Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. })
3288+
| Node::TraitItem(TraitItem { kind: TraitItemKind::Type(..), .. })
3289+
| Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const,
3290+
32723291
_ => Constness::NotConst,
32733292
}
32743293
}

Diff for: compiler/rustc_infer/src/traits/engine.rs

+18
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

Diff for: compiler/rustc_infer/src/traits/util.rs

+1-1
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

Diff for: compiler/rustc_lint/src/traits.rs

+1-1
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;

Diff for: compiler/rustc_lint/src/unused.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
211211
let mut has_emitted = false;
212212
for &(predicate, _) in cx.tcx.explicit_item_bounds(def) {
213213
// We only look at the `DefId`, so it is safe to skip the binder here.
214-
if let ty::PredicateKind::Trait(ref poly_trait_predicate, _) =
214+
if let ty::PredicateKind::Trait(ref poly_trait_predicate) =
215215
predicate.kind().skip_binder()
216216
{
217217
let def_id = poly_trait_predicate.trait_ref.def_id;

Diff for: compiler/rustc_middle/src/traits/select.rs

+2-2
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

Diff for: compiler/rustc_middle/src/ty/assoc.rs

+7
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 {

Diff for: compiler/rustc_middle/src/ty/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2169,7 +2169,7 @@ impl<'tcx> TyCtxt<'tcx> {
21692169
let generic_predicates = self.super_predicates_of(trait_did);
21702170

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

Diff for: compiler/rustc_middle/src/ty/error.rs

+9-3
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(_)

Diff for: compiler/rustc_middle/src/ty/flags.rs

+1-1
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)) => {

Diff for: compiler/rustc_middle/src/ty/mod.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ pub enum PredicateKind<'tcx> {
461461
/// A trait predicate will have `Constness::Const` if it originates
462462
/// from a bound on a `const fn` without the `?const` opt-out (e.g.,
463463
/// `const fn foobar<Foo: Bar>() {}`).
464-
Trait(TraitPredicate<'tcx>, Constness),
464+
Trait(TraitPredicate<'tcx>),
465465

466466
/// `where 'a: 'b`
467467
RegionOutlives(RegionOutlivesPredicate<'tcx>),
@@ -617,6 +617,11 @@ impl<'tcx> Predicate<'tcx> {
617617
#[derive(HashStable, TypeFoldable)]
618618
pub struct TraitPredicate<'tcx> {
619619
pub trait_ref: TraitRef<'tcx>,
620+
621+
/// A trait predicate will have `Constness::Const` if it originates
622+
/// from a bound on a `const fn` without the `?const` opt-out (e.g.,
623+
/// `const fn foobar<Foo: Bar>() {}`).
624+
pub constness: hir::Constness,
620625
}
621626

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

751756
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
752757
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
753-
PredicateKind::Trait(ty::TraitPredicate { trait_ref: self.value }, self.constness)
754-
.to_predicate(tcx)
758+
PredicateKind::Trait(ty::TraitPredicate {
759+
trait_ref: self.value,
760+
constness: self.constness,
761+
})
762+
.to_predicate(tcx)
755763
}
756764
}
757765

758766
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
759767
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
760768
self.value
761769
.map_bound(|trait_ref| {
762-
PredicateKind::Trait(ty::TraitPredicate { trait_ref }, self.constness)
770+
PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: self.constness })
763771
})
764772
.to_predicate(tcx)
765773
}
766774
}
767775

768-
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitPredicate<'tcx>> {
776+
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
769777
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
770-
self.value.map_bound(|value| PredicateKind::Trait(value, self.constness)).to_predicate(tcx)
778+
self.map_bound(PredicateKind::Trait).to_predicate(tcx)
771779
}
772780
}
773781

@@ -793,8 +801,8 @@ impl<'tcx> Predicate<'tcx> {
793801
pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> {
794802
let predicate = self.kind();
795803
match predicate.skip_binder() {
796-
PredicateKind::Trait(t, constness) => {
797-
Some(ConstnessAnd { constness, value: predicate.rebind(t.trait_ref) })
804+
PredicateKind::Trait(t) => {
805+
Some(ConstnessAnd { constness: t.constness, value: predicate.rebind(t.trait_ref) })
798806
}
799807
PredicateKind::Projection(..)
800808
| PredicateKind::Subtype(..)

Diff for: compiler/rustc_middle/src/ty/print/pretty.rs

+2-5
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)),

Diff for: compiler/rustc_middle/src/ty/relate.rs

+31-1
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

Diff for: compiler/rustc_middle/src/ty/structural_impls.rs

+8-10
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,

Diff for: compiler/rustc_middle/src/ty/sty.rs

+4-1
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)