Skip to content

Commit 20a4669

Browse files
committed
add in where equality predicate
1 parent eba3228 commit 20a4669

Some content is hidden

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

53 files changed

+458
-21
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1322,9 +1322,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13221322
generics.span,
13231323
);
13241324

1325-
for predicate in &generics.where_clause.predicates {
1326-
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
1327-
deny_equality_constraints(self, predicate, generics);
1325+
if !self.session.features_untracked().type_equality_constraints {
1326+
for predicate in &generics.where_clause.predicates {
1327+
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
1328+
deny_equality_constraints(self, predicate, generics);
1329+
}
13281330
}
13291331
}
13301332
walk_list!(self, visit_generic_param, &generics.params);
@@ -1546,6 +1548,9 @@ fn deny_equality_constraints(
15461548
predicate.span,
15471549
"equality constraints are not yet supported in `where` clauses",
15481550
);
1551+
if this.session.is_nightly_build() {
1552+
err.help("add `#![feature(type_equality_constraints)]` to the crate attributes to enable");
1553+
}
15491554
err.span_label(predicate.span, "not supported");
15501555

15511556
// Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.

compiler/rustc_feature/src/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,9 @@ declare_features! (
680680
/// Allows `#[derive(Default)]` and `#[default]` on enums.
681681
(active, derive_default_enum, "1.56.0", Some(86985), None),
682682

683+
/// Allows `where T = U` in where predicates.
684+
(active, type_equality_constraints, "1.56.0", Some(87533), None),
685+
683686
// -------------------------------------------------------------------------
684687
// feature-group-end: actual feature gates
685688
// -------------------------------------------------------------------------

compiler/rustc_infer/src/infer/outlives/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub fn explicit_outlives_bounds<'tcx>(
2626
| ty::PredicateKind::TypeOutlives(..)
2727
| ty::PredicateKind::ConstEvaluatable(..)
2828
| ty::PredicateKind::ConstEquate(..)
29+
| ty::PredicateKind::TypeEquate(..)
2930
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
3031
ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
3132
Some(OutlivesBound::RegionSubRegion(r_b, r_a))

compiler/rustc_infer/src/traits/util.rs

+4
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ impl Elaborator<'tcx> {
172172
// Currently, we do not elaborate const-equate
173173
// predicates.
174174
}
175+
ty::PredicateKind::TypeEquate(..) => {
176+
// Currently, we do not elaborate type-equate
177+
// predicates.
178+
}
175179
ty::PredicateKind::RegionOutlives(..) => {
176180
// Nothing to elaborate from `'a: 'b`.
177181
}

compiler/rustc_lint/src/builtin.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
16121612
Subtype(..) |
16131613
ConstEvaluatable(..) |
16141614
ConstEquate(..) |
1615+
TypeEquate(..) |
16151616
TypeWellFormedFromEnv(..) => continue,
16161617
};
16171618
if predicate.is_global() {

compiler/rustc_middle/src/ty/flags.rs

+4
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@ impl FlagComputation {
252252
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
253253
self.add_ty(ty);
254254
}
255+
ty::PredicateKind::TypeEquate(lhs, rhs) => {
256+
self.add_ty(lhs);
257+
self.add_ty(rhs);
258+
}
255259
}
256260
}
257261

compiler/rustc_middle/src/ty/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,9 @@ pub enum PredicateKind<'tcx> {
492492
///
493493
/// Only used for Chalk.
494494
TypeWellFormedFromEnv(Ty<'tcx>),
495+
496+
/// `where T = U`
497+
TypeEquate(Ty<'tcx>, Ty<'tcx>),
495498
}
496499

497500
/// The crate outlives map is computed during typeck and contains the
@@ -800,6 +803,7 @@ impl<'tcx> Predicate<'tcx> {
800803
| PredicateKind::TypeOutlives(..)
801804
| PredicateKind::ConstEvaluatable(..)
802805
| PredicateKind::ConstEquate(..)
806+
| PredicateKind::TypeEquate(..)
803807
| PredicateKind::TypeWellFormedFromEnv(..) => None,
804808
}
805809
}
@@ -817,6 +821,7 @@ impl<'tcx> Predicate<'tcx> {
817821
| PredicateKind::ClosureKind(..)
818822
| PredicateKind::ConstEvaluatable(..)
819823
| PredicateKind::ConstEquate(..)
824+
| PredicateKind::TypeEquate(..)
820825
| PredicateKind::TypeWellFormedFromEnv(..) => None,
821826
}
822827
}

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

+3
Original file line numberDiff line numberDiff line change
@@ -2292,6 +2292,9 @@ define_print_and_forward_display! {
22922292
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
22932293
p!("the type `", print(ty), "` is found in the environment")
22942294
}
2295+
ty::PredicateKind::TypeEquate(lhs, rhs) => {
2296+
p!("the type `", print(lhs), "` equals `", print(rhs), "`")
2297+
}
22952298
}
22962299
}
22972300

compiler/rustc_middle/src/ty/structural_impls.rs

+6
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ impl fmt::Debug for ty::PredicateKind<'tcx> {
198198
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
199199
write!(f, "TypeWellFormedFromEnv({:?})", ty)
200200
}
201+
ty::PredicateKind::TypeEquate(lhs, rhs) => {
202+
write!(f, "TypeEquate({:?}, {:?})", lhs, rhs)
203+
}
201204
}
202205
}
203206
}
@@ -450,6 +453,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
450453
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
451454
tcx.lift(ty).map(ty::PredicateKind::TypeWellFormedFromEnv)
452455
}
456+
ty::PredicateKind::TypeEquate(lhs, rhs) => {
457+
tcx.lift((lhs, rhs)).map(|(lhs, rhs)| ty::PredicateKind::TypeEquate(lhs, rhs))
458+
}
453459
}
454460
}
455461
}

compiler/rustc_mir/src/transform/check_consts/check.rs

+1
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ impl Checker<'mir, 'tcx> {
413413
| ty::PredicateKind::Projection(_)
414414
| ty::PredicateKind::ConstEvaluatable(..)
415415
| ty::PredicateKind::ConstEquate(..)
416+
| ty::PredicateKind::TypeEquate(..)
416417
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
417418
ty::PredicateKind::ObjectSafe(_) => {
418419
bug!("object safe predicate on function: {:#?}", predicate)

compiler/rustc_parse/src/parser/generics.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ impl<'a> Parser<'a> {
284284
}))
285285
// FIXME: Decide what should be used here, `=` or `==`.
286286
// FIXME: We are just dropping the binders in lifetime_defs on the floor here.
287-
} else if self.eat(&token::Eq) || self.eat(&token::EqEq) {
287+
} else if self.eat(&token::Eq) {
288288
let rhs_ty = self.parse_ty()?;
289289
Ok(ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
290290
span: lo.to(self.prev_token.span),
@@ -293,7 +293,15 @@ impl<'a> Parser<'a> {
293293
id: ast::DUMMY_NODE_ID,
294294
}))
295295
} else {
296-
self.unexpected()
296+
if self.token == token::EqEq {
297+
let err = self.struct_span_err(
298+
lo.to(self.prev_token.span),
299+
"type equality predicates are `=` not `==`",
300+
);
301+
Err(err)
302+
} else {
303+
self.unexpected()
304+
}
297305
}
298306
}
299307

compiler/rustc_privacy/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ where
132132
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => {
133133
ty.visit_with(self)
134134
}
135+
ty::PredicateKind::TypeEquate(lhs, rhs) => {
136+
lhs.visit_with(self)?;
137+
rhs.visit_with(self)
138+
}
135139
ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
136140
ty::PredicateKind::ConstEvaluatable(defs, substs)
137141
if self.def_id_visitor.tcx().features().const_evaluatable_checked =>

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,7 @@ symbols! {
12851285
type_alias_enum_variants,
12861286
type_alias_impl_trait,
12871287
type_ascription,
1288+
type_equality_constraints,
12881289
type_id,
12891290
type_length_limit,
12901291
type_macros,

compiler/rustc_trait_selection/src/opaque_types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,7 @@ crate fn required_region_bounds(
11891189
| ty::PredicateKind::RegionOutlives(..)
11901190
| ty::PredicateKind::ConstEvaluatable(..)
11911191
| ty::PredicateKind::ConstEquate(..)
1192+
| ty::PredicateKind::TypeEquate(..)
11921193
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
11931194
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
11941195
// Search for a bound of the form `erased_self_ty

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
698698
)
699699
}
700700

701+
ty::PredicateKind::TypeEquate(..) => {
702+
// Errors for `TypeEquate` predicates show up as
703+
// `SelectionError::FIXME(type_equality_constraints)`,
704+
// not `Unimplemented`.
705+
span_bug!(
706+
span,
707+
"type-equate requirement gave wrong error: `{:?}`",
708+
obligation
709+
)
710+
}
711+
701712
ty::PredicateKind::TypeWellFormedFromEnv(..) => span_bug!(
702713
span,
703714
"TypeWellFormedFromEnv predicate should only exist in the environment"

compiler/rustc_trait_selection/src/traits/fulfill.rs

+11
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
377377
| ty::PredicateKind::ClosureKind(..)
378378
| ty::PredicateKind::Subtype(_)
379379
| ty::PredicateKind::ConstEvaluatable(..)
380+
| ty::PredicateKind::TypeEquate(..)
380381
| ty::PredicateKind::ConstEquate(..) => {
381382
let pred = infcx.replace_bound_vars_with_placeholders(binder);
382383
ProcessResult::Changed(mk_pending(vec![
@@ -491,6 +492,16 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
491492
}
492493
}
493494

495+
ty::PredicateKind::TypeEquate(lhs, rhs) => {
496+
match self.selcx.infcx().can_eq(obligation.param_env, lhs, rhs) {
497+
Ok(()) => ProcessResult::Changed(vec![]),
498+
Err(e) => ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError(
499+
ExpectedFound::new(false, lhs, rhs),
500+
e,
501+
)),
502+
}
503+
}
504+
494505
ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
495506
match const_evaluatable::is_const_evaluatable(
496507
self.selcx.infcx(),

compiler/rustc_trait_selection/src/traits/object_safety.rs

+6
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,11 @@ fn predicate_references_self(
302302
// possible alternatives.
303303
if data.projection_ty.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
304304
}
305+
ty::PredicateKind::TypeEquate(lhs, rhs) => {
306+
let has_self = lhs.walk().any(|arg| arg == self_ty.into())
307+
|| rhs.walk().any(|arg| arg == self_ty.into());
308+
if has_self { Some(sp) } else { None }
309+
}
305310
ty::PredicateKind::WellFormed(..)
306311
| ty::PredicateKind::ObjectSafe(..)
307312
| ty::PredicateKind::TypeOutlives(..)
@@ -343,6 +348,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
343348
| ty::PredicateKind::TypeOutlives(..)
344349
| ty::PredicateKind::ConstEvaluatable(..)
345350
| ty::PredicateKind::ConstEquate(..)
351+
| ty::PredicateKind::TypeEquate(..)
346352
| ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
347353
}
348354
})

compiler/rustc_trait_selection/src/traits/select/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
562562
}
563563
}
564564

565+
ty::PredicateKind::TypeEquate(lhs, rhs) => {
566+
match self.infcx.can_eq(obligation.param_env, lhs, rhs) {
567+
Ok(()) => Ok(EvaluatedToOk),
568+
Err(_) => Ok(EvaluatedToErr),
569+
}
570+
}
571+
565572
ty::PredicateKind::ConstEquate(c1, c2) => {
566573
debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");
567574

compiler/rustc_trait_selection/src/traits/wf.rs

+4
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ pub fn predicate_obligations<'a, 'tcx>(
140140
wf.compute(c1.into());
141141
wf.compute(c2.into());
142142
}
143+
ty::PredicateKind::TypeEquate(lhs, rhs) => {
144+
wf.compute(lhs.into());
145+
wf.compute(rhs.into());
146+
}
143147
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
144148
bug!("TypeWellFormedFromEnv is only used for Chalk")
145149
}

compiler/rustc_traits/src/chalk/lowering.rs

+4
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
110110
| ty::PredicateKind::ClosureKind(..)
111111
| ty::PredicateKind::Subtype(..)
112112
| ty::PredicateKind::ConstEvaluatable(..)
113+
| ty::PredicateKind::TypeEquate(..)
113114
| ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
114115
};
115116
let value = chalk_ir::ProgramClauseImplication {
@@ -194,6 +195,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
194195
ty::PredicateKind::ClosureKind(..)
195196
| ty::PredicateKind::Subtype(..)
196197
| ty::PredicateKind::ConstEvaluatable(..)
198+
| ty::PredicateKind::TypeEquate(..)
197199
| ty::PredicateKind::ConstEquate(..) => {
198200
chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner))
199201
}
@@ -593,6 +595,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
593595
| ty::PredicateKind::ClosureKind(..)
594596
| ty::PredicateKind::Subtype(..)
595597
| ty::PredicateKind::ConstEvaluatable(..)
598+
| ty::PredicateKind::TypeEquate(..)
596599
| ty::PredicateKind::ConstEquate(..)
597600
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {
598601
bug!("unexpected predicate {}", &self)
@@ -721,6 +724,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<Ru
721724
| ty::PredicateKind::Subtype(..)
722725
| ty::PredicateKind::ConstEvaluatable(..)
723726
| ty::PredicateKind::ConstEquate(..)
727+
| ty::PredicateKind::TypeEquate(..)
724728
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {
725729
bug!("unexpected predicate {}", &self)
726730
}

compiler/rustc_traits/src/implied_outlives_bounds.rs

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ fn compute_implied_outlives_bounds<'tcx>(
104104
| ty::PredicateKind::ObjectSafe(..)
105105
| ty::PredicateKind::ConstEvaluatable(..)
106106
| ty::PredicateKind::ConstEquate(..)
107+
| ty::PredicateKind::TypeEquate(..)
107108
| ty::PredicateKind::TypeWellFormedFromEnv(..) => vec![],
108109
ty::PredicateKind::WellFormed(arg) => {
109110
wf_args.push(arg);

compiler/rustc_traits/src/normalize_erasing_regions.rs

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ fn not_outlives_predicate(p: &ty::Predicate<'tcx>) -> bool {
6767
| ty::PredicateKind::Subtype(..)
6868
| ty::PredicateKind::ConstEvaluatable(..)
6969
| ty::PredicateKind::ConstEquate(..)
70+
| ty::PredicateKind::TypeEquate(..)
7071
| ty::PredicateKind::TypeWellFormedFromEnv(..) => true,
7172
}
7273
}

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
838838
ty::PredicateKind::WellFormed(..) => None,
839839
ty::PredicateKind::ObjectSafe(..) => None,
840840
ty::PredicateKind::ConstEvaluatable(..) => None,
841+
ty::PredicateKind::TypeEquate(..) => None,
841842
ty::PredicateKind::ConstEquate(..) => None,
842843
// N.B., this predicate is created by breaking down a
843844
// `ClosureType: FnFoo()` predicate, where

compiler/rustc_typeck/src/check/method/probe.rs

+1
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
849849
| ty::PredicateKind::TypeOutlives(..)
850850
| ty::PredicateKind::ConstEvaluatable(..)
851851
| ty::PredicateKind::ConstEquate(..)
852+
| ty::PredicateKind::TypeEquate(..)
852853
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
853854
}
854855
});

compiler/rustc_typeck/src/collect.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -2294,8 +2294,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
22942294
}))
22952295
}
22962296

2297-
hir::WherePredicate::EqPredicate(..) => {
2298-
// FIXME(#20041)
2297+
hir::WherePredicate::EqPredicate(where_eq_pred) => {
2298+
let hir::WhereEqPredicate { hir_id: _, span, lhs_ty, rhs_ty } = where_eq_pred;
2299+
let lhs = icx.to_ty(&lhs_ty);
2300+
let rhs = icx.to_ty(&rhs_ty);
2301+
// FIXME(type_equality_constraints): prevent 2 ty::Params here which currently
2302+
// doesn't constrain types at all? It's still useful when programming though.
2303+
predicates
2304+
.insert((ty::PredicateKind::TypeEquate(lhs, rhs).to_predicate(icx.tcx), *span));
22992305
}
23002306
}
23012307
}

compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs

+1
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ fn trait_predicate_kind<'tcx>(
407407
| ty::PredicateKind::ClosureKind(..)
408408
| ty::PredicateKind::ConstEvaluatable(..)
409409
| ty::PredicateKind::ConstEquate(..)
410+
| ty::PredicateKind::TypeEquate(..)
410411
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
411412
}
412413
}

compiler/rustc_typeck/src/outlives/explicit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
5858
| ty::PredicateKind::Subtype(..)
5959
| ty::PredicateKind::ConstEvaluatable(..)
6060
| ty::PredicateKind::ConstEquate(..)
61+
| ty::PredicateKind::TypeEquate(..)
6162
| ty::PredicateKind::TypeWellFormedFromEnv(..) => (),
6263
}
6364
}

src/librustdoc/clean/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
327327
ty::PredicateKind::RegionOutlives(pred) => pred.clean(cx),
328328
ty::PredicateKind::TypeOutlives(pred) => pred.clean(cx),
329329
ty::PredicateKind::Projection(pred) => Some(pred.clean(cx)),
330+
ty::PredicateKind::TypeEquate(..) => todo!(),
330331
ty::PredicateKind::ConstEvaluatable(..) => None,
331332

332333
ty::PredicateKind::Subtype(..)

src/librustdoc/html/format.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,9 @@ crate fn print_where_clause<'a, 'tcx: 'a>(
295295
}
296296
clean::WherePredicate::EqPredicate { lhs, rhs } => {
297297
if f.alternate() {
298-
clause.push_str(&format!("{:#} == {:#}", lhs.print(cx), rhs.print(cx),));
298+
clause.push_str(&format!("{:#} = {:#}", lhs.print(cx), rhs.print(cx),));
299299
} else {
300-
clause.push_str(&format!("{} == {}", lhs.print(cx), rhs.print(cx),));
300+
clause.push_str(&format!("{} = {}", lhs.print(cx), rhs.print(cx),));
301301
}
302302
}
303303
}

0 commit comments

Comments
 (0)