Skip to content

Commit 4c46ef7

Browse files
committed
Auto merge of #68140 - ecstatic-morse:const-trait-bound-opt-out, r=oli-obk
Implement `?const` opt-out for trait bounds For now, such bounds are treated exactly the same as unprefixed ones in all contexts. [RFC 2632](rust-lang/rfcs#2632) does not specify whether such bounds are forbidden outside of `const` contexts, so they are allowed at the moment. Prior to this PR, the constness of a trait bound/impl was stored in `TraitRef`. Now, the constness of an `impl` is stored in `ast::ItemKind::Impl` and the constness of a bound in `ast::TraitBoundModifer`. Additionally, constness of trait bounds is now stored in an additional field of `ty::Predicate::Trait`, and the combination of the constness of the item along with any `TraitBoundModifier` determines the constness of the bound in accordance with the RFC. Encoding the constness of impls at the `ty` level is left for a later PR. After a discussion in \#wg-grammar on Discord, it was decided that the grammar should not encode the mutual exclusivity of trait bound modifiers. The grammar for trait bound modifiers remains `[?const] [?]`. To encode this, I add a dummy variant to `ast::TraitBoundModifier` that is used when the syntax `?const ?` appears. This variant causes an error in AST validation and disappears during HIR lowering. cc #67794 r? @oli-obk
2 parents ce361fb + 6bd69a1 commit 4c46ef7

Some content is hidden

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

71 files changed

+494
-310
lines changed

src/librustc/traits/auto_trait.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,10 @@ impl AutoTraitFinder<'tcx> {
337337
&Err(SelectionError::Unimplemented) => {
338338
if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
339339
already_visited.remove(&pred);
340-
self.add_user_pred(&mut user_computed_preds, ty::Predicate::Trait(pred));
340+
self.add_user_pred(
341+
&mut user_computed_preds,
342+
ty::Predicate::Trait(pred, ast::Constness::NotConst),
343+
);
341344
predicates.push_back(pred);
342345
} else {
343346
debug!(
@@ -405,7 +408,7 @@ impl AutoTraitFinder<'tcx> {
405408
let mut should_add_new = true;
406409
user_computed_preds.retain(|&old_pred| {
407410
match (&new_pred, old_pred) {
408-
(&ty::Predicate::Trait(new_trait), ty::Predicate::Trait(old_trait)) => {
411+
(&ty::Predicate::Trait(new_trait, _), ty::Predicate::Trait(old_trait, _)) => {
409412
if new_trait.def_id() == old_trait.def_id() {
410413
let new_substs = new_trait.skip_binder().trait_ref.substs;
411414
let old_substs = old_trait.skip_binder().trait_ref.substs;
@@ -627,7 +630,7 @@ impl AutoTraitFinder<'tcx> {
627630
// We check this by calling is_of_param on the relevant types
628631
// from the various possible predicates
629632
match &predicate {
630-
&ty::Predicate::Trait(p) => {
633+
&ty::Predicate::Trait(p, _) => {
631634
if self.is_param_no_infer(p.skip_binder().trait_ref.substs)
632635
&& !only_projections
633636
&& is_new_pred

src/librustc/traits/engine.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::infer::InferCtxt;
22
use crate::traits::Obligation;
3-
use crate::ty::{self, ToPredicate, Ty, TyCtxt};
3+
use crate::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
44
use rustc_hir::def_id::DefId;
55

66
use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError};
@@ -33,7 +33,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
3333
cause,
3434
recursion_depth: 0,
3535
param_env,
36-
predicate: trait_ref.to_predicate(),
36+
predicate: trait_ref.without_const().to_predicate(),
3737
},
3838
);
3939
}

src/librustc/traits/error_reporting/mod.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ use crate::ty::error::ExpectedFound;
1919
use crate::ty::fast_reject;
2020
use crate::ty::fold::TypeFolder;
2121
use crate::ty::SubtypePredicate;
22-
use crate::ty::{self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
22+
use crate::ty::{
23+
self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
24+
};
2325

2426
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
2527
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
@@ -128,15 +130,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
128130
}
129131

130132
let (cond, error) = match (cond, error) {
131-
(&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) => (cond, error),
133+
(&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
132134
_ => {
133135
// FIXME: make this work in other cases too.
134136
return false;
135137
}
136138
};
137139

138140
for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
139-
if let ty::Predicate::Trait(implication) = implication {
141+
if let ty::Predicate::Trait(implication, _) = implication {
140142
let error = error.to_poly_trait_ref();
141143
let implication = implication.to_poly_trait_ref();
142144
// FIXME: I'm just not taking associated types at all here.
@@ -528,7 +530,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
528530
return;
529531
}
530532
match obligation.predicate {
531-
ty::Predicate::Trait(ref trait_predicate) => {
533+
ty::Predicate::Trait(ref trait_predicate, _) => {
532534
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
533535

534536
if self.tcx.sess.has_errors() && trait_predicate.references_error() {
@@ -581,7 +583,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
581583
"{}",
582584
message.unwrap_or_else(|| format!(
583585
"the trait bound `{}` is not satisfied{}",
584-
trait_ref.to_predicate(),
586+
trait_ref.without_const().to_predicate(),
585587
post_message,
586588
))
587589
);
@@ -693,7 +695,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
693695
trait_pred
694696
});
695697
let unit_obligation = Obligation {
696-
predicate: ty::Predicate::Trait(predicate),
698+
predicate: ty::Predicate::Trait(
699+
predicate,
700+
ast::Constness::NotConst,
701+
),
697702
..obligation.clone()
698703
};
699704
if self.predicate_may_hold(&unit_obligation) {
@@ -986,7 +991,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
986991
) -> PredicateObligation<'tcx> {
987992
let new_trait_ref =
988993
ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
989-
Obligation::new(cause, param_env, new_trait_ref.to_predicate())
994+
Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
990995
}
991996
}
992997

@@ -1074,7 +1079,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10741079
}
10751080

10761081
let mut err = match predicate {
1077-
ty::Predicate::Trait(ref data) => {
1082+
ty::Predicate::Trait(ref data, _) => {
10781083
let trait_ref = data.to_poly_trait_ref();
10791084
let self_ty = trait_ref.self_ty();
10801085
debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
@@ -1267,8 +1272,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12671272
)
12681273
.value;
12691274

1270-
let obligation =
1271-
Obligation::new(ObligationCause::dummy(), param_env, cleaned_pred.to_predicate());
1275+
let obligation = Obligation::new(
1276+
ObligationCause::dummy(),
1277+
param_env,
1278+
cleaned_pred.without_const().to_predicate(),
1279+
);
12721280

12731281
self.predicate_may_hold(&obligation)
12741282
})

src/librustc/traits/error_reporting/suggestions.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use super::{
66
use crate::infer::InferCtxt;
77
use crate::traits::object_safety::object_safety_violations;
88
use crate::ty::TypeckTables;
9-
use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
9+
use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
1010

1111
use rustc_errors::{
1212
error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
@@ -48,7 +48,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
4848
} else {
4949
" where"
5050
},
51-
trait_ref.to_predicate(),
51+
trait_ref.without_const().to_predicate(),
5252
),
5353
Applicability::MachineApplicable,
5454
);
@@ -338,8 +338,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
338338
let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
339339
let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
340340
let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
341-
let new_obligation =
342-
Obligation::new(ObligationCause::dummy(), param_env, new_trait_ref.to_predicate());
341+
let new_obligation = Obligation::new(
342+
ObligationCause::dummy(),
343+
param_env,
344+
new_trait_ref.without_const().to_predicate(),
345+
);
343346
if self.predicate_must_hold_modulo_regions(&new_obligation) {
344347
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
345348
// We have a very specific type of error, where just borrowing this argument
@@ -1120,7 +1123,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11201123
// the type. The last generator has information about where the bound was introduced. At
11211124
// least one generator should be present for this diagnostic to be modified.
11221125
let (mut trait_ref, mut target_ty) = match obligation.predicate {
1123-
ty::Predicate::Trait(p) => {
1126+
ty::Predicate::Trait(p, _) => {
11241127
(Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
11251128
}
11261129
_ => (None, None),
@@ -1543,7 +1546,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15431546
err.note(&format!("required because it appears within the type `{}`", ty));
15441547
obligated_types.push(ty);
15451548

1546-
let parent_predicate = parent_trait_ref.to_predicate();
1549+
let parent_predicate = parent_trait_ref.without_const().to_predicate();
15471550
if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
15481551
self.note_obligation_cause_code(
15491552
err,
@@ -1560,7 +1563,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15601563
parent_trait_ref.print_only_trait_path(),
15611564
parent_trait_ref.skip_binder().self_ty()
15621565
));
1563-
let parent_predicate = parent_trait_ref.to_predicate();
1566+
let parent_predicate = parent_trait_ref.without_const().to_predicate();
15641567
self.note_obligation_cause_code(
15651568
err,
15661569
&parent_predicate,

src/librustc/traits/fulfill.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
311311
}
312312

313313
match obligation.predicate {
314-
ty::Predicate::Trait(ref data) => {
314+
ty::Predicate::Trait(ref data, _) => {
315315
let trait_obligation = obligation.with(data.clone());
316316

317317
if data.is_global() {

src/librustc/traits/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::mir::interpret::ErrorHandled;
2929
use crate::ty::error::{ExpectedFound, TypeError};
3030
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
3131
use crate::ty::subst::{InternalSubsts, SubstsRef};
32-
use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt};
32+
use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt, WithConstness};
3333
use crate::util::common::ErrorReported;
3434
use chalk_engine;
3535
use rustc_hir as hir;
@@ -732,7 +732,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
732732
param_env,
733733
cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),
734734
recursion_depth: 0,
735-
predicate: trait_ref.to_predicate(),
735+
predicate: trait_ref.without_const().to_predicate(),
736736
};
737737

738738
let result = infcx.predicate_must_hold_modulo_regions(&obligation);

src/librustc/traits/object_safety.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use super::elaborate_predicates;
1212

1313
use crate::traits::{self, Obligation, ObligationCause};
1414
use crate::ty::subst::{InternalSubsts, Subst};
15-
use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable};
15+
use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
1616
use rustc_hir as hir;
1717
use rustc_hir::def_id::DefId;
1818
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
@@ -234,7 +234,7 @@ fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_o
234234
.map(|(predicate, _)| predicate.subst_supertrait(tcx, &trait_ref))
235235
.any(|predicate| {
236236
match predicate {
237-
ty::Predicate::Trait(ref data) => {
237+
ty::Predicate::Trait(ref data, _) => {
238238
// In the case of a trait predicate, we can skip the "self" type.
239239
data.skip_binder().input_types().skip(1).any(has_self_ty)
240240
}
@@ -285,7 +285,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
285285
let predicates = tcx.predicates_of(def_id);
286286
let predicates = predicates.instantiate_identity(tcx).predicates;
287287
elaborate_predicates(tcx, predicates).any(|predicate| match predicate {
288-
ty::Predicate::Trait(ref trait_pred) => {
288+
ty::Predicate::Trait(ref trait_pred, _) => {
289289
trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
290290
}
291291
ty::Predicate::Projection(..)
@@ -585,6 +585,7 @@ fn receiver_is_dispatchable<'tcx>(
585585
def_id: unsize_did,
586586
substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
587587
}
588+
.without_const()
588589
.to_predicate();
589590

590591
// U: Trait<Arg1, ..., ArgN>
@@ -598,7 +599,7 @@ fn receiver_is_dispatchable<'tcx>(
598599
}
599600
});
600601

601-
ty::TraitRef { def_id: unsize_did, substs }.to_predicate()
602+
ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate()
602603
};
603604

604605
let caller_bounds: Vec<Predicate<'tcx>> = param_env
@@ -620,6 +621,7 @@ fn receiver_is_dispatchable<'tcx>(
620621
def_id: dispatch_from_dyn_did,
621622
substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
622623
}
624+
.without_const()
623625
.to_predicate();
624626

625627
Obligation::new(ObligationCause::dummy(), param_env, predicate)

src/librustc/traits/project.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1616
use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
1717
use crate::ty::fold::{TypeFoldable, TypeFolder};
1818
use crate::ty::subst::{InternalSubsts, Subst};
19-
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
19+
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
2020
use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
2121
use rustc_hir::def_id::DefId;
2222
use rustc_macros::HashStable;
@@ -738,7 +738,12 @@ fn get_paranoid_cache_value_obligation<'a, 'tcx>(
738738
depth: usize,
739739
) -> PredicateObligation<'tcx> {
740740
let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
741-
Obligation { cause, recursion_depth: depth, param_env, predicate: trait_ref.to_predicate() }
741+
Obligation {
742+
cause,
743+
recursion_depth: depth,
744+
param_env,
745+
predicate: trait_ref.without_const().to_predicate(),
746+
}
742747
}
743748

744749
/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
@@ -772,7 +777,7 @@ fn normalize_to_error<'a, 'tcx>(
772777
cause,
773778
recursion_depth: depth,
774779
param_env,
775-
predicate: trait_ref.to_predicate(),
780+
predicate: trait_ref.without_const().to_predicate(),
776781
};
777782
let tcx = selcx.infcx().tcx;
778783
let def_id = projection_ty.item_def_id;

src/librustc/traits/query/type_op/prove_predicate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
2424
// `&T`, accounts for about 60% percentage of the predicates
2525
// we have to prove. No need to canonicalize and all that for
2626
// such cases.
27-
if let Predicate::Trait(trait_ref) = key.value.predicate {
27+
if let Predicate::Trait(trait_ref, _) = key.value.predicate {
2828
if let Some(sized_def_id) = tcx.lang_items().sized_trait() {
2929
if trait_ref.def_id() == sized_def_id {
3030
if trait_ref.skip_binder().self_ty().is_trivially_sized(tcx) {

src/librustc/traits/select.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use crate::middle::lang_items;
3737
use crate::ty::fast_reject;
3838
use crate::ty::relate::TypeRelation;
3939
use crate::ty::subst::{Subst, SubstsRef};
40-
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
40+
use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
4141
use rustc_hir::def_id::DefId;
4242

4343
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -51,7 +51,7 @@ use std::cmp;
5151
use std::fmt::{self, Display};
5252
use std::iter;
5353
use std::rc::Rc;
54-
use syntax::attr;
54+
use syntax::{ast, attr};
5555

5656
pub struct SelectionContext<'cx, 'tcx> {
5757
infcx: &'cx InferCtxt<'cx, 'tcx>,
@@ -718,7 +718,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
718718
}
719719

720720
match obligation.predicate {
721-
ty::Predicate::Trait(ref t) => {
721+
ty::Predicate::Trait(ref t, _) => {
722722
debug_assert!(!t.has_escaping_bound_vars());
723723
let obligation = obligation.with(t.clone());
724724
self.evaluate_trait_predicate_recursively(previous_stack, obligation)
@@ -945,7 +945,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
945945
// trait refs. This is important because it's only a cycle
946946
// if the regions match exactly.
947947
let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth);
948-
let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate));
948+
let cycle = cycle.map(|stack| {
949+
ty::Predicate::Trait(stack.obligation.predicate, ast::Constness::NotConst)
950+
});
949951
if self.coinductive_match(cycle) {
950952
debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref);
951953
Some(EvaluatedToOk)
@@ -1060,7 +1062,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10601062

10611063
fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
10621064
let result = match predicate {
1063-
ty::Predicate::Trait(ref data) => self.tcx().trait_is_auto(data.def_id()),
1065+
ty::Predicate::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()),
10641066
_ => false,
10651067
};
10661068
debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
@@ -3366,7 +3368,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
33663368
tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
33673369
tcx.mk_substs_trait(source, &[]),
33683370
);
3369-
nested.push(predicate_to_obligation(tr.to_predicate()));
3371+
nested.push(predicate_to_obligation(tr.without_const().to_predicate()));
33703372

33713373
// If the type is `Foo + 'a`, ensure that the type
33723374
// being cast to `Foo + 'a` outlives `'a`:

0 commit comments

Comments
 (0)