From 20a4669523952b8d976467e5806246d997810a76 Mon Sep 17 00:00:00 2001 From: kadmin Date: Mon, 26 Jul 2021 07:36:47 +0000 Subject: [PATCH] add in where equality predicate --- .../rustc_ast_passes/src/ast_validation.rs | 11 +++- compiler/rustc_feature/src/active.rs | 3 + .../rustc_infer/src/infer/outlives/mod.rs | 1 + compiler/rustc_infer/src/traits/util.rs | 4 ++ compiler/rustc_lint/src/builtin.rs | 1 + compiler/rustc_middle/src/ty/flags.rs | 4 ++ compiler/rustc_middle/src/ty/mod.rs | 5 ++ compiler/rustc_middle/src/ty/print/pretty.rs | 3 + .../rustc_middle/src/ty/structural_impls.rs | 6 ++ .../src/transform/check_consts/check.rs | 1 + compiler/rustc_parse/src/parser/generics.rs | 12 +++- compiler/rustc_privacy/src/lib.rs | 4 ++ compiler/rustc_span/src/symbol.rs | 1 + .../rustc_trait_selection/src/opaque_types.rs | 1 + .../src/traits/error_reporting/mod.rs | 11 ++++ .../src/traits/fulfill.rs | 11 ++++ .../src/traits/object_safety.rs | 6 ++ .../src/traits/select/mod.rs | 7 +++ .../rustc_trait_selection/src/traits/wf.rs | 4 ++ compiler/rustc_traits/src/chalk/lowering.rs | 4 ++ .../src/implied_outlives_bounds.rs | 1 + .../src/normalize_erasing_regions.rs | 1 + .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 1 + .../rustc_typeck/src/check/method/probe.rs | 1 + compiler/rustc_typeck/src/collect.rs | 10 +++- .../src/impl_wf_check/min_specialization.rs | 1 + .../rustc_typeck/src/outlives/explicit.rs | 1 + src/librustdoc/clean/mod.rs | 1 + src/librustdoc/html/format.rs | 4 +- ...pe-projection-from-multiple-supertraits.rs | 1 + ...rojection-from-multiple-supertraits.stderr | 17 +++++- ...te-type_equality_constraints.normal.stderr | 11 ++++ .../feature-gate-type_equality_constraints.rs | 17 ++++++ src/test/ui/parser/bounds-type-where.rs | 2 +- src/test/ui/parser/bounds-type-where.stderr | 4 +- src/test/ui/parser/issue-17904.rs | 2 +- src/test/ui/parser/issue-17904.stderr | 4 +- src/test/ui/where-clauses/where-eq-assoc.rs | 29 ++++++++++ .../ui/where-clauses/where-eq-assoc.stderr | 35 ++++++++++++ .../ui/where-clauses/where-eq-double-eq.rs | 4 ++ .../where-clauses/where-eq-double-eq.stderr | 8 +++ .../ui/where-clauses/where-eq-into-iter.rs | 13 +++++ .../ui/where-clauses/where-eq-multiple.rs | 18 ++++++ .../ui/where-clauses/where-eq-multiple.stderr | 57 +++++++++++++++++++ .../ui/where-clauses/where-eq-rnd-params.rs | 10 ++++ .../where-clauses/where-eq-rnd-params.stderr | 20 +++++++ src/test/ui/where-clauses/where-eq-self.rs | 20 +++++++ .../ui/where-clauses/where-eq-self.stderr | 12 ++++ src/test/ui/where-clauses/where-eq.rs | 19 +++++++ src/test/ui/where-clauses/where-eq.stderr | 21 +++++++ .../where-equality-constraints.rs | 4 +- .../where-equality-constraints.stderr | 29 ++++++++-- .../clippy_utils/src/qualify_min_const_fn.rs | 1 + 53 files changed, 458 insertions(+), 21 deletions(-) create mode 100644 src/test/ui/feature-gates/feature-gate-type_equality_constraints.normal.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-type_equality_constraints.rs create mode 100644 src/test/ui/where-clauses/where-eq-assoc.rs create mode 100644 src/test/ui/where-clauses/where-eq-assoc.stderr create mode 100644 src/test/ui/where-clauses/where-eq-double-eq.rs create mode 100644 src/test/ui/where-clauses/where-eq-double-eq.stderr create mode 100644 src/test/ui/where-clauses/where-eq-into-iter.rs create mode 100644 src/test/ui/where-clauses/where-eq-multiple.rs create mode 100644 src/test/ui/where-clauses/where-eq-multiple.stderr create mode 100644 src/test/ui/where-clauses/where-eq-rnd-params.rs create mode 100644 src/test/ui/where-clauses/where-eq-rnd-params.stderr create mode 100644 src/test/ui/where-clauses/where-eq-self.rs create mode 100644 src/test/ui/where-clauses/where-eq-self.stderr create mode 100644 src/test/ui/where-clauses/where-eq.rs create mode 100644 src/test/ui/where-clauses/where-eq.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index acc41d9f6443c..3f2175f44f38e 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1322,9 +1322,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { generics.span, ); - for predicate in &generics.where_clause.predicates { - if let WherePredicate::EqPredicate(ref predicate) = *predicate { - deny_equality_constraints(self, predicate, generics); + if !self.session.features_untracked().type_equality_constraints { + for predicate in &generics.where_clause.predicates { + if let WherePredicate::EqPredicate(ref predicate) = *predicate { + deny_equality_constraints(self, predicate, generics); + } } } walk_list!(self, visit_generic_param, &generics.params); @@ -1546,6 +1548,9 @@ fn deny_equality_constraints( predicate.span, "equality constraints are not yet supported in `where` clauses", ); + if this.session.is_nightly_build() { + err.help("add `#![feature(type_equality_constraints)]` to the crate attributes to enable"); + } err.span_label(predicate.span, "not supported"); // Given `::Bar = RhsTy`, suggest `A: Foo`. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 3cb1dd170386b..ea331d05001ab 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -680,6 +680,9 @@ declare_features! ( /// Allows `#[derive(Default)]` and `#[default]` on enums. (active, derive_default_enum, "1.56.0", Some(86985), None), + /// Allows `where T = U` in where predicates. + (active, type_equality_constraints, "1.56.0", Some(87533), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 07c75d50d91da..a3e194881eb57 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -26,6 +26,7 @@ pub fn explicit_outlives_bounds<'tcx>( | ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => { Some(OutlivesBound::RegionSubRegion(r_b, r_a)) diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index ce1445f8a4746..aa11ed437072d 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -172,6 +172,10 @@ impl Elaborator<'tcx> { // Currently, we do not elaborate const-equate // predicates. } + ty::PredicateKind::TypeEquate(..) => { + // Currently, we do not elaborate type-equate + // predicates. + } ty::PredicateKind::RegionOutlives(..) => { // Nothing to elaborate from `'a: 'b`. } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index b3c64b76820f1..12da75b1ffdba 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1612,6 +1612,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { Subtype(..) | ConstEvaluatable(..) | ConstEquate(..) | + TypeEquate(..) | TypeWellFormedFromEnv(..) => continue, }; if predicate.is_global() { diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 9faa172a4973f..3293bd880a11a 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -252,6 +252,10 @@ impl FlagComputation { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { self.add_ty(ty); } + ty::PredicateKind::TypeEquate(lhs, rhs) => { + self.add_ty(lhs); + self.add_ty(rhs); + } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a6aff42479069..20453bb66757b 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -492,6 +492,9 @@ pub enum PredicateKind<'tcx> { /// /// Only used for Chalk. TypeWellFormedFromEnv(Ty<'tcx>), + + /// `where T = U` + TypeEquate(Ty<'tcx>, Ty<'tcx>), } /// The crate outlives map is computed during typeck and contains the @@ -800,6 +803,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::TypeOutlives(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::TypeEquate(..) | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -817,6 +821,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::ClosureKind(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::TypeEquate(..) | PredicateKind::TypeWellFormedFromEnv(..) => None, } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index dc94124e62ab6..82b47ab311630 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2292,6 +2292,9 @@ define_print_and_forward_display! { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { p!("the type `", print(ty), "` is found in the environment") } + ty::PredicateKind::TypeEquate(lhs, rhs) => { + p!("the type `", print(lhs), "` equals `", print(rhs), "`") + } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 7290c41d615df..743c0d1f4669d 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -198,6 +198,9 @@ impl fmt::Debug for ty::PredicateKind<'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { write!(f, "TypeWellFormedFromEnv({:?})", ty) } + ty::PredicateKind::TypeEquate(lhs, rhs) => { + write!(f, "TypeEquate({:?}, {:?})", lhs, rhs) + } } } } @@ -450,6 +453,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { tcx.lift(ty).map(ty::PredicateKind::TypeWellFormedFromEnv) } + ty::PredicateKind::TypeEquate(lhs, rhs) => { + tcx.lift((lhs, rhs)).map(|(lhs, rhs)| ty::PredicateKind::TypeEquate(lhs, rhs)) + } } } } diff --git a/compiler/rustc_mir/src/transform/check_consts/check.rs b/compiler/rustc_mir/src/transform/check_consts/check.rs index 109da59aa4380..29137179ffa0e 100644 --- a/compiler/rustc_mir/src/transform/check_consts/check.rs +++ b/compiler/rustc_mir/src/transform/check_consts/check.rs @@ -413,6 +413,7 @@ impl Checker<'mir, 'tcx> { | ty::PredicateKind::Projection(_) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, ty::PredicateKind::ObjectSafe(_) => { bug!("object safe predicate on function: {:#?}", predicate) diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index f175c5b50b397..3dcc8da81c3c2 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -284,7 +284,7 @@ impl<'a> Parser<'a> { })) // FIXME: Decide what should be used here, `=` or `==`. // FIXME: We are just dropping the binders in lifetime_defs on the floor here. - } else if self.eat(&token::Eq) || self.eat(&token::EqEq) { + } else if self.eat(&token::Eq) { let rhs_ty = self.parse_ty()?; Ok(ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { span: lo.to(self.prev_token.span), @@ -293,7 +293,15 @@ impl<'a> Parser<'a> { id: ast::DUMMY_NODE_ID, })) } else { - self.unexpected() + if self.token == token::EqEq { + let err = self.struct_span_err( + lo.to(self.prev_token.span), + "type equality predicates are `=` not `==`", + ); + Err(err) + } else { + self.unexpected() + } } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index cd91ecdf2bad3..5db337e818b69 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -132,6 +132,10 @@ where ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => { ty.visit_with(self) } + ty::PredicateKind::TypeEquate(lhs, rhs) => { + lhs.visit_with(self)?; + rhs.visit_with(self) + } ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE, ty::PredicateKind::ConstEvaluatable(defs, substs) if self.def_id_visitor.tcx().features().const_evaluatable_checked => diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5fc773e431c8b..f011b85542585 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1285,6 +1285,7 @@ symbols! { type_alias_enum_variants, type_alias_impl_trait, type_ascription, + type_equality_constraints, type_id, type_length_limit, type_macros, diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 95c81c5c729be..6b7c1ce150f25 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -1189,6 +1189,7 @@ crate fn required_region_bounds( | ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => { // Search for a bound of the form `erased_self_ty diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 13a6733fb478a..ba4b8a738fd55 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -698,6 +698,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) } + ty::PredicateKind::TypeEquate(..) => { + // Errors for `TypeEquate` predicates show up as + // `SelectionError::FIXME(type_equality_constraints)`, + // not `Unimplemented`. + span_bug!( + span, + "type-equate requirement gave wrong error: `{:?}`", + obligation + ) + } + ty::PredicateKind::TypeWellFormedFromEnv(..) => span_bug!( span, "TypeWellFormedFromEnv predicate should only exist in the environment" diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 9ec1dd5c2ee3b..bf3a3f8f29673 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -377,6 +377,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(_) | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::ConstEquate(..) => { let pred = infcx.replace_bound_vars_with_placeholders(binder); ProcessResult::Changed(mk_pending(vec![ @@ -491,6 +492,16 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { } } + ty::PredicateKind::TypeEquate(lhs, rhs) => { + match self.selcx.infcx().can_eq(obligation.param_env, lhs, rhs) { + Ok(()) => ProcessResult::Changed(vec![]), + Err(e) => ProcessResult::Error(FulfillmentErrorCode::CodeSubtypeError( + ExpectedFound::new(false, lhs, rhs), + e, + )), + } + } + ty::PredicateKind::ConstEvaluatable(def_id, substs) => { match const_evaluatable::is_const_evaluatable( self.selcx.infcx(), diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 7ebef7f8883ae..6b7c5b9770e93 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -302,6 +302,11 @@ fn predicate_references_self( // possible alternatives. if data.projection_ty.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None } } + ty::PredicateKind::TypeEquate(lhs, rhs) => { + let has_self = lhs.walk().any(|arg| arg == self_ty.into()) + || rhs.walk().any(|arg| arg == self_ty.into()); + if has_self { Some(sp) } else { None } + } ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::TypeOutlives(..) @@ -343,6 +348,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => false, } }) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 95611ebc8188c..1456a1f9875a3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -562,6 +562,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + ty::PredicateKind::TypeEquate(lhs, rhs) => { + match self.infcx.can_eq(obligation.param_env, lhs, rhs) { + Ok(()) => Ok(EvaluatedToOk), + Err(_) => Ok(EvaluatedToErr), + } + } + ty::PredicateKind::ConstEquate(c1, c2) => { debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts"); diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 27c8e00c5596c..097219e01f4a6 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -140,6 +140,10 @@ pub fn predicate_obligations<'a, 'tcx>( wf.compute(c1.into()); wf.compute(c2.into()); } + ty::PredicateKind::TypeEquate(lhs, rhs) => { + wf.compute(lhs.into()); + wf.compute(rhs.into()); + } ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index a838172d664c3..9e6c6ae001462 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -110,6 +110,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment bug!("unexpected predicate {}", predicate), }; let value = chalk_ir::ProgramClauseImplication { @@ -194,6 +195,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::ConstEquate(..) => { chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner)) } @@ -593,6 +595,7 @@ impl<'tcx> LowerInto<'tcx, Option { bug!("unexpected predicate {}", &self) @@ -721,6 +724,7 @@ impl<'tcx> LowerInto<'tcx, Option { bug!("unexpected predicate {}", &self) } diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 90ba90259c32b..0f6b214dd52b8 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -104,6 +104,7 @@ fn compute_implied_outlives_bounds<'tcx>( | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => vec![], ty::PredicateKind::WellFormed(arg) => { wf_args.push(arg); diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 5ad0684fe6ee2..c3f61b9237e7e 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -67,6 +67,7 @@ fn not_outlives_predicate(p: &ty::Predicate<'tcx>) -> bool { | ty::PredicateKind::Subtype(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => true, } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index f5776ae7cf66a..fd84e0651a6ec 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -838,6 +838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::PredicateKind::WellFormed(..) => None, ty::PredicateKind::ObjectSafe(..) => None, ty::PredicateKind::ConstEvaluatable(..) => None, + ty::PredicateKind::TypeEquate(..) => None, ty::PredicateKind::ConstEquate(..) => None, // N.B., this predicate is created by breaking down a // `ClosureType: FnFoo()` predicate, where diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 9037ffe49a9a2..e06a11e5d1154 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -849,6 +849,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::PredicateKind::TypeOutlives(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } }); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 997fdcefe037a..9aa899ef27199 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2294,8 +2294,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP })) } - hir::WherePredicate::EqPredicate(..) => { - // FIXME(#20041) + hir::WherePredicate::EqPredicate(where_eq_pred) => { + let hir::WhereEqPredicate { hir_id: _, span, lhs_ty, rhs_ty } = where_eq_pred; + let lhs = icx.to_ty(&lhs_ty); + let rhs = icx.to_ty(&rhs_ty); + // FIXME(type_equality_constraints): prevent 2 ty::Params here which currently + // doesn't constrain types at all? It's still useful when programming though. + predicates + .insert((ty::PredicateKind::TypeEquate(lhs, rhs).to_predicate(icx.tcx), *span)); } } } diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 505d9a59d9c2f..9df30f33464fe 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -407,6 +407,7 @@ fn trait_predicate_kind<'tcx>( | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, } } diff --git a/compiler/rustc_typeck/src/outlives/explicit.rs b/compiler/rustc_typeck/src/outlives/explicit.rs index 6e5be87928d59..12ccd0e15e34f 100644 --- a/compiler/rustc_typeck/src/outlives/explicit.rs +++ b/compiler/rustc_typeck/src/outlives/explicit.rs @@ -58,6 +58,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::PredicateKind::Subtype(..) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => (), } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 27c2f6cc87e17..cc3afee61447e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -327,6 +327,7 @@ impl<'a> Clean> for ty::Predicate<'a> { ty::PredicateKind::RegionOutlives(pred) => pred.clean(cx), ty::PredicateKind::TypeOutlives(pred) => pred.clean(cx), ty::PredicateKind::Projection(pred) => Some(pred.clean(cx)), + ty::PredicateKind::TypeEquate(..) => todo!(), ty::PredicateKind::ConstEvaluatable(..) => None, ty::PredicateKind::Subtype(..) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index cd74006530b44..1e27ef5ab9e65 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -295,9 +295,9 @@ crate fn print_where_clause<'a, 'tcx: 'a>( } clean::WherePredicate::EqPredicate { lhs, rhs } => { if f.alternate() { - clause.push_str(&format!("{:#} == {:#}", lhs.print(cx), rhs.print(cx),)); + clause.push_str(&format!("{:#} = {:#}", lhs.print(cx), rhs.print(cx),)); } else { - clause.push_str(&format!("{} == {}", lhs.print(cx), rhs.print(cx),)); + clause.push_str(&format!("{} = {}", lhs.print(cx), rhs.print(cx),)); } } } diff --git a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs index df19332b6458a..a117426f89f51 100644 --- a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs +++ b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs @@ -31,6 +31,7 @@ fn paint(c: C, d: C::Color) { fn dent_object_2(c: dyn BoxCar) where ::Color = COLOR { //~^ ERROR the value of the associated types + //~| ERROR the value of the associated types //~| ERROR equality constraints are not yet supported in `where` clauses } diff --git a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr index cd7c0dc4a44d0..19444b7545d90 100644 --- a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr +++ b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr @@ -4,6 +4,7 @@ error: equality constraints are not yet supported in `where` clauses LL | fn dent_object_2(c: dyn BoxCar) where ::Color = COLOR { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported | + = help: add `#![feature(type_equality_constraints)]` to the crate attributes to enable = note: see issue #20041 for more information error[E0221]: ambiguous associated type `Color` in bounds of `C` @@ -80,6 +81,20 @@ help: use fully qualified syntax to disambiguate LL | fn paint(c: C, d: ::Color) { | ^^^^^^^^^^^^^^^^^ +error[E0191]: the value of the associated types `Color` (from trait `Box`), `Color` (from trait `Vehicle`) must be specified + --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:51 + | +LL | type Color; + | ----------- `Vehicle::Color` defined here +... +LL | type Color; + | ----------- `Box::Color` defined here +... +LL | fn dent_object_2(c: dyn BoxCar) where ::Color = COLOR { + | ^^^^^^ associated types `Color` (from trait `Vehicle`), `Color` (from trait `Box`) must be specified + | + = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types + error[E0191]: the value of the associated types `Color` (from trait `Box`), `Color` (from trait `Vehicle`) must be specified --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:32 | @@ -94,7 +109,7 @@ LL | fn dent_object_2(c: dyn BoxCar) where ::Color | = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0191, E0221, E0222. For more information about an error, try `rustc --explain E0191`. diff --git a/src/test/ui/feature-gates/feature-gate-type_equality_constraints.normal.stderr b/src/test/ui/feature-gates/feature-gate-type_equality_constraints.normal.stderr new file mode 100644 index 0000000000000..650ccdc43e59e --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-type_equality_constraints.normal.stderr @@ -0,0 +1,11 @@ +error: equality constraints are not yet supported in `where` clauses + --> $DIR/feature-gate-type_equality_constraints.rs:9:22 + | +LL | impl Baz where T = i32 { + | ^^^^^^^ not supported + | + = help: add `#![feature(type_equality_constraints)]` to the crate attributes to enable + = note: see issue #20041 for more information + +error: aborting due to previous error + diff --git a/src/test/ui/feature-gates/feature-gate-type_equality_constraints.rs b/src/test/ui/feature-gates/feature-gate-type_equality_constraints.rs new file mode 100644 index 0000000000000..820d01ed0b622 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-type_equality_constraints.rs @@ -0,0 +1,17 @@ +// [feature] run-pass +// revisions: normal feature +#![cfg_attr(feature, feature(type_equality_constraints))] + +struct Baz { + _t: T, +} + +impl Baz where T = i32 { +//[normal]~^ ERROR equality constraints + fn resolved(self) {} +} + +fn main() { + let b = Baz{_t: 1i32}; + b.resolved(); +} diff --git a/src/test/ui/parser/bounds-type-where.rs b/src/test/ui/parser/bounds-type-where.rs index 2520ecb294c9a..c1ed4fa0a49f8 100644 --- a/src/test/ui/parser/bounds-type-where.rs +++ b/src/test/ui/parser/bounds-type-where.rs @@ -6,6 +6,6 @@ type A where T: Trait + Trait = u8; // OK type A where = u8; // OK type A where T: Trait + = u8; // OK type A where T, = u8; -//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` +//~^ ERROR expected one of `!`, `(`, `+`, `::`, `:`, `<`, or `=`, found `,` fn main() {} diff --git a/src/test/ui/parser/bounds-type-where.stderr b/src/test/ui/parser/bounds-type-where.stderr index 5636ee75c97a8..4490581cd365f 100644 --- a/src/test/ui/parser/bounds-type-where.stderr +++ b/src/test/ui/parser/bounds-type-where.stderr @@ -1,8 +1,8 @@ -error: expected one of `!`, `(`, `+`, `::`, `:`, `<`, `==`, or `=`, found `,` +error: expected one of `!`, `(`, `+`, `::`, `:`, `<`, or `=`, found `,` --> $DIR/bounds-type-where.rs:8:15 | LL | type A where T, = u8; - | ^ expected one of 8 possible tokens + | ^ expected one of 7 possible tokens error: aborting due to previous error diff --git a/src/test/ui/parser/issue-17904.rs b/src/test/ui/parser/issue-17904.rs index 7d6a54f4be12e..31b17628cd658 100644 --- a/src/test/ui/parser/issue-17904.rs +++ b/src/test/ui/parser/issue-17904.rs @@ -1,6 +1,6 @@ struct Baz where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax. struct Baz where U: Eq(U) -> R; // Notice this parses as well. struct Baz(U) where U: Eq; // This rightfully signals no error as well. -struct Foo where T: Copy, (T); //~ ERROR expected one of `:`, `==`, or `=`, found `;` +struct Foo where T: Copy, (T); //~ ERROR expected one of `:` or `=`, found `;` fn main() {} diff --git a/src/test/ui/parser/issue-17904.stderr b/src/test/ui/parser/issue-17904.stderr index a3cac676189c0..df316525fdb6f 100644 --- a/src/test/ui/parser/issue-17904.stderr +++ b/src/test/ui/parser/issue-17904.stderr @@ -1,8 +1,8 @@ -error: expected one of `:`, `==`, or `=`, found `;` +error: expected one of `:` or `=`, found `;` --> $DIR/issue-17904.rs:4:33 | LL | struct Foo where T: Copy, (T); - | ^ expected one of `:`, `==`, or `=` + | ^ expected one of `:` or `=` error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-eq-assoc.rs b/src/test/ui/where-clauses/where-eq-assoc.rs new file mode 100644 index 0000000000000..8c67f73fd3fa5 --- /dev/null +++ b/src/test/ui/where-clauses/where-eq-assoc.rs @@ -0,0 +1,29 @@ +#![feature(type_equality_constraints)] + +pub fn foo(mut t: T) -> T::Item + where T::Item = u32 +{ + t.next().unwrap() +} + +pub fn foo2(mut t: T) -> T::Item + where u32 = T::Item +{ + t.next().unwrap() +} + +pub fn foo3(mut t: T) -> u32 + where T::Item = u32 +{ + t.next().unwrap() + //~^ ERROR mismatched types +} + +pub fn foo4(mut t: T) -> u32 + where u32 = T::Item +{ + t.next().unwrap() + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/where-clauses/where-eq-assoc.stderr b/src/test/ui/where-clauses/where-eq-assoc.stderr new file mode 100644 index 0000000000000..1ecbcd230ddac --- /dev/null +++ b/src/test/ui/where-clauses/where-eq-assoc.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/where-eq-assoc.rs:18:5 + | +LL | pub fn foo3(mut t: T) -> u32 + | --- expected `u32` because of return type +... +LL | t.next().unwrap() + | ^^^^^^^^^^^^^^^^^ expected `u32`, found associated type + | + = note: expected type `u32` + found associated type `::Item` +help: consider constraining the associated type `::Item` to `u32` + | +LL | pub fn foo3>(mut t: T) -> u32 + | ^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/where-eq-assoc.rs:25:5 + | +LL | pub fn foo4(mut t: T) -> u32 + | --- expected `u32` because of return type +... +LL | t.next().unwrap() + | ^^^^^^^^^^^^^^^^^ expected `u32`, found associated type + | + = note: expected type `u32` + found associated type `::Item` +help: consider constraining the associated type `::Item` to `u32` + | +LL | pub fn foo4>(mut t: T) -> u32 + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/where-clauses/where-eq-double-eq.rs b/src/test/ui/where-clauses/where-eq-double-eq.rs new file mode 100644 index 0000000000000..d49177c0a2b96 --- /dev/null +++ b/src/test/ui/where-clauses/where-eq-double-eq.rs @@ -0,0 +1,4 @@ +pub fn foo() where T == u32 {} +//~^ ERROR type equality + +fn main() {} diff --git a/src/test/ui/where-clauses/where-eq-double-eq.stderr b/src/test/ui/where-clauses/where-eq-double-eq.stderr new file mode 100644 index 0000000000000..43ac15cc5281b --- /dev/null +++ b/src/test/ui/where-clauses/where-eq-double-eq.stderr @@ -0,0 +1,8 @@ +error: type equality predicates are `=` not `==` + --> $DIR/where-eq-double-eq.rs:1:23 + | +LL | pub fn foo() where T == u32 {} + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/where-clauses/where-eq-into-iter.rs b/src/test/ui/where-clauses/where-eq-into-iter.rs new file mode 100644 index 0000000000000..6cfc3db9d8145 --- /dev/null +++ b/src/test/ui/where-clauses/where-eq-into-iter.rs @@ -0,0 +1,13 @@ +// run-pass +#![feature(type_equality_constraints)] + +pub fn foo1() where T = Vec {} +pub fn foo2() where T::Item = u32 {} +pub fn foo3() where T::Item = u32, T = Vec {} +pub fn foo4() where T::Item = u32, T = Vec {} + +pub trait Bar {} +pub fn foo5() where T::Item = u32, T::Item: Bar {} +pub fn foo6() where T::Item: Bar, T::Item = u32 {} + +fn main() {} diff --git a/src/test/ui/where-clauses/where-eq-multiple.rs b/src/test/ui/where-clauses/where-eq-multiple.rs new file mode 100644 index 0000000000000..be49ae9aa28a9 --- /dev/null +++ b/src/test/ui/where-clauses/where-eq-multiple.rs @@ -0,0 +1,18 @@ +#![feature(type_equality_constraints)] + +// multiple types can compile, but can't actually be called +pub fn foo7() where T::Item = u64, T::Item = u32 {} + +pub fn foo8() where T = i32, T = i64, T = usize {} + +fn main() { + foo8::(); + //~^ ERROR mismatched types + //~| ERROR mismatched types + foo8::(); + //~^ ERROR mismatched types + //~| ERROR mismatched types + foo8::(); + //~^ ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/src/test/ui/where-clauses/where-eq-multiple.stderr b/src/test/ui/where-clauses/where-eq-multiple.stderr new file mode 100644 index 0000000000000..7198a7dbf8adb --- /dev/null +++ b/src/test/ui/where-clauses/where-eq-multiple.stderr @@ -0,0 +1,57 @@ +error[E0308]: mismatched types + --> $DIR/where-eq-multiple.rs:9:3 + | +LL | foo8::(); + | ^^^^^^^^^^^ expected `i32`, found `i64` + | + = note: expected type `i64` + found type `i32` + +error[E0308]: mismatched types + --> $DIR/where-eq-multiple.rs:9:3 + | +LL | foo8::(); + | ^^^^^^^^^^^ expected `i32`, found `usize` + | + = note: expected type `usize` + found type `i32` + +error[E0308]: mismatched types + --> $DIR/where-eq-multiple.rs:12:3 + | +LL | foo8::(); + | ^^^^^^^^^^^ expected `i64`, found `i32` + | + = note: expected type `i32` + found type `i64` + +error[E0308]: mismatched types + --> $DIR/where-eq-multiple.rs:12:3 + | +LL | foo8::(); + | ^^^^^^^^^^^ expected `i64`, found `usize` + | + = note: expected type `usize` + found type `i64` + +error[E0308]: mismatched types + --> $DIR/where-eq-multiple.rs:15:3 + | +LL | foo8::(); + | ^^^^^^^^^^^^^ expected `usize`, found `i32` + | + = note: expected type `i32` + found type `usize` + +error[E0308]: mismatched types + --> $DIR/where-eq-multiple.rs:15:3 + | +LL | foo8::(); + | ^^^^^^^^^^^^^ expected `usize`, found `i64` + | + = note: expected type `i64` + found type `usize` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/where-clauses/where-eq-rnd-params.rs b/src/test/ui/where-clauses/where-eq-rnd-params.rs new file mode 100644 index 0000000000000..e39eeeca3e41e --- /dev/null +++ b/src/test/ui/where-clauses/where-eq-rnd-params.rs @@ -0,0 +1,10 @@ +#![feature(type_equality_constraints)] + +pub fn foo(a: A) -> B + where A = B +{ + a + //~^ ERROR mismatched types +} + + fn main() {} diff --git a/src/test/ui/where-clauses/where-eq-rnd-params.stderr b/src/test/ui/where-clauses/where-eq-rnd-params.stderr new file mode 100644 index 0000000000000..1edfd2f18c16b --- /dev/null +++ b/src/test/ui/where-clauses/where-eq-rnd-params.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/where-eq-rnd-params.rs:6:5 + | +LL | pub fn foo(a: A) -> B + | - - - expected `B` because of return type + | | | + | | expected type parameter + | found type parameter +... +LL | a + | ^ expected type parameter `B`, found type parameter `A` + | + = note: expected type parameter `B` + found type parameter `A` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/where-clauses/where-eq-self.rs b/src/test/ui/where-clauses/where-eq-self.rs new file mode 100644 index 0000000000000..a3d3f62a9f7c5 --- /dev/null +++ b/src/test/ui/where-clauses/where-eq-self.rs @@ -0,0 +1,20 @@ +#![feature(type_equality_constraints)] + +pub struct Foo; + +impl Foo { + pub fn foo(&self) where T = Self {} +} + +pub trait Bar { + fn test() -> Self where T = Self; +} + +impl Bar for Foo { + fn test() -> Self where T = Self { + //~^ ERROR method not compatible with trait + Foo + } +} + +fn main() {} diff --git a/src/test/ui/where-clauses/where-eq-self.stderr b/src/test/ui/where-clauses/where-eq-self.stderr new file mode 100644 index 0000000000000..bdc78e7b6e8fe --- /dev/null +++ b/src/test/ui/where-clauses/where-eq-self.stderr @@ -0,0 +1,12 @@ +error[E0308]: method not compatible with trait + --> $DIR/where-eq-self.rs:14:5 + | +LL | fn test() -> Self where T = Self { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found struct `Foo` + | + = note: expected struct `Foo` + found type parameter `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/where-clauses/where-eq.rs b/src/test/ui/where-clauses/where-eq.rs new file mode 100644 index 0000000000000..cd9fa97a65045 --- /dev/null +++ b/src/test/ui/where-clauses/where-eq.rs @@ -0,0 +1,19 @@ +#![feature(type_equality_constraints)] + +trait Foo {} +struct Bar; +struct NotBar; +impl Foo for Bar {} +impl Foo for NotBar {} + +fn baz() where T = Bar {} +fn baz2() where T = i32 {} + +fn main() { + baz::(); + baz::(); + //~^ ERROR mismatched types + baz2::(); + baz2::(); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/where-clauses/where-eq.stderr b/src/test/ui/where-clauses/where-eq.stderr new file mode 100644 index 0000000000000..59682490accc5 --- /dev/null +++ b/src/test/ui/where-clauses/where-eq.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/where-eq.rs:14:3 + | +LL | baz::(); + | ^^^^^^^^^^^^^ expected struct `NotBar`, found struct `Bar` + | + = note: expected struct `Bar` + found struct `NotBar` + +error[E0308]: mismatched types + --> $DIR/where-eq.rs:17:3 + | +LL | baz2::(); + | ^^^^^^^^^^^ expected struct `Bar`, found `i32` + | + = note: expected type `i32` + found struct `Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/where-clauses/where-equality-constraints.rs b/src/test/ui/where-clauses/where-equality-constraints.rs index 8828f09d92d33..557954593b684 100644 --- a/src/test/ui/where-clauses/where-equality-constraints.rs +++ b/src/test/ui/where-clauses/where-equality-constraints.rs @@ -1,6 +1,8 @@ fn f() where u8 = u16 {} //~^ ERROR equality constraints are not yet supported in `where` clauses -fn g() where for<'a> &'static (u8,) == u16, {} +//~| ERROR mismatched types +fn g() where for<'a> &'static (u8,) = u16, {} //~^ ERROR equality constraints are not yet supported in `where` clauses +//~| ERROR mismatched types fn main() {} diff --git a/src/test/ui/where-clauses/where-equality-constraints.stderr b/src/test/ui/where-clauses/where-equality-constraints.stderr index 9d8fac02ed33b..9b0a6562eb740 100644 --- a/src/test/ui/where-clauses/where-equality-constraints.stderr +++ b/src/test/ui/where-clauses/where-equality-constraints.stderr @@ -4,15 +4,36 @@ error: equality constraints are not yet supported in `where` clauses LL | fn f() where u8 = u16 {} | ^^^^^^^^ not supported | + = help: add `#![feature(type_equality_constraints)]` to the crate attributes to enable = note: see issue #20041 for more information error: equality constraints are not yet supported in `where` clauses - --> $DIR/where-equality-constraints.rs:3:14 + --> $DIR/where-equality-constraints.rs:4:14 | -LL | fn g() where for<'a> &'static (u8,) == u16, {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported +LL | fn g() where for<'a> &'static (u8,) = u16, {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported | + = help: add `#![feature(type_equality_constraints)]` to the crate attributes to enable = note: see issue #20041 for more information -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/where-equality-constraints.rs:1:1 + | +LL | fn f() where u8 = u16 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `u16` + | + = note: expected type `u16` + found type `u8` + +error[E0308]: mismatched types + --> $DIR/where-equality-constraints.rs:4:1 + | +LL | fn g() where for<'a> &'static (u8,) = u16, {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&(u8,)`, found `u16` + | + = note: expected type `u16` + found reference `&'static (u8,)` + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 0e6ead675c247..fc3cebd3435fc 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -32,6 +32,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: Option<&Ru | ty::PredicateKind::Projection(_) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) + | ty::PredicateKind::TypeEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate), ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),