Skip to content

Commit 4c4563c

Browse files
committed
Auto merge of #68140 - ecstatic-morse:const-trait-bound-opt-out, r=<try>
Support `?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. cc #67794 r? @oli-obk
2 parents f363745 + c37571d commit 4c4563c

File tree

38 files changed

+155
-202
lines changed

38 files changed

+155
-202
lines changed

src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -215,14 +215,10 @@ impl NiceRegionError<'me, 'tcx> {
215215
false
216216
};
217217

218-
let expected_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef {
219-
def_id: trait_def_id,
220-
substs: expected_substs,
221-
});
222-
let actual_trait_ref = self.infcx.resolve_vars_if_possible(&ty::TraitRef {
223-
def_id: trait_def_id,
224-
substs: actual_substs,
225-
});
218+
let expected_trait_ref =
219+
self.infcx.resolve_vars_if_possible(&ty::TraitRef::new(trait_def_id, expected_substs));
220+
let actual_trait_ref =
221+
self.infcx.resolve_vars_if_possible(&ty::TraitRef::new(trait_def_id, actual_substs));
226222

227223
// Search the expected and actual trait references to see (a)
228224
// whether the sub/sup placeholders appear in them (sometimes

src/librustc/traits/auto_trait.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
8383
) -> AutoTraitResult<A> {
8484
let tcx = self.tcx;
8585

86-
let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) };
86+
let trait_ref = ty::TraitRef::new(trait_did, tcx.mk_substs_trait(ty, &[]));
8787

8888
let trait_pred = ty::Binder::bind(trait_ref);
8989

@@ -271,10 +271,7 @@ impl AutoTraitFinder<'tcx> {
271271
let mut already_visited = FxHashSet::default();
272272
let mut predicates = VecDeque::new();
273273
predicates.push_back(ty::Binder::bind(ty::TraitPredicate {
274-
trait_ref: ty::TraitRef {
275-
def_id: trait_did,
276-
substs: infcx.tcx.mk_substs_trait(ty, &[]),
277-
},
274+
trait_ref: ty::TraitRef::new(trait_did, infcx.tcx.mk_substs_trait(ty, &[])),
278275
}));
279276

280277
let mut computed_preds: FxHashSet<_> = param_env.caller_bounds.iter().cloned().collect();

src/librustc/traits/engine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
2626
def_id: DefId,
2727
cause: ObligationCause<'tcx>,
2828
) {
29-
let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) };
29+
let trait_ref = ty::TraitRef::new(def_id, infcx.tcx.mk_substs_trait(ty, &[]));
3030
self.register_predicate_obligation(
3131
infcx,
3232
Obligation {

src/librustc/traits/error_reporting.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1340,8 +1340,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13401340
cause: ObligationCause<'tcx>,
13411341
param_env: ty::ParamEnv<'tcx>,
13421342
) -> PredicateObligation<'tcx> {
1343-
let new_trait_ref =
1344-
ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
1343+
let new_trait_ref = ty::TraitRef::new(def_id, self.tcx.mk_substs_trait(output_ty, &[]));
13451344
Obligation::new(cause, param_env, new_trait_ref.to_predicate())
13461345
}
13471346

src/librustc/traits/fulfill.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ pub struct PendingPredicateObligation<'tcx> {
7272

7373
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
7474
#[cfg(target_arch = "x86_64")]
75-
static_assert_size!(PendingPredicateObligation<'_>, 136);
75+
static_assert_size!(PendingPredicateObligation<'_>, 144);
7676

7777
impl<'a, 'tcx> FulfillmentContext<'tcx> {
7878
/// Creates a new fulfillment context.

src/librustc/traits/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
137137

138138
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
139139
#[cfg(target_arch = "x86_64")]
140-
static_assert_size!(PredicateObligation<'_>, 112);
140+
static_assert_size!(PredicateObligation<'_>, 120);
141141

142142
/// The reason why we incurred this obligation; used for error reporting.
143143
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
@@ -320,7 +320,7 @@ pub struct AssocTypeBoundData {
320320

321321
// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
322322
#[cfg(target_arch = "x86_64")]
323-
static_assert_size!(ObligationCauseCode<'_>, 32);
323+
static_assert_size!(ObligationCauseCode<'_>, 40);
324324

325325
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
326326
pub struct MatchExpressionArmCause<'tcx> {
@@ -727,7 +727,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
727727
infcx.tcx.def_path_str(def_id)
728728
);
729729

730-
let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) };
730+
let trait_ref = ty::TraitRef::new(def_id, infcx.tcx.mk_substs_trait(ty, &[]));
731731
let obligation = Obligation {
732732
param_env,
733733
cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID),

src/librustc/traits/object_safety.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -579,10 +579,10 @@ fn receiver_is_dispatchable<'tcx>(
579579
let mut param_env = tcx.param_env(method.def_id);
580580

581581
// Self: Unsize<U>
582-
let unsize_predicate = ty::TraitRef {
583-
def_id: unsize_did,
584-
substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
585-
}
582+
let unsize_predicate = ty::TraitRef::new(
583+
unsize_did,
584+
tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
585+
)
586586
.to_predicate();
587587

588588
// U: Trait<Arg1, ..., ArgN>
@@ -596,7 +596,7 @@ fn receiver_is_dispatchable<'tcx>(
596596
}
597597
});
598598

599-
ty::TraitRef { def_id: unsize_did, substs }.to_predicate()
599+
ty::TraitRef::new(unsize_did, substs).to_predicate()
600600
};
601601

602602
let caller_bounds: Vec<Predicate<'tcx>> = param_env
@@ -614,10 +614,10 @@ fn receiver_is_dispatchable<'tcx>(
614614

615615
// Receiver: DispatchFromDyn<Receiver[Self => U]>
616616
let obligation = {
617-
let predicate = ty::TraitRef {
618-
def_id: dispatch_from_dyn_did,
619-
substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
620-
}
617+
let predicate = ty::TraitRef::new(
618+
dispatch_from_dyn_did,
619+
tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
620+
)
621621
.to_predicate();
622622

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

src/librustc/traits/util.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,7 @@ pub fn predicate_for_trait_def(
557557
self_ty: Ty<'tcx>,
558558
params: &[GenericArg<'tcx>],
559559
) -> PredicateObligation<'tcx> {
560-
let trait_ref =
561-
ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) };
560+
let trait_ref = ty::TraitRef::new(trait_def_id, tcx.mk_substs_trait(self_ty, params));
562561
predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
563562
}
564563

@@ -629,10 +628,8 @@ pub fn closure_trait_ref_and_return_type(
629628
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
630629
TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
631630
};
632-
let trait_ref = ty::TraitRef {
633-
def_id: fn_trait_def_id,
634-
substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
635-
};
631+
let trait_ref =
632+
ty::TraitRef::new(fn_trait_def_id, tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]));
636633
ty::Binder::bind((trait_ref, sig.skip_binder().output()))
637634
}
638635

@@ -642,8 +639,7 @@ pub fn generator_trait_ref_and_outputs(
642639
self_ty: Ty<'tcx>,
643640
sig: ty::PolyGenSig<'tcx>,
644641
) -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> {
645-
let trait_ref =
646-
ty::TraitRef { def_id: fn_trait_def_id, substs: tcx.mk_substs_trait(self_ty, &[]) };
642+
let trait_ref = ty::TraitRef::new(fn_trait_def_id, tcx.mk_substs_trait(self_ty, &[]));
647643
ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
648644
}
649645

src/librustc/traits/wf.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -374,10 +374,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
374374
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
375375
if !subty.has_escaping_bound_vars() {
376376
let cause = self.cause(cause);
377-
let trait_ref = ty::TraitRef {
378-
def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
379-
substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
380-
};
377+
let trait_ref = ty::TraitRef::new(
378+
self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
379+
self.infcx.tcx.mk_substs_trait(subty, &[]),
380+
);
381381
self.out.push(traits::Obligation::new(cause, self.param_env, trait_ref.to_predicate()));
382382
}
383383
}

src/librustc/ty/mod.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -2467,11 +2467,9 @@ impl<'tcx> AdtDef {
24672467
Some(x) => x,
24682468
_ => return vec![ty],
24692469
};
2470-
let sized_predicate = Binder::dummy(TraitRef {
2471-
def_id: sized_trait,
2472-
substs: tcx.mk_substs_trait(ty, &[]),
2473-
})
2474-
.to_predicate();
2470+
let sized_predicate =
2471+
Binder::dummy(TraitRef::new(sized_trait, tcx.mk_substs_trait(ty, &[])))
2472+
.to_predicate();
24752473
let predicates = tcx.predicates_of(self.did).predicates;
24762474
if predicates.iter().any(|(p, _)| *p == sized_predicate) {
24772475
vec![]

src/librustc/ty/print/pretty.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1749,7 +1749,13 @@ define_print_and_forward_display! {
17491749
}
17501750

17511751
ty::TraitRef<'tcx> {
1752-
p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
1752+
p!(
1753+
write("<{} as {}{}>",
1754+
self.self_ty(),
1755+
if self.maybe_const { "?const " } else { "" },
1756+
self.print_only_trait_path()
1757+
)
1758+
)
17531759
}
17541760

17551761
TraitRefPrintOnlyTraitPath<'tcx> {

src/librustc/ty/relate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
287287
Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
288288
} else {
289289
let substs = relate_substs(relation, None, a.substs, b.substs)?;
290-
Ok(ty::TraitRef { def_id: a.def_id, substs: substs })
290+
Ok(ty::TraitRef::new(a.def_id, substs))
291291
}
292292
}
293293
}

src/librustc/ty/structural_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ impl<'tcx, I: Idx, T: Lift<'tcx>> Lift<'tcx> for IndexVec<I, T> {
392392
impl<'a, 'tcx> Lift<'tcx> for ty::TraitRef<'a> {
393393
type Lifted = ty::TraitRef<'tcx>;
394394
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
395-
tcx.lift(&self.substs).map(|substs| ty::TraitRef { def_id: self.def_id, substs })
395+
tcx.lift(&self.substs).map(|substs| ty::TraitRef::new(self.def_id, substs))
396396
}
397397
}
398398

src/librustc/ty/sty.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -670,8 +670,7 @@ impl<'tcx> Binder<ExistentialPredicate<'tcx>> {
670670
ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty)))
671671
}
672672
ExistentialPredicate::AutoTrait(did) => {
673-
let trait_ref =
674-
Binder(ty::TraitRef { def_id: did, substs: tcx.mk_substs_trait(self_ty, &[]) });
673+
let trait_ref = Binder(ty::TraitRef::new(did, tcx.mk_substs_trait(self_ty, &[])));
675674
trait_ref.to_predicate()
676675
}
677676
}
@@ -784,17 +783,32 @@ impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
784783
pub struct TraitRef<'tcx> {
785784
pub def_id: DefId,
786785
pub substs: SubstsRef<'tcx>,
786+
787+
/// Whether the reference to the trait is prefixed by `?const`.
788+
//
789+
// FIXME(ecstaticmorse): This field causes `TraitRef` to increase in size by an entire machine
790+
// word, despite it never being used during trait solving. Try implementing the checks in
791+
// `qualify_min_const_fn` using `hir::TraitRef` instead.
792+
pub maybe_const: bool,
787793
}
788794

789795
impl<'tcx> TraitRef<'tcx> {
790796
pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> {
791-
TraitRef { def_id, substs }
797+
TraitRef::new_maybe_const(def_id, substs, false)
798+
}
799+
800+
pub fn new_maybe_const(
801+
def_id: DefId,
802+
substs: SubstsRef<'tcx>,
803+
maybe_const: bool,
804+
) -> TraitRef<'tcx> {
805+
TraitRef { def_id, substs, maybe_const }
792806
}
793807

794808
/// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
795809
/// are the parameters defined on trait.
796810
pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> {
797-
TraitRef { def_id, substs: InternalSubsts::identity_for_item(tcx, def_id) }
811+
TraitRef::new(def_id, InternalSubsts::identity_for_item(tcx, def_id))
798812
}
799813

800814
#[inline]
@@ -817,7 +831,7 @@ impl<'tcx> TraitRef<'tcx> {
817831
) -> ty::TraitRef<'tcx> {
818832
let defs = tcx.generics_of(trait_id);
819833

820-
ty::TraitRef { def_id: trait_id, substs: tcx.intern_substs(&substs[..defs.params.len()]) }
834+
ty::TraitRef::new(trait_id, tcx.intern_substs(&substs[..defs.params.len()]))
821835
}
822836
}
823837

@@ -882,7 +896,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> {
882896
// otherwise the escaping vars would be captured by the binder
883897
// debug_assert!(!self_ty.has_escaping_bound_vars());
884898

885-
ty::TraitRef { def_id: self.def_id, substs: tcx.mk_substs_trait(self_ty, self.substs) }
899+
ty::TraitRef::new(self.def_id, tcx.mk_substs_trait(self_ty, self.substs))
886900
}
887901
}
888902

@@ -1058,7 +1072,7 @@ impl<'tcx> ProjectionTy<'tcx> {
10581072
/// then this function would return a `T: Iterator` trait reference.
10591073
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
10601074
let def_id = tcx.associated_item(self.item_def_id).container.id();
1061-
ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) }
1075+
ty::TraitRef::new(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
10621076
}
10631077

10641078
pub fn self_ty(&self) -> Ty<'tcx> {

src/librustc_ast_lowering/lib.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1977,13 +1977,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19771977
// ::std::future::Future<future_params>
19781978
let future_path =
19791979
self.std_path(span, &[sym::future, sym::Future], Some(future_params), false);
1980+
let future_trait_ref =
1981+
hir::TraitRef { path: future_path, hir_ref_id: self.next_id(), constness: None };
19801982

19811983
hir::GenericBound::Trait(
1982-
hir::PolyTraitRef {
1983-
trait_ref: hir::TraitRef { path: future_path, hir_ref_id: self.next_id() },
1984-
bound_generic_params: &[],
1985-
span,
1986-
},
1984+
hir::PolyTraitRef { trait_ref: future_trait_ref, bound_generic_params: &[], span },
19871985
hir::TraitBoundModifier::None,
19881986
)
19891987
}
@@ -2149,7 +2147,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21492147
hir::QPath::Resolved(None, path) => path,
21502148
qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
21512149
};
2152-
hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) }
2150+
2151+
hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id), constness: p.constness }
21532152
}
21542153

21552154
fn lower_poly_trait_ref(
@@ -2158,7 +2157,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21582157
mut itctx: ImplTraitContext<'_, 'hir>,
21592158
) -> hir::PolyTraitRef<'hir> {
21602159
if p.trait_ref.constness.is_some() {
2161-
self.diagnostic().span_err(p.span, "`?const` on trait bounds is not yet implemented");
2160+
// self.diagnostic().span_err(p.span, "`?const` on trait bounds is not yet implemented");
21622161
}
21632162

21642163
let bound_generic_params = self.lower_generic_params(
@@ -2463,8 +2462,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
24632462
Res::Def(DefKind::Trait, _) | Res::Def(DefKind::TraitAlias, _) => {
24642463
let principal = hir::PolyTraitRef {
24652464
bound_generic_params: &[],
2466-
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
24672465
span,
2466+
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id, constness: None },
24682467
};
24692468

24702469
// The original ID is taken by the `PolyTraitRef`,

src/librustc_hir/hir.rs

+6
Original file line numberDiff line numberDiff line change
@@ -2233,6 +2233,8 @@ pub struct TraitRef<'hir> {
22332233
// Don't hash the `ref_id`. It is tracked via the thing it is used to access.
22342234
#[stable_hasher(ignore)]
22352235
pub hir_ref_id: HirId,
2236+
2237+
pub constness: Option<Constness>,
22362238
}
22372239

22382240
impl TraitRef<'_> {
@@ -2247,6 +2249,10 @@ impl TraitRef<'_> {
22472249
_ => unreachable!(),
22482250
}
22492251
}
2252+
2253+
pub fn is_maybe_const(&self) -> bool {
2254+
self.constness == Some(Constness::NotConst)
2255+
}
22502256
}
22512257

22522258
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]

0 commit comments

Comments
 (0)