From 07659996221446273065651ff9c0fcb00935eb03 Mon Sep 17 00:00:00 2001 From: kadmin Date: Fri, 30 Jul 2021 08:56:45 +0000 Subject: [PATCH 1/7] add eq constraints on associated constants --- compiler/rustc_ast/src/ast.rs | 14 ++-- compiler/rustc_ast/src/mut_visit.rs | 19 +++-- compiler/rustc_ast/src/visit.rs | 18 ++--- compiler/rustc_ast_lowering/src/lib.rs | 9 ++- .../rustc_ast_passes/src/ast_validation.rs | 15 ++-- compiler/rustc_ast_passes/src/feature_gate.rs | 8 +-- compiler/rustc_ast_passes/src/node_count.rs | 4 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 10 ++- compiler/rustc_hir/src/hir.rs | 2 + compiler/rustc_hir/src/intravisit.rs | 5 +- compiler/rustc_hir_pretty/src/lib.rs | 4 ++ compiler/rustc_interface/src/util.rs | 5 +- compiler/rustc_middle/src/ty/mod.rs | 19 +++++ compiler/rustc_parse/src/parser/path.rs | 37 +++++----- compiler/rustc_passes/src/hir_stats.rs | 6 +- compiler/rustc_typeck/src/astconv/mod.rs | 17 ++++- compiler/rustc_typeck/src/bounds.rs | 69 +++++++++++++------ compiler/rustc_typeck/src/collect.rs | 2 +- .../rustc_typeck/src/collect/item_bounds.rs | 6 +- src/librustdoc/clean/mod.rs | 3 +- src/test/ui/associated-consts/assoc-const.rs | 14 ++++ .../clippy/clippy_utils/src/ast_utils.rs | 5 +- src/tools/rustfmt/src/types.rs | 17 ++--- 23 files changed, 195 insertions(+), 113 deletions(-) create mode 100644 src/test/ui/associated-consts/assoc-const.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 079b9e43373fa..9d447f3b5cb53 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -224,7 +224,7 @@ pub enum AngleBracketedArg { /// Argument for a generic parameter. Arg(GenericArg), /// Constraint for an associated item. - Constraint(AssocTyConstraint), + Constraint(AssocConstraint), } impl AngleBracketedArg { @@ -1843,19 +1843,21 @@ impl UintTy { /// A constraint on an associated type (e.g., `A = Bar` in `Foo` or /// `A: TraitA + TraitB` in `Foo`). #[derive(Clone, Encodable, Decodable, Debug)] -pub struct AssocTyConstraint { +pub struct AssocConstraint { pub id: NodeId, pub ident: Ident, pub gen_args: Option, - pub kind: AssocTyConstraintKind, + pub kind: AssocConstraintKind, pub span: Span, } -/// The kinds of an `AssocTyConstraint`. +/// The kinds of an `AssocConstraint`. #[derive(Clone, Encodable, Decodable, Debug)] -pub enum AssocTyConstraintKind { - /// E.g., `A = Bar` in `Foo`. +pub enum AssocConstraintKind { + /// E.g., `A = Bar` in `Foo` where A is an associated type. Equality { ty: P }, + /// E.g., `A = 3` in `Foo` where N is an associated const. + ConstEquality { c: AnonConst }, /// E.g. `A: TraitA + TraitB` in `Foo`. Bound { bounds: GenericBounds }, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 564a8a8c8729e..ba68ff691caed 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -165,8 +165,8 @@ pub trait MutVisitor: Sized { noop_visit_lifetime(l, self); } - fn visit_ty_constraint(&mut self, t: &mut AssocTyConstraint) { - noop_visit_ty_constraint(t, self); + fn visit_constraint(&mut self, t: &mut AssocConstraint) { + noop_visit_constraint(t, self); } fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) { @@ -430,8 +430,8 @@ pub fn noop_flat_map_arm(mut arm: Arm, vis: &mut T) -> SmallVec<[ smallvec![arm] } -pub fn noop_visit_ty_constraint( - AssocTyConstraint { id, ident, gen_args, kind, span }: &mut AssocTyConstraint, +pub fn noop_visit_constraint( + AssocConstraint { id, ident, gen_args, kind, span }: &mut AssocConstraint, vis: &mut T, ) { vis.visit_id(id); @@ -440,12 +440,9 @@ pub fn noop_visit_ty_constraint( vis.visit_generic_args(gen_args); } match kind { - AssocTyConstraintKind::Equality { ref mut ty } => { - vis.visit_ty(ty); - } - AssocTyConstraintKind::Bound { ref mut bounds } => { - visit_bounds(bounds, vis); - } + AssocConstraintKind::Equality { ref mut ty } => vis.visit_ty(ty), + AssocConstraintKind::ConstEquality { ref mut c } => vis.visit_anon_const(c), + AssocConstraintKind::Bound { ref mut bounds } => visit_bounds(bounds, vis), } vis.visit_span(span); } @@ -555,7 +552,7 @@ pub fn noop_visit_angle_bracketed_parameter_data( let AngleBracketedArgs { args, span } = data; visit_vec(args, |arg| match arg { AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg), - AngleBracketedArg::Constraint(constraint) => vis.visit_ty_constraint(constraint), + AngleBracketedArg::Constraint(constraint) => vis.visit_constraint(constraint), }); vis.visit_span(span); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 0b95270a4e1ef..f054f4de2f9d0 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -190,8 +190,8 @@ pub trait Visitor<'ast>: Sized { fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) { walk_generic_arg(self, generic_arg) } - fn visit_assoc_ty_constraint(&mut self, constraint: &'ast AssocTyConstraint) { - walk_assoc_ty_constraint(self, constraint) + fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) { + walk_assoc_constraint(self, constraint) } fn visit_attribute(&mut self, attr: &'ast Attribute) { walk_attribute(self, attr) @@ -464,7 +464,7 @@ where for arg in &data.args { match arg { AngleBracketedArg::Arg(a) => visitor.visit_generic_arg(a), - AngleBracketedArg::Constraint(c) => visitor.visit_assoc_ty_constraint(c), + AngleBracketedArg::Constraint(c) => visitor.visit_assoc_constraint(c), } } } @@ -486,19 +486,15 @@ where } } -pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>( - visitor: &mut V, - constraint: &'a AssocTyConstraint, -) { +pub fn walk_assoc_constraint<'a, V: Visitor<'a>>(visitor: &mut V, constraint: &'a AssocConstraint) { visitor.visit_ident(constraint.ident); if let Some(ref gen_args) = constraint.gen_args { visitor.visit_generic_args(gen_args.span(), gen_args); } match constraint.kind { - AssocTyConstraintKind::Equality { ref ty } => { - visitor.visit_ty(ty); - } - AssocTyConstraintKind::Bound { ref bounds } => { + AssocConstraintKind::Equality { ref ty } => visitor.visit_ty(ty), + AssocConstraintKind::ConstEquality { ref c } => visitor.visit_anon_const(c), + AssocConstraintKind::Bound { ref bounds } => { walk_list!(visitor, visit_param_bound, bounds); } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 35eb716949a13..450f42385848e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -960,7 +960,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// returns a `hir::TypeBinding` representing `Item`. fn lower_assoc_ty_constraint( &mut self, - constraint: &AssocTyConstraint, + constraint: &AssocConstraint, mut itctx: ImplTraitContext<'_, 'hir>, ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); @@ -997,10 +997,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; let kind = match constraint.kind { - AssocTyConstraintKind::Equality { ref ty } => { + AssocConstraintKind::Equality { ref ty } => { hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) } } - AssocTyConstraintKind::Bound { ref bounds } => { + AssocConstraintKind::ConstEquality { ref c } => { + hir::TypeBindingKind::Const { c: self.lower_anon_const(c) } + } + AssocConstraintKind::Bound { ref bounds } => { let mut capturable_lifetimes; let mut parent_def_id = self.current_hir_id_owner; // Piggy-back on the `impl Trait` context to figure out the correct behavior. diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 45920bb27d5b6..2c575cfdbdceb 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -138,10 +138,11 @@ impl<'a> AstValidator<'a> { self.outer_impl_trait = old; } - fn visit_assoc_ty_constraint_from_generic_args(&mut self, constraint: &'a AssocTyConstraint) { + fn visit_assoc_constraint_from_generic_args(&mut self, constraint: &'a AssocConstraint) { match constraint.kind { - AssocTyConstraintKind::Equality { .. } => {} - AssocTyConstraintKind::Bound { .. } => { + AssocConstraintKind::Equality { .. } => {} + AssocConstraintKind::ConstEquality { .. } => {} + AssocConstraintKind::Bound { .. } => { if self.is_assoc_ty_bound_banned { self.err_handler().span_err( constraint.span, @@ -150,7 +151,7 @@ impl<'a> AstValidator<'a> { } } } - self.visit_assoc_ty_constraint(constraint); + self.visit_assoc_constraint(constraint); } // Mirrors `visit::walk_ty`, but tracks relevant state. @@ -1277,7 +1278,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // are allowed to contain nested `impl Trait`. AngleBracketedArg::Constraint(constraint) => { self.with_impl_trait(None, |this| { - this.visit_assoc_ty_constraint_from_generic_args(constraint); + this.visit_assoc_constraint_from_generic_args(constraint); }); } } @@ -1586,11 +1587,11 @@ fn deny_equality_constraints( let len = assoc_path.segments.len() - 1; let gen_args = args.as_ref().map(|p| (**p).clone()); // Build ``. - let arg = AngleBracketedArg::Constraint(AssocTyConstraint { + let arg = AngleBracketedArg::Constraint(AssocConstraint { id: rustc_ast::node_id::DUMMY_NODE_ID, ident: *ident, gen_args, - kind: AssocTyConstraintKind::Equality { + kind: AssocConstraintKind::Equality { ty: predicate.rhs_ty.clone(), }, span: ident.span, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 85e35c942b903..0cc74a1ac0b62 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -1,6 +1,6 @@ use rustc_ast as ast; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; -use rustc_ast::{AssocTyConstraint, AssocTyConstraintKind, NodeId}; +use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId}; use rustc_ast::{PatKind, RangeEnd, VariantData}; use rustc_errors::struct_span_err; use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; @@ -622,8 +622,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_fn(self, fn_kind, span) } - fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) { - if let AssocTyConstraintKind::Bound { .. } = constraint.kind { + fn visit_assoc_constraint(&mut self, constraint: &'a AssocConstraint) { + if let AssocConstraintKind::Bound { .. } = constraint.kind { gate_feature_post!( &self, associated_type_bounds, @@ -631,7 +631,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "associated type bounds are unstable" ) } - visit::walk_assoc_ty_constraint(self, constraint) + visit::walk_assoc_constraint(self, constraint) } fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { diff --git a/compiler/rustc_ast_passes/src/node_count.rs b/compiler/rustc_ast_passes/src/node_count.rs index 3980e6da68250..a4a48cc8e8a7f 100644 --- a/compiler/rustc_ast_passes/src/node_count.rs +++ b/compiler/rustc_ast_passes/src/node_count.rs @@ -126,9 +126,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_generic_args(self, path_span, generic_args) } - fn visit_assoc_ty_constraint(&mut self, constraint: &AssocTyConstraint) { + fn visit_assoc_constraint(&mut self, constraint: &AssocConstraint) { self.count += 1; - walk_assoc_ty_constraint(self, constraint) + walk_assoc_constraint(self, constraint) } fn visit_attribute(&mut self, _attr: &Attribute) { self.count += 1; diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index dab2e1f5ee14b..381860244678d 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -952,16 +952,20 @@ impl<'a> State<'a> { } } - pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocTyConstraint) { + pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocConstraint) { self.print_ident(constraint.ident); constraint.gen_args.as_ref().map(|args| self.print_generic_args(args, false)); self.space(); match &constraint.kind { - ast::AssocTyConstraintKind::Equality { ty } => { + ast::AssocConstraintKind::Equality { ty } => { self.word_space("="); self.print_type(ty); } - ast::AssocTyConstraintKind::Bound { bounds } => { + ast::AssocConstraintKind::ConstEquality { c } => { + self.word_space("="); + self.print_expr_anon_const(c); + } + ast::AssocConstraintKind::Bound { bounds } => { self.print_type_bounds(":", &*bounds); } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 369b5e6da2d28..039bb0db0aa79 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2136,6 +2136,8 @@ pub enum TypeBindingKind<'hir> { Constraint { bounds: &'hir [GenericBound<'hir>] }, /// E.g., `Foo`. Equality { ty: &'hir Ty<'hir> }, + /// E.g., `Foo`. + Const { c: AnonConst }, } impl TypeBinding<'_> { diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 52c0538f1bcfc..56b32cde9d54f 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -827,9 +827,8 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>( visitor.visit_ident(type_binding.ident); visitor.visit_generic_args(type_binding.span, type_binding.gen_args); match type_binding.kind { - TypeBindingKind::Equality { ref ty } => { - visitor.visit_ty(ty); - } + TypeBindingKind::Equality { ref ty } => visitor.visit_ty(ty), + TypeBindingKind::Const { ref c } => visitor.visit_anon_const(c), TypeBindingKind::Constraint { bounds } => { walk_list!(visitor, visit_param_bound, bounds); } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 7675778ff881b..a76af35a8e626 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1756,6 +1756,10 @@ impl<'a> State<'a> { self.word_space("="); self.print_type(ty); } + hir::TypeBindingKind::Const { ref c } => { + self.word_space("="); + self.print_anon_const(c); + } hir::TypeBindingKind::Constraint { bounds } => { self.print_bounds(":", bounds); } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index cb51555f5cadf..abecc8d1a8be5 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -738,8 +738,9 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { | ast::GenericArg::Const(_) => false, }, ast::AngleBracketedArg::Constraint(c) => match c.kind { - ast::AssocTyConstraintKind::Bound { .. } => true, - ast::AssocTyConstraintKind::Equality { ref ty } => { + ast::AssocConstraintKind::Bound { .. } => true, + ast::AssocConstraintKind::ConstEquality { .. } => false, + ast::AssocConstraintKind::Equality { ref ty } => { involves_impl_trait(ty) } }, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d6e89e52b95ed..9e7e8dc838af3 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -814,6 +814,25 @@ pub struct ProjectionPredicate<'tcx> { pub ty: Ty<'tcx>, } +/// This kind of predicate has no *direct* correspondent in the +/// syntax, but it roughly corresponds to the syntactic forms: +/// +/// 1. `T: TraitRef<..., Item = Const>` +/// 2. `>::Item == Const` (NYI) +/// +/// In particular, form #1 is "desugared" to the combination of a +/// normal trait predicate (`T: TraitRef<...>`) and one of these +/// predicates. Form #2 is a broader form in that it also permits +/// equality between arbitrary types. Processing an instance of +/// Form #2 eventually yields one of these `ProjectionPredicate` +/// instances to normalize the LHS. +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug)] +#[derive(HashStable, TypeFoldable)] +pub struct ConstPredicate<'tcx> { + pub projection: ProjectionTy<'tcx>, + pub c: &'tcx Const<'tcx>, +} + pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; impl<'tcx> PolyProjectionPredicate<'tcx> { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 7f8fadb33bd8a..7c2d8ba21a26c 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -4,8 +4,8 @@ use crate::maybe_whole; use rustc_ast::ptr::P; use rustc_ast::token::{self, Token}; use rustc_ast::{ - self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocTyConstraint, - AssocTyConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, + self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocConstraint, + AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, Path, PathSegment, QSelf, }; use rustc_errors::{pluralize, Applicability, PResult}; @@ -469,12 +469,9 @@ impl<'a> Parser<'a> { // Parse associated type constraint bound. let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?; - AssocTyConstraintKind::Bound { bounds } + AssocConstraintKind::Bound { bounds } } else if self.eat(&token::Eq) { - // Parse associated type equality constraint - - let ty = self.parse_assoc_equality_term(ident, self.prev_token.span)?; - AssocTyConstraintKind::Equality { ty } + self.parse_assoc_equality_term(ident, self.prev_token.span)? } else { unreachable!(); }; @@ -482,11 +479,11 @@ impl<'a> Parser<'a> { let span = lo.to(self.prev_token.span); // Gate associated type bounds, e.g., `Iterator`. - if let AssocTyConstraintKind::Bound { .. } = kind { + if let AssocConstraintKind::Bound { .. } = kind { self.sess.gated_spans.gate(sym::associated_type_bounds, span); } let constraint = - AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span }; + AssocConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span }; Ok(Some(AngleBracketedArg::Constraint(constraint))) } else { Ok(Some(AngleBracketedArg::Arg(arg))) @@ -499,22 +496,22 @@ impl<'a> Parser<'a> { /// Parse the term to the right of an associated item equality constraint. /// That is, parse `` in `Item = `. /// Right now, this only admits types in ``. - fn parse_assoc_equality_term(&mut self, ident: Ident, eq: Span) -> PResult<'a, P> { + fn parse_assoc_equality_term( + &mut self, + ident: Ident, + eq: Span, + ) -> PResult<'a, AssocConstraintKind> { let arg = self.parse_generic_arg(None)?; let span = ident.span.to(self.prev_token.span); - match arg { - Some(GenericArg::Type(ty)) => return Ok(ty), - Some(GenericArg::Const(expr)) => { - self.struct_span_err(span, "cannot constrain an associated constant to a value") - .span_label(ident.span, "this associated constant...") - .span_label(expr.value.span, "...cannot be constrained to this value") - .emit(); - } + let ty = match arg { + Some(GenericArg::Type(ty)) => ty, + Some(GenericArg::Const(c)) => return Ok(AssocConstraintKind::ConstEquality { c }), Some(GenericArg::Lifetime(lt)) => { self.struct_span_err(span, "associated lifetimes are not supported") .span_label(lt.ident.span, "the lifetime is given here") .help("if you meant to specify a trait object, write `dyn Trait + 'lifetime`") .emit(); + self.mk_ty(span, ast::TyKind::Err) } None => { let after_eq = eq.shrink_to_hi(); @@ -542,8 +539,8 @@ impl<'a> Parser<'a> { }; return Err(err); } - } - Ok(self.mk_ty(span, ast::TyKind::Err)) + }; + Ok(AssocConstraintKind::Equality { ty }) } /// We do not permit arbitrary expressions as const arguments. They must be one of: diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index d665c12f762c5..963a625aaeada 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -338,9 +338,9 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_path_segment(self, path_span, path_segment) } - fn visit_assoc_ty_constraint(&mut self, constraint: &'v ast::AssocTyConstraint) { - self.record("AssocTyConstraint", Id::None, constraint); - ast_visit::walk_assoc_ty_constraint(self, constraint) + fn visit_assoc_constraint(&mut self, constraint: &'v ast::AssocConstraint) { + self.record("AssocConstraint", Id::None, constraint); + ast_visit::walk_assoc_constraint(self, constraint) } fn visit_attribute(&mut self, attr: &'v ast::Attribute) { diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 2ada1c0ddf4fa..2d847f6145d6f 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -124,6 +124,7 @@ struct ConvertedBinding<'a, 'tcx> { #[derive(Debug)] enum ConvertedBindingKind<'a, 'tcx> { Equality(Ty<'tcx>), + Const(&'tcx Const<'tcx>), Constraint(&'a [hir::GenericBound<'a>]), } @@ -604,7 +605,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TypeBindingKind::Equality { ty } => { ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty)) } - hir::TypeBindingKind::Constraint { bounds } => { + hir::TypeBindingKind::Const { ref c } => { + let local_did = self.tcx().hir().local_def_id(c.hir_id); + let c = Const::from_anon_const(self.tcx(), local_did); + ConvertedBindingKind::Const(&c) + } + hir::TypeBindingKind::Constraint { ref bounds } => { ConvertedBindingKind::Constraint(bounds) } }; @@ -1231,6 +1237,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { binding.span, )); } + ConvertedBindingKind::Const(c) => { + bounds.const_bounds.push(( + projection_ty.map_bound(|projection_ty| ty::ConstPredicate { + projection: projection_ty, + c, + }), + binding.span, + )); + } ConvertedBindingKind::Constraint(ast_bounds) => { // "Desugar" a constraint like `T: Iterator` to // diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 8bc3a48e5b506..47c3ea5457578 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -37,6 +37,12 @@ pub struct Bounds<'tcx> { /// here. pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>, + /// A list of const equality bounds. So if you had `T: + /// Iterator` this would include `::N => 4`. Note that the self-type is explicit + /// here. + pub const_bounds: Vec<(ty::Binder<'tcx, ty::ConstPredicate<'tcx>>, Span)>, + /// `Some` if there is *no* `?Sized` predicate. The `span` /// is the location in the source of the `T` declaration which can /// be cited as the source of the `T: Sized` requirement. @@ -48,14 +54,19 @@ impl<'tcx> Bounds<'tcx> { /// where-clauses). Because some of our bounds listings (e.g., /// regions) don't include the self-type, you must supply the /// self-type here (the `param_ty` parameter). - pub fn predicates( - &self, + pub fn predicates<'out, 's>( + &'s self, tcx: TyCtxt<'tcx>, param_ty: Ty<'tcx>, - ) -> Vec<(ty::Predicate<'tcx>, Span)> { + // the output must live shorter than the duration of the borrow of self and 'tcx. + ) -> impl Iterator, Span)> + 'out + where + 'tcx: 'out, + 's: 'out, + { // If it could be sized, and is, add the `Sized` predicate. let sized_predicate = self.implicitly_sized.and_then(|span| { - tcx.lang_items().sized_trait().map(|sized| { + tcx.lang_items().sized_trait().map(move |sized| { let trait_ref = ty::Binder::dummy(ty::TraitRef { def_id: sized, substs: tcx.mk_substs_trait(param_ty, &[]), @@ -64,25 +75,39 @@ impl<'tcx> Bounds<'tcx> { }) }); - sized_predicate - .into_iter() - .chain(self.region_bounds.iter().map(|&(region_bound, span)| { - ( - region_bound - .map_bound(|region_bound| ty::OutlivesPredicate(param_ty, region_bound)) - .to_predicate(tcx), - span, - ) - })) - .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| { + let region_preds = self.region_bounds.iter().map(move |&(region_bound, span)| { + let pred = region_bound + .map_bound(|region_bound| ty::OutlivesPredicate(param_ty, region_bound)) + .to_predicate(tcx); + (pred, span) + }); + let trait_bounds = + self.trait_bounds.iter().map(move |&(bound_trait_ref, span, constness)| { let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx); (predicate, span) - })) - .chain( - self.projection_bounds - .iter() - .map(|&(projection, span)| (projection.to_predicate(tcx), span)), - ) - .collect() + }); + let projection_bounds = self + .projection_bounds + .iter() + .map(move |&(projection, span)| (projection.to_predicate(tcx), span)); + let const_bounds = self.const_bounds.iter().map(move |&(bound, span)| { + // FIXME(...): what about the projection's generics? + // Is this the right local defid? Or should I get the self ty then + let pred = bound + .map_bound(|cp| { + let got = + ty::Const::from_anon_const(tcx, cp.projection.item_def_id.expect_local()); + ty::PredicateKind::ConstEquate(cp.c, got) + }) + .to_predicate(tcx); + (pred, span) + }); + + sized_predicate + .into_iter() + .chain(region_preds) + .chain(trait_bounds) + .chain(projection_bounds) + .chain(const_bounds) } } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index fbb630004cacd..7cb100a0a83f0 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2450,7 +2450,7 @@ fn predicates_from_bound<'tcx>( ) -> Vec<(ty::Predicate<'tcx>, Span)> { let mut bounds = Bounds::default(); astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars); - bounds.predicates(astconv.tcx(), param_ty) + bounds.predicates(astconv.tcx(), param_ty).collect() } fn compute_sig_of_foreign_fn_decl<'tcx>( diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 26cad8fb18058..6d992629a00ff 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -67,11 +67,11 @@ fn opaque_type_bounds<'tcx>( let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); // Opaque types are implicitly sized unless a `?Sized` bound is found >::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); - let bounds = bounds.predicates(tcx, item_ty); + let preds = bounds.predicates(tcx, item_ty); + let bounds = tcx.arena.alloc_from_iter(preds); debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds); - - tcx.arena.alloc_slice(&bounds) + bounds }) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a5bc70a74ae92..169cb618a7d93 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2117,7 +2117,8 @@ impl Clean for hir::TypeBindingKind<'_> { hir::TypeBindingKind::Equality { ref ty } => { TypeBindingKind::Equality { ty: ty.clean(cx) } } - hir::TypeBindingKind::Constraint { bounds } => TypeBindingKind::Constraint { + hir::TypeBindingKind::Const { c: _ } => todo!(), + hir::TypeBindingKind::Constraint { ref bounds } => TypeBindingKind::Constraint { bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(), }, } diff --git a/src/test/ui/associated-consts/assoc-const.rs b/src/test/ui/associated-consts/assoc-const.rs new file mode 100644 index 0000000000000..9332d16afe54f --- /dev/null +++ b/src/test/ui/associated-consts/assoc-const.rs @@ -0,0 +1,14 @@ +// run-pass + +pub trait Foo { + const N: usize; +} + +pub struct Bar; + +impl Foo for Bar { + const N: usize = 3; +} + +fn foo>() {} +fn main() {} diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 3d3180521ab7a..d4f037677e089 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -645,12 +645,13 @@ pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool { } } -pub fn eq_assoc_constraint(l: &AssocTyConstraint, r: &AssocTyConstraint) -> bool { - use AssocTyConstraintKind::*; +pub fn eq_assoc_constraint(l: &AssocConstraint, r: &AssocConstraint) -> bool { + use AssocConstraintKind::*; eq_id(l.ident, r.ident) && match (&l.kind, &r.kind) { (Equality { ty: l }, Equality { ty: r }) => eq_ty(l, r), (Bound { bounds: l }, Bound { bounds: r }) => over(l, r, eq_generic_bound), + (ConstEquality { c: l }, ConstEquality { c: r }) => eq_anon_const(l, r), _ => false, } } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 88f5dc4324510..4bad9742a0ef4 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -141,7 +141,7 @@ pub(crate) enum SegmentParam<'a> { Const(&'a ast::AnonConst), LifeTime(&'a ast::Lifetime), Type(&'a ast::Ty), - Binding(&'a ast::AssocTyConstraint), + Binding(&'a ast::AssocConstraint), } impl<'a> SegmentParam<'a> { @@ -176,9 +176,9 @@ impl<'a> Rewrite for SegmentParam<'a> { } } -impl Rewrite for ast::AssocTyConstraint { +impl Rewrite for ast::AssocConstraint { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - use ast::AssocTyConstraintKind::{Bound, Equality}; + use ast::AssocConstraintKind::{Bound, Equality, ConstEquality}; let mut result = String::with_capacity(128); result.push_str(rewrite_ident(context, self.ident)); @@ -192,8 +192,8 @@ impl Rewrite for ast::AssocTyConstraint { let infix = match (&self.kind, context.config.type_punctuation_density()) { (Bound { .. }, _) => ": ", - (Equality { .. }, TypeDensity::Wide) => " = ", - (Equality { .. }, TypeDensity::Compressed) => "=", + (ConstEquality { .. } | Equality { .. }, TypeDensity::Wide) => " = ", + (ConstEquality { .. } | Equality { .. }, TypeDensity::Compressed) => "=", }; result.push_str(infix); @@ -206,11 +206,12 @@ impl Rewrite for ast::AssocTyConstraint { } } -impl Rewrite for ast::AssocTyConstraintKind { +impl Rewrite for ast::AssocConstraintKind { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self { - ast::AssocTyConstraintKind::Equality { ty } => ty.rewrite(context, shape), - ast::AssocTyConstraintKind::Bound { bounds } => bounds.rewrite(context, shape), + ast::AssocConstraintKind::Equality { ty } => ty.rewrite(context, shape), + ast::AssocConstraintKind::ConstEquality { c } => c.rewrite(context, shape), + ast::AssocConstraintKind::Bound { bounds } => bounds.rewrite(context, shape), } } } From fb57b7518d207caa99bdd99f4dab2a7d3902a83a Mon Sep 17 00:00:00 2001 From: kadmin Date: Fri, 7 Jan 2022 03:58:32 +0000 Subject: [PATCH 2/7] Add term Instead of having a separate enum variant for types and consts have one but have either a const or type. --- compiler/rustc_ast/src/ast.rs | 25 ++++++++++++++++--- compiler/rustc_ast/src/mut_visit.rs | 6 +++-- compiler/rustc_ast/src/visit.rs | 6 +++-- compiler/rustc_ast_lowering/src/lib.rs | 10 +++----- .../rustc_ast_passes/src/ast_validation.rs | 3 +-- compiler/rustc_ast_pretty/src/pprust/state.rs | 13 +++++----- compiler/rustc_interface/src/util.rs | 10 +++++--- compiler/rustc_middle/src/ty/mod.rs | 1 + compiler/rustc_parse/src/parser/path.rs | 6 +++-- .../clippy/clippy_utils/src/ast_utils.rs | 11 ++++++-- src/tools/rustfmt/src/types.rs | 14 ++++++----- 11 files changed, 68 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 9d447f3b5cb53..d0732b35b6e9e 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1851,13 +1851,30 @@ pub struct AssocConstraint { pub span: Span, } +/// The kinds of an `AssocConstraint`. +#[derive(Clone, Encodable, Decodable, Debug)] +pub enum Term { + Ty(P), + Const(AnonConst), +} + +impl From> for Term { + fn from(v: P) -> Self { + Term::Ty(v) + } +} + +impl From for Term { + fn from(v: AnonConst) -> Self { + Term::Const(v) + } +} + /// The kinds of an `AssocConstraint`. #[derive(Clone, Encodable, Decodable, Debug)] pub enum AssocConstraintKind { - /// E.g., `A = Bar` in `Foo` where A is an associated type. - Equality { ty: P }, - /// E.g., `A = 3` in `Foo` where N is an associated const. - ConstEquality { c: AnonConst }, + /// E.g., `A = Bar`, `A = 3` in `Foo` where A is an associated type. + Equality { term: Term }, /// E.g. `A: TraitA + TraitB` in `Foo`. Bound { bounds: GenericBounds }, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index ba68ff691caed..a81a227629539 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -440,8 +440,10 @@ pub fn noop_visit_constraint( vis.visit_generic_args(gen_args); } match kind { - AssocConstraintKind::Equality { ref mut ty } => vis.visit_ty(ty), - AssocConstraintKind::ConstEquality { ref mut c } => vis.visit_anon_const(c), + AssocConstraintKind::Equality { ref mut term } => match term { + Term::Ty(ty) => vis.visit_ty(ty), + Term::Const(c) => vis.visit_anon_const(c), + }, AssocConstraintKind::Bound { ref mut bounds } => visit_bounds(bounds, vis), } vis.visit_span(span); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index f054f4de2f9d0..73e9297549cd4 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -492,8 +492,10 @@ pub fn walk_assoc_constraint<'a, V: Visitor<'a>>(visitor: &mut V, constraint: &' visitor.visit_generic_args(gen_args.span(), gen_args); } match constraint.kind { - AssocConstraintKind::Equality { ref ty } => visitor.visit_ty(ty), - AssocConstraintKind::ConstEquality { ref c } => visitor.visit_anon_const(c), + AssocConstraintKind::Equality { ref term } => match term { + Term::Ty(ty) => visitor.visit_ty(ty), + Term::Const(c) => visitor.visit_anon_const(c), + }, AssocConstraintKind::Bound { ref bounds } => { walk_list!(visitor, visit_param_bound, bounds); } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 450f42385848e..9a8a097ee249c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -997,12 +997,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; let kind = match constraint.kind { - AssocConstraintKind::Equality { ref ty } => { - hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) } - } - AssocConstraintKind::ConstEquality { ref c } => { - hir::TypeBindingKind::Const { c: self.lower_anon_const(c) } - } + AssocConstraintKind::Equality { ref term } => match term { + Term::Ty(ref ty) => hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) }, + Term::Const(ref c) => hir::TypeBindingKind::Const { c: self.lower_anon_const(c) }, + }, AssocConstraintKind::Bound { ref bounds } => { let mut capturable_lifetimes; let mut parent_def_id = self.current_hir_id_owner; diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 2c575cfdbdceb..eb7c75cac0520 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -141,7 +141,6 @@ impl<'a> AstValidator<'a> { fn visit_assoc_constraint_from_generic_args(&mut self, constraint: &'a AssocConstraint) { match constraint.kind { AssocConstraintKind::Equality { .. } => {} - AssocConstraintKind::ConstEquality { .. } => {} AssocConstraintKind::Bound { .. } => { if self.is_assoc_ty_bound_banned { self.err_handler().span_err( @@ -1592,7 +1591,7 @@ fn deny_equality_constraints( ident: *ident, gen_args, kind: AssocConstraintKind::Equality { - ty: predicate.rhs_ty.clone(), + term: predicate.rhs_ty.clone().into(), }, span: ident.span, }); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 381860244678d..3c45b5790fb47 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1,7 +1,6 @@ use crate::pp::Breaks::{Consistent, Inconsistent}; use crate::pp::{self, Breaks}; -use rustc_ast::attr; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, CommentKind, DelimToken, Nonterminal, Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; @@ -9,6 +8,7 @@ use rustc_ast::util::classify; use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle}; use rustc_ast::util::parser::{self, AssocOp, Fixity}; use rustc_ast::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}; +use rustc_ast::{attr, Term}; use rustc_ast::{GenericArg, MacArgs, ModKind}; use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier}; use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass}; @@ -957,13 +957,12 @@ impl<'a> State<'a> { constraint.gen_args.as_ref().map(|args| self.print_generic_args(args, false)); self.space(); match &constraint.kind { - ast::AssocConstraintKind::Equality { ty } => { + ast::AssocConstraintKind::Equality { term } => { self.word_space("="); - self.print_type(ty); - } - ast::AssocConstraintKind::ConstEquality { c } => { - self.word_space("="); - self.print_expr_anon_const(c); + match term { + Term::Ty(ty) => self.print_type(ty), + Term::Const(c) => self.print_expr_anon_const(c), + } } ast::AssocConstraintKind::Bound { bounds } => { self.print_type_bounds(":", &*bounds); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index abecc8d1a8be5..0d1081ee26b77 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -1,7 +1,7 @@ use libloading::Library; use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *}; use rustc_ast::ptr::P; -use rustc_ast::{self as ast, AttrVec, BlockCheckMode}; +use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Term}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[cfg(parallel_compiler)] @@ -739,9 +739,11 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { }, ast::AngleBracketedArg::Constraint(c) => match c.kind { ast::AssocConstraintKind::Bound { .. } => true, - ast::AssocConstraintKind::ConstEquality { .. } => false, - ast::AssocConstraintKind::Equality { ref ty } => { - involves_impl_trait(ty) + ast::AssocConstraintKind::Equality { ref term } => { + match term { + Term::Ty(ty) => involves_impl_trait(ty), + Term::Const(_) => false, + } } }, }) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9e7e8dc838af3..72e4e26dd3ee7 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -799,6 +799,7 @@ pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; /// syntax, but it roughly corresponds to the syntactic forms: /// /// 1. `T: TraitRef<..., Item = Type>` +/// - Or `T: TraitRef<..., Item = Const>` /// 2. `>::Item == Type` (NYI) /// /// In particular, form #1 is "desugared" to the combination of a diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 7c2d8ba21a26c..8f272820015b2 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -505,7 +505,9 @@ impl<'a> Parser<'a> { let span = ident.span.to(self.prev_token.span); let ty = match arg { Some(GenericArg::Type(ty)) => ty, - Some(GenericArg::Const(c)) => return Ok(AssocConstraintKind::ConstEquality { c }), + Some(GenericArg::Const(c)) => { + return Ok(AssocConstraintKind::Equality { term: c.into() }); + } Some(GenericArg::Lifetime(lt)) => { self.struct_span_err(span, "associated lifetimes are not supported") .span_label(lt.ident.span, "the lifetime is given here") @@ -540,7 +542,7 @@ impl<'a> Parser<'a> { return Err(err); } }; - Ok(AssocConstraintKind::Equality { ty }) + Ok(AssocConstraintKind::Equality { term: ty.into() }) } /// We do not permit arbitrary expressions as const arguments. They must be one of: diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index d4f037677e089..604c95d2bc81f 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -645,13 +645,20 @@ pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool { } } +fn eq_term(l: &Term, r: &Term) -> bool { + match (l, r) { + (Term::Ty(l), Term::Ty(r)) => eq_ty(l,r), + (Term::Const(l), Term::Const(r)) => eq_anon_const(l,r), + _ => false, + } +} + pub fn eq_assoc_constraint(l: &AssocConstraint, r: &AssocConstraint) -> bool { use AssocConstraintKind::*; eq_id(l.ident, r.ident) && match (&l.kind, &r.kind) { - (Equality { ty: l }, Equality { ty: r }) => eq_ty(l, r), + (Equality { term: l }, Equality { term: r }) => eq_term(l, r), (Bound { bounds: l }, Bound { bounds: r }) => over(l, r, eq_generic_bound), - (ConstEquality { c: l }, ConstEquality { c: r }) => eq_anon_const(l, r), _ => false, } } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 4bad9742a0ef4..9d5f790e80956 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1,7 +1,7 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; -use rustc_ast::ast::{self, FnRetTy, Mutability}; +use rustc_ast::ast::{self, FnRetTy, Mutability, Term}; use rustc_ast::ptr; use rustc_span::{symbol::kw, BytePos, Pos, Span}; @@ -178,7 +178,7 @@ impl<'a> Rewrite for SegmentParam<'a> { impl Rewrite for ast::AssocConstraint { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - use ast::AssocConstraintKind::{Bound, Equality, ConstEquality}; + use ast::AssocConstraintKind::{Bound, Equality}; let mut result = String::with_capacity(128); result.push_str(rewrite_ident(context, self.ident)); @@ -192,8 +192,8 @@ impl Rewrite for ast::AssocConstraint { let infix = match (&self.kind, context.config.type_punctuation_density()) { (Bound { .. }, _) => ": ", - (ConstEquality { .. } | Equality { .. }, TypeDensity::Wide) => " = ", - (ConstEquality { .. } | Equality { .. }, TypeDensity::Compressed) => "=", + (Equality { .. }, TypeDensity::Wide) => " = ", + (Equality { .. }, TypeDensity::Compressed) => "=", }; result.push_str(infix); @@ -209,8 +209,10 @@ impl Rewrite for ast::AssocConstraint { impl Rewrite for ast::AssocConstraintKind { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self { - ast::AssocConstraintKind::Equality { ty } => ty.rewrite(context, shape), - ast::AssocConstraintKind::ConstEquality { c } => c.rewrite(context, shape), + ast::AssocConstraintKind::Equality { term } => match term { + Term::Ty(ty) => ty.rewrite(context, shape), + Term::Const(c) => c.rewrite(context,shape), + }, ast::AssocConstraintKind::Bound { bounds } => bounds.rewrite(context, shape), } } From 67f56671d0384bdb2d92dddebfbf42510b16e0f7 Mon Sep 17 00:00:00 2001 From: kadmin Date: Sat, 8 Jan 2022 09:28:12 +0000 Subject: [PATCH 3/7] Use Term in ProjectionPredicate ProjectionPredicate should be able to handle both associated types and consts so this adds the first step of that. It mainly just pipes types all the way down, not entirely sure how to handle consts, but hopefully that'll come with time. --- Cargo.lock | 54 ++++--------------- compiler/rustc_ast_lowering/src/lib.rs | 13 +++-- compiler/rustc_ast_lowering/src/path.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 4 +- .../src/diagnostics/region_name.rs | 5 +- compiler/rustc_hir/src/hir.rs | 28 +++++++--- compiler/rustc_hir/src/intravisit.rs | 10 ++-- compiler/rustc_hir_pretty/src/lib.rs | 13 +++-- .../src/infer/error_reporting/mod.rs | 8 ++- .../error_reporting/nice_region_error/util.rs | 5 +- .../rustc_infer/src/infer/opaque_types.rs | 12 +++-- compiler/rustc_infer/src/infer/projection.rs | 3 +- compiler/rustc_middle/src/ty/flags.rs | 9 ++-- compiler/rustc_middle/src/ty/mod.rs | 51 ++++++++++-------- compiler/rustc_middle/src/ty/print/pretty.rs | 9 +++- compiler/rustc_middle/src/ty/relate.rs | 13 +++-- .../rustc_middle/src/ty/structural_impls.rs | 18 +++++-- compiler/rustc_middle/src/ty/sty.rs | 11 ++-- compiler/rustc_parse/src/parser/path.rs | 12 ++--- compiler/rustc_privacy/src/lib.rs | 5 +- .../src/traits/error_reporting/mod.rs | 9 ++-- .../src/traits/project.rs | 12 ++--- .../src/traits/relationships.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 4 +- compiler/rustc_traits/src/chalk/lowering.rs | 4 +- compiler/rustc_typeck/src/astconv/errors.rs | 8 ++- compiler/rustc_typeck/src/astconv/mod.rs | 37 +++++++------ compiler/rustc_typeck/src/bounds.rs | 25 +-------- compiler/rustc_typeck/src/check/closure.rs | 4 +- .../rustc_typeck/src/check/compare_method.rs | 2 +- .../rustc_typeck/src/check/method/suggest.rs | 2 +- compiler/rustc_typeck/src/check/mod.rs | 6 ++- compiler/rustc_typeck/src/collect.rs | 6 ++- .../rustc_typeck/src/collect/item_bounds.rs | 6 +-- .../src/constrained_generic_params.rs | 2 +- .../src/impl_wf_check/min_specialization.rs | 2 +- src/librustdoc/clean/mod.rs | 18 ++++--- src/llvm-project | 2 +- src/test/ui/associated-consts/assoc-const.rs | 5 ++ .../issue-89013-no-kw.rs | 2 +- .../issue-89013-no-kw.stderr | 22 +++++--- .../parser-error-recovery/issue-89013.rs | 2 +- .../parser-error-recovery/issue-89013.stderr | 22 +++++--- .../parser/recover-assoc-const-constraint.rs | 6 ++- .../recover-assoc-const-constraint.stderr | 20 ------- src/tools/cargo | 2 +- .../clippy_lints/src/manual_async_fn.rs | 4 +- .../clippy/clippy_lints/src/methods/mod.rs | 4 +- .../src/methods/unnecessary_to_owned.rs | 2 +- .../src/unit_return_expecting_ord.rs | 4 +- src/tools/rust-analyzer | 2 +- 51 files changed, 274 insertions(+), 259 deletions(-) delete mode 100644 src/test/ui/parser/recover-assoc-const-constraint.stderr diff --git a/Cargo.lock b/Cargo.lock index 18b85103202e3..529e17b158fc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -335,7 +335,7 @@ dependencies = [ "cargo-test-macro", "cargo-test-support", "cargo-util", - "clap 3.0.6", + "clap", "crates-io", "crossbeam-utils", "curl", @@ -615,28 +615,13 @@ dependencies = [ "ansi_term 0.12.1", "atty", "bitflags", - "strsim 0.8.0", - "textwrap 0.11.0", + "strsim", + "textwrap", "unicode-width", "vec_map", "yaml-rust 0.3.5", ] -[[package]] -name = "clap" -version = "3.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1957aa4a5fb388f0a0a73ce7556c5b42025b874e5cdc2c670775e346e97adec0" -dependencies = [ - "atty", - "bitflags", - "indexmap", - "os_str_bytes", - "strsim 0.10.0", - "termcolor", - "textwrap 0.14.2", -] - [[package]] name = "clippy" version = "0.1.60" @@ -669,7 +654,7 @@ version = "0.0.1" dependencies = [ "bytecount", "cargo_metadata 0.14.0", - "clap 2.34.0", + "clap", "indoc", "itertools 0.10.1", "opener", @@ -1751,7 +1736,7 @@ name = "installer" version = "0.0.0" dependencies = [ "anyhow", - "clap 2.34.0", + "clap", "flate2", "lazy_static", "num_cpus", @@ -2190,7 +2175,7 @@ dependencies = [ "ammonia", "anyhow", "chrono", - "clap 2.34.0", + "clap", "elasticlunr-rs", "env_logger 0.7.1", "handlebars", @@ -2521,15 +2506,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "os_str_bytes" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -dependencies = [ - "memchr", -] - [[package]] name = "output_vt100" version = "0.1.2" @@ -2934,7 +2910,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0b4b5faaf07040474e8af74a9e19ff167d5d204df5db5c5c765edecfb900358" dependencies = [ "bitflags", - "clap 2.34.0", + "clap", "derive_more", "env_logger 0.7.1", "humantime 2.0.1", @@ -3282,7 +3258,7 @@ dependencies = [ name = "rustbook" version = "0.1.0" dependencies = [ - "clap 2.34.0", + "clap", "env_logger 0.7.1", "mdbook", ] @@ -4898,19 +4874,13 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "structopt" version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" dependencies = [ - "clap 2.34.0", + "clap", "lazy_static", "structopt-derive", ] @@ -5081,12 +5051,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "textwrap" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" - [[package]] name = "thiserror" version = "1.0.30" diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9a8a097ee249c..b2965774e2a6e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -997,10 +997,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; let kind = match constraint.kind { - AssocConstraintKind::Equality { ref term } => match term { - Term::Ty(ref ty) => hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) }, - Term::Const(ref c) => hir::TypeBindingKind::Const { c: self.lower_anon_const(c) }, - }, + AssocConstraintKind::Equality { ref term } => { + let term = match term { + Term::Ty(ref ty) => self.lower_ty(ty, itctx).into(), + Term::Const(ref c) => self.lower_anon_const(c).into(), + }; + hir::TypeBindingKind::Equality { term } + } AssocConstraintKind::Bound { ref bounds } => { let mut capturable_lifetimes; let mut parent_def_id = self.current_hir_id_owner; @@ -1079,7 +1082,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx, ); - hir::TypeBindingKind::Equality { ty } + hir::TypeBindingKind::Equality { term: ty.into() } }) } else { // Desugar `AssocTy: Bounds` into a type binding where the diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 46928a1846540..79262235cd9f2 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -420,7 +420,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ty: &'hir hir::Ty<'hir>, ) -> hir::TypeBinding<'hir> { let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME); - let kind = hir::TypeBindingKind::Equality { ty }; + let kind = hir::TypeBindingKind::Equality { term: ty.into() }; let args = arena_vec![self;]; let bindings = arena_vec![self;]; let gen_args = self.arena.alloc(hir::GenericArgs { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3c45b5790fb47..17941058ed6f0 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -964,9 +964,7 @@ impl<'a> State<'a> { Term::Const(c) => self.print_expr_anon_const(c), } } - ast::AssocConstraintKind::Bound { bounds } => { - self.print_type_bounds(":", &*bounds); - } + ast::AssocConstraintKind::Bound { bounds } => self.print_type_bounds(":", &*bounds), } } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 9aa58f05a8e65..01cc72121c7d4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -779,7 +779,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { [ hir::TypeBinding { ident: Ident { name: sym::Output, .. }, - kind: hir::TypeBindingKind::Equality { ty }, + kind: + hir::TypeBindingKind::Equality { + term: hir::Term::Ty(ty), + }, .. }, ], diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 039bb0db0aa79..43aa0ae265a09 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -377,7 +377,7 @@ impl GenericArgs<'_> { GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err), _ => false, }) || self.bindings.iter().any(|arg| match arg.kind { - TypeBindingKind::Equality { ty } => matches!(ty.kind, TyKind::Err), + TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err), _ => false, }) } @@ -2129,21 +2129,37 @@ pub struct TypeBinding<'hir> { pub span: Span, } +#[derive(Debug, HashStable_Generic)] +pub enum Term<'hir> { + Ty(&'hir Ty<'hir>), + Const(AnonConst), +} + +impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> { + fn from(ty: &'hir Ty<'hir>) -> Self { + Term::Ty(ty) + } +} + +impl<'hir> From for Term<'hir> { + fn from(c: AnonConst) -> Self { + Term::Const(c) + } +} + // Represents the two kinds of type bindings. #[derive(Debug, HashStable_Generic)] pub enum TypeBindingKind<'hir> { /// E.g., `Foo`. Constraint { bounds: &'hir [GenericBound<'hir>] }, - /// E.g., `Foo`. - Equality { ty: &'hir Ty<'hir> }, - /// E.g., `Foo`. - Const { c: AnonConst }, + /// E.g., `Foo`, `Foo` + Equality { term: Term<'hir> }, } impl TypeBinding<'_> { pub fn ty(&self) -> &Ty<'_> { match self.kind { - TypeBindingKind::Equality { ref ty } => ty, + TypeBindingKind::Equality { term: Term::Ty(ref ty) } => ty, _ => panic!("expected equality type binding for parenthesized generic args"), } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 56b32cde9d54f..a219dad7b3d22 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -827,11 +827,11 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>( visitor.visit_ident(type_binding.ident); visitor.visit_generic_args(type_binding.span, type_binding.gen_args); match type_binding.kind { - TypeBindingKind::Equality { ref ty } => visitor.visit_ty(ty), - TypeBindingKind::Const { ref c } => visitor.visit_anon_const(c), - TypeBindingKind::Constraint { bounds } => { - walk_list!(visitor, visit_param_bound, bounds); - } + TypeBindingKind::Equality { ref term } => match term { + Term::Ty(ref ty) => visitor.visit_ty(ty), + Term::Const(ref c) => visitor.visit_anon_const(c), + }, + TypeBindingKind::Constraint { bounds } => walk_list!(visitor, visit_param_bound, bounds), } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index a76af35a8e626..a301c5e34565c 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -6,7 +6,7 @@ use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, Breaks}; use rustc_ast_pretty::pprust::{Comments, PrintState}; use rustc_hir as hir; -use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node}; +use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term}; use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier}; use rustc_span::source_map::{SourceMap, Spanned}; use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol}; @@ -1752,13 +1752,12 @@ impl<'a> State<'a> { self.print_generic_args(binding.gen_args, false, false); self.space(); match generic_args.bindings[0].kind { - hir::TypeBindingKind::Equality { ref ty } => { + hir::TypeBindingKind::Equality { ref term } => { self.word_space("="); - self.print_type(ty); - } - hir::TypeBindingKind::Const { ref c } => { - self.word_space("="); - self.print_anon_const(c); + match term { + Term::Ty(ref ty) => self.print_type(ty), + Term::Const(ref c) => self.print_anon_const(c), + } } hir::TypeBindingKind::Constraint { bounds } => { self.print_bounds(":", bounds); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 6e6012fdc1a60..f1e99faba01bd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -69,7 +69,7 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ self, subst::{GenericArgKind, Subst, SubstsRef}, - Region, Ty, TyCtxt, TypeFoldable, + Region, Term, Ty, TyCtxt, TypeFoldable, }; use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span}; use rustc_target::spec::abi; @@ -1780,7 +1780,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { { if projection_predicate.projection_ty.item_def_id == item_def_id { // We don't account for multiple `Future::Output = Ty` contraints. - return Some(projection_predicate.ty); + match projection_predicate.term { + Term::Ty(ty) => return Some(ty), + // Can return None, but not sure if that makes sense? + Term::Const(_c) => todo!(), + } } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 04eceecc5f072..3fa71d1a3d817 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -122,8 +122,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { { for type_binding in generic_args.bindings.iter() { if type_binding.ident.name == rustc_span::sym::Output { - if let hir::TypeBindingKind::Equality { ty } = - type_binding.kind + if let hir::TypeBindingKind::Equality { + term: hir::Term::Ty(ty), + } = type_binding.kind { return Some(ty); } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 8894093c66c98..39339da9a0bfc 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -7,7 +7,7 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; -use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor}; +use rustc_middle::ty::{self, OpaqueTypeKey, Term, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_span::Span; use std::ops::ControlFlow; @@ -584,9 +584,13 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { debug!(?predicate); if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { - if projection.ty.references_error() { - // No point on adding these obligations since there's a type error involved. - return tcx.ty_error(); + if let Term::Ty(ty) = projection.term { + if ty.references_error() { + // No point on adding these obligations since there's a type error involved. + return tcx.ty_error(); + } + } else { + todo!(); } } diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index 9b53ab72b00de..b45a6514d7934 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -26,7 +26,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { kind: TypeVariableOriginKind::NormalizeProjectionType, span: self.tcx.def_span(def_id), }); - let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var }); + let projection = + ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, term: ty_var.into() }); let obligation = Obligation::with_depth( cause, recursion_depth, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index b6e673983fd4e..74c8d7b777722 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -1,5 +1,5 @@ use crate::ty::subst::{GenericArg, GenericArgKind}; -use crate::ty::{self, InferConst, Ty, TypeFlags}; +use crate::ty::{self, InferConst, Term, Ty, TypeFlags}; use std::slice; #[derive(Debug)] @@ -241,9 +241,12 @@ impl FlagComputation { self.add_ty(a); self.add_ty(b); } - ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => { + ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { self.add_projection_ty(projection_ty); - self.add_ty(ty); + match term { + Term::Ty(ty) => self.add_ty(ty), + Term::Const(_c) => todo!(), + } } ty::PredicateKind::WellFormed(arg) => { self.add_substs(slice::from_ref(&arg)); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 72e4e26dd3ee7..f1851150e38e8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -484,7 +484,7 @@ crate struct PredicateInner<'tcx> { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PredicateInner<'_>, 48); +static_assert_size!(PredicateInner<'_>, 56); #[derive(Clone, Copy, Lift)] pub struct Predicate<'tcx> { @@ -795,11 +795,35 @@ pub struct CoercePredicate<'tcx> { } pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable)] +pub enum Term<'tcx> { + Ty(Ty<'tcx>), + Const(&'tcx Const<'tcx>), +} + +impl<'tcx> From> for Term<'tcx> { + fn from(ty: Ty<'tcx>) -> Self { + Term::Ty(ty) + } +} + +impl<'tcx> From<&'tcx Const<'tcx>> for Term<'tcx> { + fn from(c: &'tcx Const<'tcx>) -> Self { + Term::Const(c) + } +} + +impl<'tcx> Term<'tcx> { + pub fn ty(&self) -> Ty<'tcx> { + if let Term::Ty(ty) = self { ty } else { panic!("Expected type") } + } +} + /// This kind of predicate has no *direct* correspondent in the /// syntax, but it roughly corresponds to the syntactic forms: /// /// 1. `T: TraitRef<..., Item = Type>` -/// - Or `T: TraitRef<..., Item = Const>` /// 2. `>::Item == Type` (NYI) /// /// In particular, form #1 is "desugared" to the combination of a @@ -812,26 +836,7 @@ pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; #[derive(HashStable, TypeFoldable)] pub struct ProjectionPredicate<'tcx> { pub projection_ty: ProjectionTy<'tcx>, - pub ty: Ty<'tcx>, -} - -/// This kind of predicate has no *direct* correspondent in the -/// syntax, but it roughly corresponds to the syntactic forms: -/// -/// 1. `T: TraitRef<..., Item = Const>` -/// 2. `>::Item == Const` (NYI) -/// -/// In particular, form #1 is "desugared" to the combination of a -/// normal trait predicate (`T: TraitRef<...>`) and one of these -/// predicates. Form #2 is a broader form in that it also permits -/// equality between arbitrary types. Processing an instance of -/// Form #2 eventually yields one of these `ProjectionPredicate` -/// instances to normalize the LHS. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug)] -#[derive(HashStable, TypeFoldable)] -pub struct ConstPredicate<'tcx> { - pub projection: ProjectionTy<'tcx>, - pub c: &'tcx Const<'tcx>, + pub term: Term<'tcx>, } pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; @@ -857,7 +862,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { } pub fn ty(&self) -> Binder<'tcx, Ty<'tcx>> { - self.map_bound(|predicate| predicate.ty) + self.map_bound(|predicate| if let Term::Ty(ty) = predicate.term { ty } else { todo!() }) } /// The `DefId` of the `TraitItem` for the associated type. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 94cd650e39e6f..8c07f154637e3 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2499,7 +2499,14 @@ define_print_and_forward_display! { } ty::ProjectionPredicate<'tcx> { - p!(print(self.projection_ty), " == ", print(self.ty)) + p!(print(self.projection_ty), " == ", print(self.term)) + } + + ty::Term<'tcx> { + match self { + ty::Term::Ty(ty) => p!(print(ty)), + ty::Term::Const(c) => p!(print(c)), + } } ty::ProjectionTy<'tcx> { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 9e381cabdfe84..851c4592f4fad 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -7,7 +7,7 @@ use crate::mir::interpret::{get_slice_bytes, ConstValue, GlobalAlloc, Scalar}; use crate::ty::error::{ExpectedFound, TypeError}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, Term, Ty, TyCtxt, TypeFoldable}; use rustc_hir as ast; use rustc_hir::def_id::DefId; use rustc_span::DUMMY_SP; @@ -839,10 +839,13 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { a: ty::ProjectionPredicate<'tcx>, b: ty::ProjectionPredicate<'tcx>, ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> { - Ok(ty::ProjectionPredicate { - projection_ty: relation.relate(a.projection_ty, b.projection_ty)?, - ty: relation.relate(a.ty, b.ty)?, - }) + match (a.term, b.term) { + (Term::Ty(a_ty), Term::Ty(b_ty)) => Ok(ty::ProjectionPredicate { + projection_ty: relation.relate(a.projection_ty, b.projection_ty)?, + term: relation.relate(a_ty, b_ty)?.into(), + }), + _ => todo!(), + } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a27169d59e13f..3cbea92ae6714 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -6,7 +6,7 @@ use crate::mir::interpret; use crate::mir::ProjectionKind; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; -use crate::ty::{self, InferConst, Lift, Ty, TyCtxt}; +use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; use rustc_hir::def::Namespace; use rustc_hir::def_id::CRATE_DEF_INDEX; @@ -158,7 +158,7 @@ impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> { impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.ty) + write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term) } } @@ -356,6 +356,16 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialPredicate<'a> { } } +impl<'a, 'tcx> Lift<'tcx> for Term<'a> { + type Lifted = ty::Term<'tcx>; + fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { + Some(match self { + Term::Ty(ty) => Term::Ty(tcx.lift(ty)?), + Term::Const(c) => Term::Const(tcx.lift(c)?), + }) + } +} + impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> { type Lifted = ty::TraitPredicate<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option> { @@ -403,8 +413,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionTy<'a> { impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> { type Lifted = ty::ProjectionPredicate<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option> { - tcx.lift((self.projection_ty, self.ty)) - .map(|(projection_ty, ty)| ty::ProjectionPredicate { projection_ty, ty }) + tcx.lift((self.projection_ty, self.term)) + .map(|(projection_ty, term)| ty::ProjectionPredicate { projection_ty, term }) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 92fb7612688c0..50d0862905bbf 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -8,7 +8,7 @@ use crate::infer::canonical::Canonical; use crate::ty::fold::ValidateBoundVars; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::InferTy::{self, *}; -use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable}; +use crate::ty::{self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeFoldable}; use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS}; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; @@ -1570,7 +1570,7 @@ impl<'tcx> ExistentialProjection<'tcx> { item_def_id: self.item_def_id, substs: tcx.mk_substs_trait(self_ty, self.substs), }, - ty: self.ty, + term: self.ty.into(), } } @@ -1580,11 +1580,16 @@ impl<'tcx> ExistentialProjection<'tcx> { ) -> Self { // Assert there is a Self. projection_predicate.projection_ty.substs.type_at(0); + let ty = if let Term::Ty(ty) = projection_predicate.term { + ty + } else { + todo!(); + }; Self { item_def_id: projection_predicate.projection_ty.item_def_id, substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]), - ty: projection_predicate.ty, + ty, } } } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 8f272820015b2..531cac1f57e56 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -503,17 +503,15 @@ impl<'a> Parser<'a> { ) -> PResult<'a, AssocConstraintKind> { let arg = self.parse_generic_arg(None)?; let span = ident.span.to(self.prev_token.span); - let ty = match arg { - Some(GenericArg::Type(ty)) => ty, - Some(GenericArg::Const(c)) => { - return Ok(AssocConstraintKind::Equality { term: c.into() }); - } + let term = match arg { + Some(GenericArg::Type(ty)) => ty.into(), + Some(GenericArg::Const(c)) => c.into(), Some(GenericArg::Lifetime(lt)) => { self.struct_span_err(span, "associated lifetimes are not supported") .span_label(lt.ident.span, "the lifetime is given here") .help("if you meant to specify a trait object, write `dyn Trait + 'lifetime`") .emit(); - self.mk_ty(span, ast::TyKind::Err) + self.mk_ty(span, ast::TyKind::Err).into() } None => { let after_eq = eq.shrink_to_hi(); @@ -542,7 +540,7 @@ impl<'a> Parser<'a> { return Err(err); } }; - Ok(AssocConstraintKind::Equality { term: ty.into() }) + Ok(AssocConstraintKind::Equality { term }) } /// We do not permit arbitrary expressions as const arguments. They must be one of: diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 7577b77181a06..dc432905b1c7c 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -127,7 +127,8 @@ where constness: _, polarity: _, }) => self.visit_trait(trait_ref), - ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => { + ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { + let ty = term.ty(); ty.visit_with(self)?; self.visit_projection_ty(projection_ty) } @@ -1185,7 +1186,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { } for (poly_predicate, _) in bounds.projection_bounds { - if self.visit(poly_predicate.skip_binder().ty).is_break() + if self.visit(poly_predicate.skip_binder().term.ty()).is_break() || self .visit_projection_ty(poly_predicate.skip_binder().projection_ty) .is_break() 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 b4d297a03ef21..85135383b8062 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1304,7 +1304,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { debug!( "report_projection_error normalized_ty={:?} data.ty={:?}", - normalized_ty, data.ty + normalized_ty, + data.term.ty() ); let is_normalized_ty_expected = !matches!( @@ -1318,12 +1319,12 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( is_normalized_ty_expected, normalized_ty, - data.ty, + data.term.ty(), ) { values = Some(infer::ValuePairs::Types(ExpectedFound::new( is_normalized_ty_expected, normalized_ty, - data.ty, + data.term.ty(), ))); err_buf = error; @@ -1803,7 +1804,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { } ty::PredicateKind::Projection(data) => { let self_ty = data.projection_ty.self_ty(); - let ty = data.ty; + let ty = data.term.ty(); if predicate.references_error() || self.is_tainted_by_errors() { return; } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 577b96f3a400b..4995590baec23 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -214,7 +214,7 @@ fn project_and_unify_type<'cx, 'tcx>( let infcx = selcx.infcx(); match infcx .at(&obligation.cause, obligation.param_env) - .eq(normalized_ty, obligation.predicate.ty) + .eq(normalized_ty, obligation.predicate.term.ty()) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); @@ -1615,7 +1615,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( substs: trait_ref.substs, item_def_id: obligation.predicate.item_def_id, }, - ty, + term: ty.into(), } }); @@ -1641,7 +1641,7 @@ fn confirm_discriminant_kind_candidate<'cx, 'tcx>( let predicate = ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { substs, item_def_id: discriminant_def_id }, - ty: self_ty.discriminant_ty(tcx), + term: self_ty.discriminant_ty(tcx).into(), }; // We get here from `poly_project_and_unify_type` which replaces bound vars @@ -1674,7 +1674,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>( let predicate = ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { substs, item_def_id: metadata_def_id }, - ty: metadata_ty, + term: metadata_ty.into(), }; confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false) @@ -1747,7 +1747,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( substs: trait_ref.substs, item_def_id: fn_once_output_def_id, }, - ty: ret_type, + term: ret_type.into(), }); confirm_param_env_candidate(selcx, obligation, predicate, true) @@ -1803,7 +1803,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( Ok(InferOk { value: _, obligations }) => { nested_obligations.extend(obligations); assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); - Progress { ty: cache_entry.ty, obligations: nested_obligations } + Progress { ty: cache_entry.term.ty(), obligations: nested_obligations } } Err(e) => { let msg = format!( diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs index e0098cc92d515..acac76cdfaaf0 100644 --- a/compiler/rustc_trait_selection/src/traits/relationships.rs +++ b/compiler/rustc_trait_selection/src/traits/relationships.rs @@ -62,7 +62,7 @@ pub(crate) fn update<'tcx, T>( if let ty::PredicateKind::Projection(predicate) = obligation.predicate.kind().skip_binder() { // If the projection predicate (Foo::Bar == X) has X as a non-TyVid, // we need to make it into one. - if let Some(vid) = predicate.ty.ty_vid() { + if let Some(vid) = predicate.term.ty().ty_vid() { debug!("relationship: {:?}.output = true", vid); engine.relationships().entry(vid).or_default().output = true; } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index f6e98f427108f..e3b366c65bf5c 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -116,7 +116,7 @@ pub fn predicate_obligations<'a, 'tcx>( } ty::PredicateKind::Projection(t) => { wf.compute_projection(t.projection_ty); - wf.compute(t.ty.into()); + wf.compute(t.term.ty().into()); } ty::PredicateKind::WellFormed(arg) => { wf.compute(arg); @@ -219,7 +219,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( // projection coming from another associated type. See // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and // `traits-assoc-type-in-supertrait-bad.rs`. - if let ty::Projection(projection_ty) = proj.ty.kind() { + if let ty::Projection(projection_ty) = proj.term.ty().kind() { if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id) { diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 36c536c0ba3b2..e651ff63c5249 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -227,7 +227,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq>> { fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq> { chalk_ir::AliasEq { - ty: self.ty.lower_into(interner), + ty: self.term.ty().lower_into(interner), alias: self.projection_ty.lower_into(interner), } } @@ -787,7 +787,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound trait_bound: trait_ref.lower_into(interner), associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id), parameters: own_substs.iter().map(|arg| arg.lower_into(interner)).collect(), - value: self.ty.lower_into(interner), + value: self.term.ty().lower_into(interner), } } } diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs index 1f99a9b0536d0..b532c41642c6e 100644 --- a/compiler/rustc_typeck/src/astconv/errors.rs +++ b/compiler/rustc_typeck/src/astconv/errors.rs @@ -151,8 +151,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .bindings .iter() .find_map(|b| match (b.ident.name == sym::Output, &b.kind) { - (true, hir::TypeBindingKind::Equality { ty }) => { - sess.source_map().span_to_snippet(ty.span).ok() + (true, hir::TypeBindingKind::Equality { term }) => { + let span = match term { + hir::Term::Ty(ty) => ty.span, + hir::Term::Const(c) => self.tcx().hir().span(c.hir_id), + }; + sess.source_map().span_to_snippet(span).ok() } _ => None, }) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 2d847f6145d6f..2866a7884a77a 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -602,14 +602,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .iter() .map(|binding| { let kind = match binding.kind { - hir::TypeBindingKind::Equality { ty } => { - ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty)) - } - hir::TypeBindingKind::Const { ref c } => { - let local_did = self.tcx().hir().local_def_id(c.hir_id); - let c = Const::from_anon_const(self.tcx(), local_did); - ConvertedBindingKind::Const(&c) - } + hir::TypeBindingKind::Equality { ref term } => match term { + hir::Term::Ty(ref ty) => { + ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty)) + } + hir::Term::Const(ref c) => { + let local_did = self.tcx().hir().local_def_id(c.hir_id); + let c = Const::from_anon_const(self.tcx(), local_did); + ConvertedBindingKind::Const(&c) + } + }, hir::TypeBindingKind::Constraint { ref bounds } => { ConvertedBindingKind::Constraint(bounds) } @@ -1227,21 +1229,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // // `::Item = u32` bounds.projection_bounds.push(( - projection_ty.map_bound(|projection_ty| { - debug!( - "add_predicates_for_ast_type_binding: projection_ty {:?}, substs: {:?}", - projection_ty, projection_ty.substs - ); - ty::ProjectionPredicate { projection_ty, ty } + projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate { + projection_ty, + term: ty.into(), }), binding.span, )); } ConvertedBindingKind::Const(c) => { - bounds.const_bounds.push(( - projection_ty.map_bound(|projection_ty| ty::ConstPredicate { - projection: projection_ty, - c, + bounds.projection_bounds.push(( + projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate { + projection_ty, + term: c.into(), }), binding.span, )); @@ -1393,7 +1392,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // A `Self` within the original bound will be substituted with a // `trait_object_dummy_self`, so check for that. let references_self = - pred.skip_binder().ty.walk().any(|arg| arg == dummy_self.into()); + pred.skip_binder().term.ty().walk().any(|arg| arg == dummy_self.into()); // If the projection output contains `Self`, force the user to // elaborate it explicitly to avoid a lot of complexity. diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 47c3ea5457578..6a28bb16a20ac 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -37,12 +37,6 @@ pub struct Bounds<'tcx> { /// here. pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>, - /// A list of const equality bounds. So if you had `T: - /// Iterator` this would include `::N => 4`. Note that the self-type is explicit - /// here. - pub const_bounds: Vec<(ty::Binder<'tcx, ty::ConstPredicate<'tcx>>, Span)>, - /// `Some` if there is *no* `?Sized` predicate. The `span` /// is the location in the source of the `T` declaration which can /// be cited as the source of the `T: Sized` requirement. @@ -90,24 +84,7 @@ impl<'tcx> Bounds<'tcx> { .projection_bounds .iter() .map(move |&(projection, span)| (projection.to_predicate(tcx), span)); - let const_bounds = self.const_bounds.iter().map(move |&(bound, span)| { - // FIXME(...): what about the projection's generics? - // Is this the right local defid? Or should I get the self ty then - let pred = bound - .map_bound(|cp| { - let got = - ty::Const::from_anon_const(tcx, cp.projection.item_def_id.expect_local()); - ty::PredicateKind::ConstEquate(cp.c, got) - }) - .to_predicate(tcx); - (pred, span) - }); - sized_predicate - .into_iter() - .chain(region_preds) - .chain(trait_bounds) - .chain(projection_bounds) - .chain(const_bounds) + sized_predicate.into_iter().chain(region_preds).chain(trait_bounds).chain(projection_bounds) } } diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index c87ab0d410cd9..c8e1d8b190c9d 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -279,7 +279,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - let ret_param_ty = projection.skip_binder().ty; + let ret_param_ty = projection.skip_binder().term.ty(); let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty); debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty); @@ -706,7 +706,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Extract the type from the projection. Note that there can // be no bound variables in this type because the "self type" // does not have any regions in it. - let output_ty = self.resolve_vars_if_possible(predicate.ty); + let output_ty = self.resolve_vars_if_possible(predicate.term.ty()); debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty); Some(output_ty) } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 74327affede48..c3fae46909f1c 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1360,7 +1360,7 @@ pub fn check_type_bounds<'tcx>( item_def_id: trait_ty.def_id, substs: rebased_substs, }, - ty: impl_ty_value, + term: impl_ty_value.into(), }, bound_vars, ) diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index f2fe4403d558c..590d65b7cba3f 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -789,7 +789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_def_id: projection_ty.item_def_id, }; - let ty = pred.skip_binder().ty; + let ty: Ty<'_> = pred.skip_binder().term.ty(); let obligation = format!("{} = {}", projection_ty, ty); let quiet = format!("{} = {}", quiet_projection_ty, ty); diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 719266ad5a435..8d06b8a7a170b 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -691,7 +691,11 @@ fn bounds_from_generic_predicates<'tcx>( // insert the associated types where they correspond, but for now let's be "lazy" and // propose this instead of the following valid resugaring: // `T: Trait, Trait::Assoc = K` → `T: Trait` - where_clauses.push(format!("{} = {}", tcx.def_path_str(p.projection_ty.item_def_id), p.ty)); + where_clauses.push(format!( + "{} = {}", + tcx.def_path_str(p.projection_ty.item_def_id), + p.term.ty() + )); } let where_clauses = if where_clauses.is_empty() { String::new() diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 7cb100a0a83f0..2843f19d09e0e 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -664,7 +664,11 @@ impl<'tcx> ItemCtxt<'tcx> { .params .iter() .filter_map(|param| match param.kind { - GenericParamKind::Type { .. } if param.hir_id == param_id => Some(¶m.bounds), + GenericParamKind::Type { .. } | GenericParamKind::Const { .. } + if param.hir_id == param_id => + { + Some(¶m.bounds) + } _ => None, }) .flat_map(|bounds| bounds.iter()) diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 6d992629a00ff..87a67c4a4e060 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -67,11 +67,7 @@ fn opaque_type_bounds<'tcx>( let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); // Opaque types are implicitly sized unless a `?Sized` bound is found >::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); - let preds = bounds.predicates(tcx, item_ty); - - let bounds = tcx.arena.alloc_from_iter(preds); - debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds); - bounds + tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty)) }) } diff --git a/compiler/rustc_typeck/src/constrained_generic_params.rs b/compiler/rustc_typeck/src/constrained_generic_params.rs index 1095290132347..a0c8fc822dffd 100644 --- a/compiler/rustc_typeck/src/constrained_generic_params.rs +++ b/compiler/rustc_typeck/src/constrained_generic_params.rs @@ -203,7 +203,7 @@ pub fn setup_constraining_predicates<'tcx>( if !relies_only_on_inputs { continue; } - input_parameters.extend(parameters_for(&projection.ty, false)); + input_parameters.extend(parameters_for(&projection.term, false)); } else { continue; } 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 6296f2ab32a52..5e6704c9864fc 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -199,7 +199,7 @@ fn unconstrained_parent_impl_substs<'tcx>( for (predicate, _) in impl_generic_predicates.predicates.iter() { if let ty::PredicateKind::Projection(proj) = predicate.kind().skip_binder() { let projection_ty = proj.projection_ty; - let projected_ty = proj.ty; + let projected_ty = proj.term.ty(); let unbound_trait_ref = projection_ty.trait_ref(tcx); if Some(unbound_trait_ref) == impl_trait_ref { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 169cb618a7d93..f6af81769b7a1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -354,7 +354,8 @@ impl<'tcx> Clean> for ty::OutlivesPredicate, ty: impl<'tcx> Clean for ty::ProjectionPredicate<'tcx> { fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate { - let ty::ProjectionPredicate { projection_ty, ty } = self; + let ty::ProjectionPredicate { projection_ty, term } = self; + let ty = term.ty(); WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) } } } @@ -623,8 +624,9 @@ fn clean_ty_generics( .filter(|b| !b.is_sized_bound(cx)), ); - let proj = projection - .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty)); + let proj = projection.map(|p| { + (p.skip_binder().projection_ty.clean(cx), p.skip_binder().term.ty()) + }); if let Some(((_, trait_did, name), rhs)) = proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs))) { @@ -1566,7 +1568,7 @@ impl<'tcx> Clean for Ty<'tcx> { .ident .name, kind: TypeBindingKind::Equality { - ty: proj.ty.clean(cx), + ty: proj.term.ty().clean(cx), }, }) } else { @@ -2114,10 +2116,10 @@ impl Clean for hir::TypeBinding<'_> { impl Clean for hir::TypeBindingKind<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> TypeBindingKind { match *self { - hir::TypeBindingKind::Equality { ref ty } => { - TypeBindingKind::Equality { ty: ty.clean(cx) } - } - hir::TypeBindingKind::Const { c: _ } => todo!(), + hir::TypeBindingKind::Equality { ref term } => match term { + hir::Term::Ty(ref ty) => TypeBindingKind::Equality { ty: ty.clean(cx) }, + hir::Term::Const(ref _c) => todo!(), + }, hir::TypeBindingKind::Constraint { ref bounds } => TypeBindingKind::Constraint { bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(), }, diff --git a/src/llvm-project b/src/llvm-project index 2abffbf977a9e..6b3dbcc81a470 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 2abffbf977a9e8c6ca4174a08fe5c4d7781f0aac +Subproject commit 6b3dbcc81a470e5da84576d63fcfc19e3b1154cd diff --git a/src/test/ui/associated-consts/assoc-const.rs b/src/test/ui/associated-consts/assoc-const.rs index 9332d16afe54f..582d0a6922985 100644 --- a/src/test/ui/associated-consts/assoc-const.rs +++ b/src/test/ui/associated-consts/assoc-const.rs @@ -10,5 +10,10 @@ impl Foo for Bar { const N: usize = 3; } +const TEST:usize = 3; + + fn foo>() {} +fn bar>() {} + fn main() {} diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs index 19e0f38d320c4..32b08fb97f271 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs @@ -7,7 +7,7 @@ struct Bar; const T: usize = 42; impl Foo for Bar { -//~^ ERROR cannot constrain an associated constant to a value +//~^ ERROR this trait takes 1 generic argument but 0 generic arguments were supplied //~| ERROR associated type bindings are not allowed here fn do_x(&self) -> [u8; 3] { [0u8; 3] diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr index bbca92ad63a91..455f6f61aada3 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr @@ -1,11 +1,18 @@ -error: cannot constrain an associated constant to a value - --> $DIR/issue-89013-no-kw.rs:9:10 +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/issue-89013-no-kw.rs:9:6 | LL | impl Foo for Bar { - | -^^^- - | | | - | | ...cannot be constrained to this value - | this associated constant... + | ^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `N` + --> $DIR/issue-89013-no-kw.rs:1:7 + | +LL | trait Foo { + | ^^^ - +help: add missing generic argument + | +LL | impl Foo for Bar { + | ++ error[E0229]: associated type bindings are not allowed here --> $DIR/issue-89013-no-kw.rs:9:10 @@ -15,4 +22,5 @@ LL | impl Foo for Bar { error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0229`. +Some errors have detailed explanations: E0107, E0229. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs index ca1158a2f6d16..97c22fa7862d5 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs @@ -8,7 +8,7 @@ const T: usize = 42; impl Foo for Bar { //~^ ERROR expected lifetime, type, or constant, found keyword `const` -//~| ERROR cannot constrain an associated constant to a value +//~| ERROR this trait takes 1 generic //~| ERROR associated type bindings are not allowed here fn do_x(&self) -> [u8; 3] { [0u8; 3] diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr index 85379d3f06e4b..57108d718cfde 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr @@ -10,14 +10,21 @@ LL - impl Foo for Bar { LL + impl Foo for Bar { | -error: cannot constrain an associated constant to a value - --> $DIR/issue-89013.rs:9:10 +error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied + --> $DIR/issue-89013.rs:9:6 | LL | impl Foo for Bar { - | -^^^^^^^^^- - | | | - | | ...cannot be constrained to this value - | this associated constant... + | ^^^ expected 1 generic argument + | +note: trait defined here, with 1 generic parameter: `N` + --> $DIR/issue-89013.rs:1:7 + | +LL | trait Foo { + | ^^^ - +help: add missing generic argument + | +LL | impl Foo for Bar { + | ++ error[E0229]: associated type bindings are not allowed here --> $DIR/issue-89013.rs:9:10 @@ -27,4 +34,5 @@ LL | impl Foo for Bar { error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0229`. +Some errors have detailed explanations: E0107, E0229. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/parser/recover-assoc-const-constraint.rs b/src/test/ui/parser/recover-assoc-const-constraint.rs index 06be3cdcc1a95..3f7423dcb8e0c 100644 --- a/src/test/ui/parser/recover-assoc-const-constraint.rs +++ b/src/test/ui/parser/recover-assoc-const-constraint.rs @@ -1,7 +1,9 @@ +// run-pass + #[cfg(FALSE)] fn syntax() { - bar::(); //~ ERROR cannot constrain an associated constant to a value - bar::(); //~ ERROR cannot constrain an associated constant to a value + bar::(); + bar::(); } fn main() {} diff --git a/src/test/ui/parser/recover-assoc-const-constraint.stderr b/src/test/ui/parser/recover-assoc-const-constraint.stderr deleted file mode 100644 index c6733b33faa58..0000000000000 --- a/src/test/ui/parser/recover-assoc-const-constraint.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: cannot constrain an associated constant to a value - --> $DIR/recover-assoc-const-constraint.rs:3:11 - | -LL | bar::(); - | ----^^^-- - | | | - | | ...cannot be constrained to this value - | this associated constant... - -error: cannot constrain an associated constant to a value - --> $DIR/recover-assoc-const-constraint.rs:4:11 - | -LL | bar::(); - | ----^^^------ - | | | - | | ...cannot be constrained to this value - | this associated constant... - -error: aborting due to 2 previous errors - diff --git a/src/tools/cargo b/src/tools/cargo index 06b9d31743210..358e79fe56fe3 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 06b9d31743210b788b130c8a484c2838afa6fc27 +Subproject commit 358e79fe56fe374649275ca7aebaafd57ade0e8d diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 86819752f90ff..2af3555e370a4 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -6,7 +6,7 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId, + Term, AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, HirId, IsAsync, ItemKind, LifetimeName, TraitRef, Ty, TyKind, TypeBindingKind, }; use rustc_lint::{LateContext, LateLintPass}; @@ -140,7 +140,7 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t if args.bindings.len() == 1; let binding = &args.bindings[0]; if binding.ident.name == sym::Output; - if let TypeBindingKind::Equality{ty: output} = binding.kind; + if let TypeBindingKind::Equality{term: Term::Ty(output)} = binding.kind; then { return Some(output) } diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index ed5136e7d00ff..c0e65e520f23a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -2143,10 +2143,10 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() { // walk the associated type and check for Self if let Some(self_adt) = self_ty.ty_adt_def() { - if contains_adt_constructor(projection_predicate.ty, self_adt) { + if contains_adt_constructor(projection_predicate.term.ty(), self_adt) { return; } - } else if contains_ty(projection_predicate.ty, self_ty) { + } else if contains_ty(projection_predicate.term.ty(), self_ty) { return; } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index e5b6d296b2d25..865a36a5cd1d6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -243,7 +243,7 @@ fn check_other_call_arg<'tcx>( if if trait_predicate.def_id() == deref_trait_id { if let [projection_predicate] = projection_predicates[..] { let normalized_ty = - cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.ty); + cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term.ty()); implements_trait(cx, receiver_ty, deref_trait_id, &[]) && get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(normalized_ty) } else { diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs index fe35ff33d35a4..09f9e1ee09990 100644 --- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs +++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs @@ -98,9 +98,9 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve if trait_pred.self_ty() == inp; if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred); then { - if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.ty) { + if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.term.ty()) { args_to_check.push((i, "Ord".to_string())); - } else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.ty) { + } else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.term.ty()) { args_to_check.push((i, "PartialOrd".to_string())); } } diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 0f8c96c92689a..8e9ccbf97a702 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 0f8c96c92689af8378dbe9f466c6bf15a3a27458 +Subproject commit 8e9ccbf97a70259b6c6576e8fd7d77d28238737e From e7529d6a3867ed1692818702b40814ee992eba2d Mon Sep 17 00:00:00 2001 From: kadmin Date: Mon, 10 Jan 2022 23:39:21 +0000 Subject: [PATCH 4/7] Update term for use in more places Replace use of `ty()` on term and use it in more places. This will allow more flexibility in the future, but slightly worried it allows items which are consts which only accept types. --- .../rustc_infer/src/infer/opaque_types.rs | 11 +--- compiler/rustc_interface/src/util.rs | 2 + compiler/rustc_middle/src/ty/assoc.rs | 13 ++++ compiler/rustc_middle/src/ty/consts.rs | 12 ++-- compiler/rustc_middle/src/ty/flags.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 8 +-- compiler/rustc_middle/src/ty/print/pretty.rs | 24 +++++--- compiler/rustc_middle/src/ty/relate.rs | 25 +++++--- compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 17 ++++-- .../src/traits/auto_trait.rs | 16 +++-- .../src/traits/error_reporting/mod.rs | 10 ++-- .../src/traits/project.rs | 11 ++-- .../src/traits/relationships.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 7 ++- compiler/rustc_traits/src/chalk/lowering.rs | 16 ++++- compiler/rustc_typeck/src/astconv/mod.rs | 41 +++++++------ compiler/rustc_typeck/src/check/closure.rs | 8 ++- .../rustc_typeck/src/check/method/suggest.rs | 9 ++- compiler/rustc_typeck/src/check/mod.rs | 5 +- src/librustdoc/clean/auto_trait.rs | 8 ++- src/librustdoc/clean/mod.rs | 60 +++++++++++++------ src/librustdoc/clean/simplify.rs | 10 ++-- src/librustdoc/clean/types.rs | 33 ++++++++-- src/librustdoc/html/format.rs | 18 +++++- src/librustdoc/json/conversions.rs | 11 +++- src/rustdoc-json-types/lib.rs | 11 +++- .../repeated_projection_type.stderr | 2 +- .../clippy/clippy_lints/src/methods/mod.rs | 8 ++- .../src/methods/unnecessary_to_owned.rs | 5 +- .../src/unit_return_expecting_ord.rs | 5 +- 31 files changed, 284 insertions(+), 128 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 39339da9a0bfc..4851e637d3a62 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -7,7 +7,7 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; -use rustc_middle::ty::{self, OpaqueTypeKey, Term, Ty, TyCtxt, TypeFoldable, TypeVisitor}; +use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_span::Span; use std::ops::ControlFlow; @@ -584,13 +584,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { debug!(?predicate); if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { - if let Term::Ty(ty) = projection.term { - if ty.references_error() { - // No point on adding these obligations since there's a type error involved. - return tcx.ty_error(); - } - } else { - todo!(); + if projection.term.references_error() { + return tcx.ty_error(); } } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 0d1081ee26b77..3921187baa55e 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -742,6 +742,8 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { ast::AssocConstraintKind::Equality { ref term } => { match term { Term::Ty(ty) => involves_impl_trait(ty), + // FIXME(...): This should check if the constant + // involves a trait impl, but for now ignore. Term::Const(_) => false, } } diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 8563bac0bbf87..2776370ba6f46 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -152,6 +152,19 @@ impl<'tcx> AssocItems<'tcx> { .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id)) } + /// Returns the associated item with the given name and any of `AssocKind`, if one exists. + pub fn find_by_name_and_kinds( + &self, + tcx: TyCtxt<'_>, + ident: Ident, + kinds: &[AssocKind], + parent_def_id: DefId, + ) -> Option<&ty::AssocItem> { + self.filter_by_name_unhygienic(ident.name) + .filter(|item| kinds.contains(&item.kind)) + .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id)) + } + /// Returns the associated item with the given name in the given `Namespace`, if one exists. pub fn find_by_name_and_namespace( &self, diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 75705d40a6c80..d6c35dfef8888 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -86,10 +86,14 @@ impl<'tcx> Const<'tcx> { if let Some(lit_input) = lit_input { // If an error occurred, ignore that it's a literal and leave reporting the error up to // mir. - if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) { - return Some(c); - } else { - tcx.sess.delay_span_bug(expr.span, "Const::from_anon_const: couldn't lit_to_const"); + match tcx.at(expr.span).lit_to_const(lit_input) { + Ok(c) => return Some(c), + Err(e) => { + tcx.sess.delay_span_bug( + expr.span, + &format!("Const::from_anon_const: couldn't lit_to_const {:?}", e), + ); + } } } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 74c8d7b777722..be9021dc61989 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -245,7 +245,7 @@ impl FlagComputation { self.add_projection_ty(projection_ty); match term { Term::Ty(ty) => self.add_ty(ty), - Term::Const(_c) => todo!(), + Term::Const(c) => self.add_const(c), } } ty::PredicateKind::WellFormed(arg) => { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f1851150e38e8..42e6f3f6ef584 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -815,8 +815,8 @@ impl<'tcx> From<&'tcx Const<'tcx>> for Term<'tcx> { } impl<'tcx> Term<'tcx> { - pub fn ty(&self) -> Ty<'tcx> { - if let Term::Ty(ty) = self { ty } else { panic!("Expected type") } + pub fn ty(&self) -> Option> { + if let Term::Ty(ty) = self { Some(ty) } else { None } } } @@ -861,8 +861,8 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) } - pub fn ty(&self) -> Binder<'tcx, Ty<'tcx>> { - self.map_bound(|predicate| if let Term::Ty(ty) = predicate.term { ty } else { todo!() }) + pub fn term(&self) -> Binder<'tcx, Term<'tcx>> { + self.map_bound(|predicate| predicate.term) } /// The `DefId` of the `TraitItem` for the associated type. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 8c07f154637e3..6fcb6ac5f4c0b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1,6 +1,6 @@ use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; -use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable}; use rustc_apfloat::ieee::{Double, Single}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sso::SsoHashSet; @@ -799,7 +799,7 @@ pub trait PrettyPrinter<'tcx>: let trait_ref = proj_ref.required_poly_trait_ref(self.tcx()); // Projection type entry -- the def-id for naming, and the ty. - let proj_ty = (proj_ref.projection_def_id(), proj_ref.ty()); + let proj_ty = (proj_ref.projection_def_id(), proj_ref.term()); self.insert_trait_and_projection( trait_ref, @@ -850,8 +850,10 @@ pub trait PrettyPrinter<'tcx>: } p!(")"); - if !return_ty.skip_binder().is_unit() { - p!("-> ", print(return_ty)); + if let Term::Ty(ty) = return_ty.skip_binder() { + if !ty.is_unit() { + p!("-> ", print(return_ty)); + } } p!(write("{}", if paren_needed { ")" } else { "" })); @@ -902,14 +904,15 @@ pub trait PrettyPrinter<'tcx>: first = false; } - for (assoc_item_def_id, ty) in assoc_items { + for (assoc_item_def_id, term) in assoc_items { + let ty = if let Term::Ty(ty) = term.skip_binder() { ty } else { continue }; if !first { p!(", "); } p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).ident)); // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks - match ty.skip_binder().kind() { + match ty.kind() { ty::Projection(ty::ProjectionTy { item_def_id, .. }) if Some(*item_def_id) == self.tcx().lang_items().generator_return() => { @@ -943,8 +946,11 @@ pub trait PrettyPrinter<'tcx>: fn insert_trait_and_projection( &mut self, trait_ref: ty::PolyTraitRef<'tcx>, - proj_ty: Option<(DefId, ty::Binder<'tcx, Ty<'tcx>>)>, - traits: &mut BTreeMap, BTreeMap>>>, + proj_ty: Option<(DefId, ty::Binder<'tcx, Term<'tcx>>)>, + traits: &mut BTreeMap< + ty::PolyTraitRef<'tcx>, + BTreeMap>>, + >, fn_traits: &mut BTreeMap, OpaqueFnEntry<'tcx>>, ) { let trait_def_id = trait_ref.def_id(); @@ -2716,5 +2722,5 @@ pub struct OpaqueFnEntry<'tcx> { has_fn_once: bool, fn_mut_trait_ref: Option>, fn_trait_ref: Option>, - return_ty: Option>>, + return_ty: Option>>, } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 851c4592f4fad..bd6c24445ef51 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -833,19 +833,30 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> { } } +impl<'tcx> Relate<'tcx> for ty::Term<'tcx> { + fn relate>( + relation: &mut R, + a: Self, + b: Self, + ) -> RelateResult<'tcx, Self> { + Ok(match (a, b) { + (Term::Ty(a), Term::Ty(b)) => relation.relate(a, b)?.into(), + (Term::Const(a), Term::Const(b)) => relation.relate(a, b)?.into(), + _ => return Err(TypeError::Mismatch), + }) + } +} + impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { fn relate>( relation: &mut R, a: ty::ProjectionPredicate<'tcx>, b: ty::ProjectionPredicate<'tcx>, ) -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> { - match (a.term, b.term) { - (Term::Ty(a_ty), Term::Ty(b_ty)) => Ok(ty::ProjectionPredicate { - projection_ty: relation.relate(a.projection_ty, b.projection_ty)?, - term: relation.relate(a_ty, b_ty)?.into(), - }), - _ => todo!(), - } + Ok(ty::ProjectionPredicate { + projection_ty: relation.relate(a.projection_ty, b.projection_ty)?, + term: relation.relate(a.term, b.term)?.into(), + }) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 50d0862905bbf..453e380f6e3a0 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1583,7 +1583,7 @@ impl<'tcx> ExistentialProjection<'tcx> { let ty = if let Term::Ty(ty) = projection_predicate.term { ty } else { - todo!(); + panic!("Only types are permitted here"); }; Self { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index dc432905b1c7c..73873c8cf0d91 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -128,8 +128,10 @@ where polarity: _, }) => self.visit_trait(trait_ref), ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { - let ty = term.ty(); - ty.visit_with(self)?; + match term { + ty::Term::Ty(ty) => ty.visit_with(self)?, + ty::Term::Const(ct) => ct.visit_with(self)?, + } self.visit_projection_ty(projection_ty) } ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => { @@ -1186,10 +1188,13 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { } for (poly_predicate, _) in bounds.projection_bounds { - if self.visit(poly_predicate.skip_binder().term.ty()).is_break() - || self - .visit_projection_ty(poly_predicate.skip_binder().projection_ty) - .is_break() + let pred = poly_predicate.skip_binder(); + let poly_pred_term = match pred.term { + ty::Term::Ty(ty) => self.visit(ty), + ty::Term::Const(ct) => self.visit(ct), + }; + if poly_pred_term.is_break() + || self.visit_projection_ty(pred.projection_ty).is_break() { return; } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 05d2a373dc639..cc20c1179452c 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -6,7 +6,7 @@ use super::*; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::InferCtxt; use rustc_middle::ty::fold::TypeFolder; -use rustc_middle::ty::{Region, RegionVid}; +use rustc_middle::ty::{Region, RegionVid, Term}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -606,7 +606,11 @@ impl<'tcx> AutoTraitFinder<'tcx> { } fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool { - matches!(*p.ty().skip_binder().kind(), ty::Projection(proj) if proj == p.skip_binder().projection_ty) + if let Term::Ty(ty) = p.term().skip_binder() { + matches!(ty.kind(), ty::Projection(proj) if proj == &p.skip_binder().projection_ty) + } else { + false + } } fn evaluate_nested_obligations( @@ -663,7 +667,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // Additionally, we check if we've seen this predicate before, // to avoid rendering duplicate bounds to the user. if self.is_param_no_infer(p.skip_binder().projection_ty.substs) - && !p.ty().skip_binder().has_infer_types() + && !p.term().skip_binder().has_infer_types() && is_new_pred { debug!( @@ -752,7 +756,8 @@ impl<'tcx> AutoTraitFinder<'tcx> { // when we started out trying to unify // some inference variables. See the comment above // for more infomration - if p.ty().skip_binder().has_infer_types() { + if p.term().skip_binder().ty().map_or(false, |ty| ty.has_infer_types()) + { if !self.evaluate_nested_obligations( ty, v.into_iter(), @@ -774,7 +779,8 @@ impl<'tcx> AutoTraitFinder<'tcx> { // However, we should always make progress (either by generating // subobligations or getting an error) when we started off with // inference variables - if p.ty().skip_binder().has_infer_types() { + if p.term().skip_binder().ty().map_or(false, |ty| ty.has_infer_types()) + { panic!("Unexpected result when selecting {:?} {:?}", ty, obligation) } } 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 85135383b8062..43a961c5c9116 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1304,8 +1304,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { debug!( "report_projection_error normalized_ty={:?} data.ty={:?}", - normalized_ty, - data.term.ty() + normalized_ty, data.term, ); let is_normalized_ty_expected = !matches!( @@ -1315,16 +1314,17 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::ObjectCastObligation(_) | ObligationCauseCode::OpaqueType ); - + // FIXME(...): Handle Consts here + let data_ty = data.term.ty().unwrap(); if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( is_normalized_ty_expected, normalized_ty, - data.term.ty(), + data_ty, ) { values = Some(infer::ValuePairs::Types(ExpectedFound::new( is_normalized_ty_expected, normalized_ty, - data.term.ty(), + data_ty, ))); err_buf = error; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 4995590baec23..4b53b624c72f1 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -212,10 +212,9 @@ fn project_and_unify_type<'cx, 'tcx>( debug!(?normalized_ty, ?obligations, "project_and_unify_type result"); let infcx = selcx.infcx(); - match infcx - .at(&obligation.cause, obligation.param_env) - .eq(normalized_ty, obligation.predicate.term.ty()) - { + // FIXME(...): Handle consts here as well as types. + let obligation_pred_ty = obligation.predicate.term.ty().unwrap(); + match infcx.at(&obligation.cause, obligation.param_env).eq(normalized_ty, obligation_pred_ty) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); Ok(Ok(Some(obligations))) @@ -1803,7 +1802,9 @@ fn confirm_param_env_candidate<'cx, 'tcx>( Ok(InferOk { value: _, obligations }) => { nested_obligations.extend(obligations); assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); - Progress { ty: cache_entry.term.ty(), obligations: nested_obligations } + // FIXME(...): Handle consts here as well? Maybe this progress type should just take + // a term instead. + Progress { ty: cache_entry.term.ty().unwrap(), obligations: nested_obligations } } Err(e) => { let msg = format!( diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs index acac76cdfaaf0..aea44841b8f12 100644 --- a/compiler/rustc_trait_selection/src/traits/relationships.rs +++ b/compiler/rustc_trait_selection/src/traits/relationships.rs @@ -62,7 +62,7 @@ pub(crate) fn update<'tcx, T>( if let ty::PredicateKind::Projection(predicate) = obligation.predicate.kind().skip_binder() { // If the projection predicate (Foo::Bar == X) has X as a non-TyVid, // we need to make it into one. - if let Some(vid) = predicate.term.ty().ty_vid() { + if let Some(vid) = predicate.term.ty().and_then(|ty| ty.ty_vid()) { debug!("relationship: {:?}.output = true", vid); engine.relationships().entry(vid).or_default().output = true; } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e3b366c65bf5c..6a355b567e091 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -116,7 +116,10 @@ pub fn predicate_obligations<'a, 'tcx>( } ty::PredicateKind::Projection(t) => { wf.compute_projection(t.projection_ty); - wf.compute(t.term.ty().into()); + wf.compute(match t.term { + ty::Term::Ty(ty) => ty.into(), + ty::Term::Const(c) => c.into(), + }) } ty::PredicateKind::WellFormed(arg) => { wf.compute(arg); @@ -219,7 +222,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( // projection coming from another associated type. See // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and // `traits-assoc-type-in-supertrait-bad.rs`. - if let ty::Projection(projection_ty) = proj.term.ty().kind() { + if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind()) { if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id) { diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index e651ff63c5249..dd98e4ae81b34 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -227,12 +227,24 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq>> { fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq> { chalk_ir::AliasEq { - ty: self.term.ty().lower_into(interner), + ty: self.term.ty().unwrap().lower_into(interner), alias: self.projection_ty.lower_into(interner), } } } +/* +// FIXME(...): Where do I add this to Chalk? I can't find it in the rustc repo anywhere. +impl<'tcx> LowerInto<'tcx, chalk_ir::Term>> for rustc_middle::ty::Term<'tcx> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Term> { + match self { + ty::Term::Ty(ty) => ty.lower_into(interner).into(), + ty::Term::Const(c) => c.lower_into(interner).into(), + } + } +} +*/ + impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Ty> { let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i)); @@ -787,7 +799,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound trait_bound: trait_ref.lower_into(interner), associated_ty_id: chalk_ir::AssocTypeId(self.projection_ty.item_def_id), parameters: own_substs.iter().map(|arg| arg.lower_into(interner)).collect(), - value: self.term.ty().lower_into(interner), + value: self.term.ty().unwrap().lower_into(interner), } } } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 2866a7884a77a..a13eaa6f178de 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -123,8 +123,7 @@ struct ConvertedBinding<'a, 'tcx> { #[derive(Debug)] enum ConvertedBindingKind<'a, 'tcx> { - Equality(Ty<'tcx>), - Const(&'tcx Const<'tcx>), + Equality(ty::Term<'tcx>), Constraint(&'a [hir::GenericBound<'a>]), } @@ -604,12 +603,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let kind = match binding.kind { hir::TypeBindingKind::Equality { ref term } => match term { hir::Term::Ty(ref ty) => { - ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty)) + ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty).into()) } hir::Term::Const(ref c) => { let local_did = self.tcx().hir().local_def_id(c.hir_id); let c = Const::from_anon_const(self.tcx(), local_did); - ConvertedBindingKind::Const(&c) + ConvertedBindingKind::Equality(c.into()) } }, hir::TypeBindingKind::Constraint { ref bounds } => { @@ -875,6 +874,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id) .is_some() } + fn trait_defines_associated_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool { + self.tcx() + .associated_items(trait_def_id) + .find_by_name_and_kinds( + self.tcx(), + assoc_name, + &[ty::AssocKind::Type, ty::AssocKind::Const], + trait_def_id, + ) + .is_some() + } // Sets `implicitly_sized` to true on `Bounds` if necessary pub(crate) fn add_implicitly_sized<'hir>( @@ -1223,7 +1233,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } match binding.kind { - ConvertedBindingKind::Equality(ty) => { + ConvertedBindingKind::Equality(term) => { // "Desugar" a constraint like `T: Iterator` this to // the "projection predicate" for: // @@ -1231,16 +1241,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { bounds.projection_bounds.push(( projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, - term: ty.into(), - }), - binding.span, - )); - } - ConvertedBindingKind::Const(c) => { - bounds.projection_bounds.push(( - projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate { - projection_ty, - term: c.into(), + term: term, }), binding.span, )); @@ -1391,8 +1392,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let pred = bound_predicate.rebind(pred); // A `Self` within the original bound will be substituted with a // `trait_object_dummy_self`, so check for that. - let references_self = - pred.skip_binder().term.ty().walk().any(|arg| arg == dummy_self.into()); + let references_self = match pred.skip_binder().term { + ty::Term::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), + ty::Term::Const(c) => { + c.ty.walk().any(|arg| arg == dummy_self.into()) + } + }; // If the projection output contains `Self`, force the user to // elaborate it explicitly to avoid a lot of complexity. @@ -1615,7 +1620,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { I: Iterator>, { let mut matching_candidates = all_candidates() - .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name)); + .filter(|r| self.trait_defines_associated_named(r.def_id(), assoc_name)); let bound = match matching_candidates.next() { Some(bound) => bound, diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index c8e1d8b190c9d..504807e87b69a 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -279,7 +279,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - let ret_param_ty = projection.skip_binder().term.ty(); + // Since this is a return parameter type it is safe to unwrap. + let ret_param_ty = projection.skip_binder().term.ty().unwrap(); let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty); debug!("deduce_sig_from_projection: ret_param_ty={:?}", ret_param_ty); @@ -706,9 +707,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Extract the type from the projection. Note that there can // be no bound variables in this type because the "self type" // does not have any regions in it. - let output_ty = self.resolve_vars_if_possible(predicate.term.ty()); + let output_ty = self.resolve_vars_if_possible(predicate.term); debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty); - Some(output_ty) + // FIXME(...): How to handle consts here? Will this always be a const? + Some(output_ty.ty().unwrap()) } /// Converts the types that the user supplied, in case that doing diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 590d65b7cba3f..bf362357ed073 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -789,10 +789,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_def_id: projection_ty.item_def_id, }; - let ty: Ty<'_> = pred.skip_binder().term.ty(); + let fmt = match pred.skip_binder().term { + ty::Term::Ty(ty) => format!("{}", ty), + ty::Term::Const(c) => format!("{}", c), + }; - let obligation = format!("{} = {}", projection_ty, ty); - let quiet = format!("{} = {}", quiet_projection_ty, ty); + let obligation = format!("{} = {}", projection_ty, fmt); + let quiet = format!("{} = {}", quiet_projection_ty, fmt); bound_span_label(projection_ty.self_ty(), &obligation, &quiet); Some((obligation, projection_ty.self_ty())) diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 8d06b8a7a170b..9f67713d585bd 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -694,7 +694,10 @@ fn bounds_from_generic_predicates<'tcx>( where_clauses.push(format!( "{} = {}", tcx.def_path_str(p.projection_ty.item_def_id), - p.term.ty() + match p.term { + ty::Term::Ty(ty) => format!("{}", ty), + ty::Term::Const(c) => format!("{}", c), + } )); } let where_clauses = if where_clauses.is_empty() { diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 09692d27e8fbe..18a4d8a475380 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -553,8 +553,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { if self.is_fn_trait(trait_) && left_name == sym::Output { ty_to_fn .entry(*ty.clone()) - .and_modify(|e| *e = (e.0.clone(), Some(rhs.clone()))) - .or_insert((None, Some(rhs))); + .and_modify(|e| { + *e = (e.0.clone(), Some(rhs.ty().unwrap().clone())) + }) + .or_insert((None, Some(rhs.ty().unwrap().clone()))); continue; } @@ -570,7 +572,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { GenericArgs::AngleBracketed { ref mut bindings, .. } => { bindings.push(TypeBinding { name: left_name, - kind: TypeBindingKind::Equality { ty: rhs }, + kind: TypeBindingKind::Equality { term: rhs }, }); } GenericArgs::Parenthesized { .. } => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f6af81769b7a1..6a3cdcc2c20da 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -272,9 +272,10 @@ impl Clean for hir::WherePredicate<'_> { bounds: wrp.bounds.iter().filter_map(|x| x.clean(cx)).collect(), }, - hir::WherePredicate::EqPredicate(ref wrp) => { - WherePredicate::EqPredicate { lhs: wrp.lhs_ty.clean(cx), rhs: wrp.rhs_ty.clean(cx) } - } + hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate { + lhs: wrp.lhs_ty.clean(cx), + rhs: wrp.rhs_ty.clean(cx).into(), + }, } } } @@ -352,11 +353,31 @@ impl<'tcx> Clean> for ty::OutlivesPredicate, ty: } } +impl<'tcx> Clean for ty::Term<'tcx> { + fn clean(&self, cx: &mut DocContext<'_>) -> Term { + match self { + ty::Term::Ty(ty) => Term::Type(ty.clean(cx)), + ty::Term::Const(c) => Term::Constant(c.clean(cx)), + } + } +} + +impl<'tcx> Clean for hir::Term<'tcx> { + fn clean(&self, cx: &mut DocContext<'_>) -> Term { + match self { + hir::Term::Ty(ty) => Term::Type(ty.clean(cx)), + hir::Term::Const(c) => { + let def_id = cx.tcx.hir().local_def_id(c.hir_id); + Term::Constant(ty::Const::from_anon_const(cx.tcx, def_id).clean(cx)) + } + } + } +} + impl<'tcx> Clean for ty::ProjectionPredicate<'tcx> { fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate { let ty::ProjectionPredicate { projection_ty, term } = self; - let ty = term.ty(); - WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) } + WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: term.clean(cx) } } } @@ -614,7 +635,7 @@ fn clean_ty_generics( if let Some(param_idx) = param_idx { if let Some(b) = impl_trait.get_mut(¶m_idx.into()) { - let p = p.clean(cx)?; + let p: WherePredicate = p.clean(cx)?; b.extend( p.get_bounds() @@ -624,13 +645,17 @@ fn clean_ty_generics( .filter(|b| !b.is_sized_bound(cx)), ); - let proj = projection.map(|p| { - (p.skip_binder().projection_ty.clean(cx), p.skip_binder().term.ty()) - }); + let proj = projection + .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().term)); if let Some(((_, trait_did, name), rhs)) = proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs))) { - impl_trait_proj.entry(param_idx).or_default().push((trait_did, name, rhs)); + // FIXME(...): Remove this unwrap() + impl_trait_proj.entry(param_idx).or_default().push(( + trait_did, + name, + rhs.ty().unwrap(), + )); } return None; @@ -649,7 +674,7 @@ fn clean_ty_generics( if let Some(proj) = impl_trait_proj.remove(&idx) { for (trait_did, name, rhs) in proj { let rhs = rhs.clean(cx); - simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs); + simplify::merge_bounds(cx, &mut bounds, trait_did, name, &Term::Type(rhs)); } } } else { @@ -1497,7 +1522,9 @@ impl<'tcx> Clean for Ty<'tcx> { for pb in obj.projection_bounds() { bindings.push(TypeBinding { name: cx.tcx.associated_item(pb.item_def_id()).ident.name, - kind: TypeBindingKind::Equality { ty: pb.skip_binder().ty.clean(cx) }, + kind: TypeBindingKind::Equality { + term: pb.skip_binder().ty.clean(cx).into(), + }, }); } @@ -1568,7 +1595,7 @@ impl<'tcx> Clean for Ty<'tcx> { .ident .name, kind: TypeBindingKind::Equality { - ty: proj.term.ty().clean(cx), + term: proj.term.clean(cx), }, }) } else { @@ -2116,10 +2143,9 @@ impl Clean for hir::TypeBinding<'_> { impl Clean for hir::TypeBindingKind<'_> { fn clean(&self, cx: &mut DocContext<'_>) -> TypeBindingKind { match *self { - hir::TypeBindingKind::Equality { ref term } => match term { - hir::Term::Ty(ref ty) => TypeBindingKind::Equality { ty: ty.clean(cx) }, - hir::Term::Const(ref _c) => todo!(), - }, + hir::TypeBindingKind::Equality { ref term } => { + TypeBindingKind::Equality { term: term.clean(cx) } + } hir::TypeBindingKind::Constraint { ref bounds } => TypeBindingKind::Constraint { bounds: bounds.iter().filter_map(|b| b.clean(cx)).collect(), }, diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 4c81e75e8d630..0bad153280822 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -92,7 +92,7 @@ crate fn merge_bounds( bounds: &mut Vec, trait_did: DefId, name: Symbol, - rhs: &clean::Type, + rhs: &clean::Term, ) -> bool { !bounds.iter_mut().any(|b| { let trait_ref = match *b { @@ -110,14 +110,14 @@ crate fn merge_bounds( PP::AngleBracketed { ref mut bindings, .. } => { bindings.push(clean::TypeBinding { name, - kind: clean::TypeBindingKind::Equality { ty: rhs.clone() }, + kind: clean::TypeBindingKind::Equality { term: rhs.clone() }, }); } PP::Parenthesized { ref mut output, .. } => match output { - Some(o) => assert_eq!(o.as_ref(), rhs), + Some(o) => assert_eq!(&clean::Term::Type(o.as_ref().clone()), rhs), None => { - if *rhs != clean::Type::Tuple(Vec::new()) { - *output = Some(Box::new(rhs.clone())); + if *rhs != clean::Term::Type(clean::Type::Tuple(Vec::new())) { + *output = Some(Box::new(rhs.ty().unwrap().clone())); } } }, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 00c6e38839f54..ba771c0c1a1a4 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1212,7 +1212,7 @@ impl Lifetime { crate enum WherePredicate { BoundPredicate { ty: Type, bounds: Vec, bound_params: Vec }, RegionPredicate { lifetime: Lifetime, bounds: Vec }, - EqPredicate { lhs: Type, rhs: Type }, + EqPredicate { lhs: Type, rhs: Term }, } impl WherePredicate { @@ -1308,7 +1308,12 @@ impl FnDecl { FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] { GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => { let bindings = trait_.bindings().unwrap(); - FnRetTy::Return(bindings[0].ty().clone()) + let ret_ty = bindings[0].term(); + let ty = match ret_ty { + Term::Type(ty) => ty, + Term::Constant(_c) => unreachable!(), + }; + FnRetTy::Return(ty.clone()) } _ => panic!("unexpected desugaring of async function"), }, @@ -2121,6 +2126,24 @@ crate struct Constant { crate kind: ConstantKind, } +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +crate enum Term { + Type(Type), + Constant(Constant), +} + +impl Term { + crate fn ty(&self) -> Option<&Type> { + if let Term::Type(ty) = self { Some(ty) } else { None } + } +} + +impl From for Term { + fn from(ty: Type) -> Self { + Term::Type(ty) + } +} + #[derive(Clone, PartialEq, Eq, Hash, Debug)] crate enum ConstantKind { /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a @@ -2283,14 +2306,14 @@ crate struct TypeBinding { #[derive(Clone, PartialEq, Eq, Debug, Hash)] crate enum TypeBindingKind { - Equality { ty: Type }, + Equality { term: Term }, Constraint { bounds: Vec }, } impl TypeBinding { - crate fn ty(&self) -> &Type { + crate fn term(&self) -> &Term { match self.kind { - TypeBindingKind::Equality { ref ty } => ty, + TypeBindingKind::Equality { ref term } => term, _ => panic!("expected equality type binding for parenthesized generic args"), } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 8571a6a137f51..08840626259dc 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1442,11 +1442,11 @@ impl clean::TypeBinding { display_fn(move |f| { f.write_str(self.name.as_str())?; match self.kind { - clean::TypeBindingKind::Equality { ref ty } => { + clean::TypeBindingKind::Equality { ref term } => { if f.alternate() { - write!(f, " = {:#}", ty.print(cx))?; + write!(f, " = {:#}", term.print(cx))?; } else { - write!(f, " = {}", ty.print(cx))?; + write!(f, " = {}", term.print(cx))?; } } clean::TypeBindingKind::Constraint { ref bounds } => { @@ -1492,6 +1492,18 @@ impl clean::GenericArg { } } +impl clean::types::Term { + crate fn print<'a, 'tcx: 'a>( + &'a self, + cx: &'a Context<'tcx>, + ) -> impl fmt::Display + 'a + Captures<'tcx> { + match self { + clean::types::Term::Type(ty) => ty.print(cx), + _ => todo!(), + } + } +} + crate fn display_fn(f: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Display { struct WithFormatter(Cell>); diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index c8efa4bbbcc30..e77bd5c922313 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -162,7 +162,7 @@ impl FromWithTcx for TypeBindingKind { fn from_tcx(kind: clean::TypeBindingKind, tcx: TyCtxt<'_>) -> Self { use clean::TypeBindingKind::*; match kind { - Equality { ty } => TypeBindingKind::Equality(ty.into_tcx(tcx)), + Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)), Constraint { bounds } => { TypeBindingKind::Constraint(bounds.into_iter().map(|a| a.into_tcx(tcx)).collect()) } @@ -452,6 +452,15 @@ impl FromWithTcx for Type { } } +impl FromWithTcx for Term { + fn from_tcx(term: clean::Term, tcx: TyCtxt<'_>) -> Term { + match term { + clean::Term::Type(ty) => Term::Type(FromWithTcx::from_tcx(ty, tcx)), + clean::Term::Constant(c) => Term::Constant(FromWithTcx::from_tcx(c, tcx)), + } + } +} + impl FromWithTcx for FunctionPointer { fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self { let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl; diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 9466f84ffcd59..618c8aab86a19 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -148,7 +148,7 @@ pub struct TypeBinding { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] pub enum TypeBindingKind { - Equality(Type), + Equality(Term), Constraint(Vec), } @@ -335,7 +335,7 @@ pub enum GenericParamDefKind { pub enum WherePredicate { BoundPredicate { ty: Type, bounds: Vec }, RegionPredicate { lifetime: String, bounds: Vec }, - EqPredicate { lhs: Type, rhs: Type }, + EqPredicate { lhs: Type, rhs: Term }, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] @@ -359,6 +359,13 @@ pub enum TraitBoundModifier { MaybeConst, } +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum Term { + Type(Type), + Constant(Constant), +} + #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "snake_case")] #[serde(tag = "kind", content = "inner")] diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr index 07d194476a5db..ad51707070f9f 100644 --- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr +++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -1,4 +1,4 @@ -error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[HASH]::Id::This) }, (I,)), [])` +error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[HASH]::Id::This) }, Ty((I,))), [])` --> $DIR/repeated_projection_type.rs:19:1 | LL | / impl> X for V { diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index c0e65e520f23a..ca8bbbd8f9169 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -2141,12 +2141,16 @@ impl<'tcx> LateLintPass<'tcx> for Methods { // one of the associated types must be Self for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() { + let assoc_ty = match projection_predicate.term { + ty::Term::Ty(ty) => ty, + ty::Term::Const(c) => c.ty, + }; // walk the associated type and check for Self if let Some(self_adt) = self_ty.ty_adt_def() { - if contains_adt_constructor(projection_predicate.term.ty(), self_adt) { + if contains_adt_constructor(assoc_ty, self_adt) { return; } - } else if contains_ty(projection_predicate.term.ty(), self_ty) { + } else if contains_ty(assoc_ty, self_ty) { return; } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 865a36a5cd1d6..9162de3cceafa 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -243,9 +243,10 @@ fn check_other_call_arg<'tcx>( if if trait_predicate.def_id() == deref_trait_id { if let [projection_predicate] = projection_predicates[..] { let normalized_ty = - cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term.ty()); + cx.tcx.subst_and_normalize_erasing_regions(call_substs, cx.param_env, projection_predicate.term); implements_trait(cx, receiver_ty, deref_trait_id, &[]) - && get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(normalized_ty) + && get_associated_type(cx, receiver_ty, deref_trait_id, + "Target").map_or(false, |ty| ty::Term::Ty(ty) == normalized_ty) } else { false } diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs index 09f9e1ee09990..68156df2ecea8 100644 --- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs +++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs @@ -98,9 +98,10 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve if trait_pred.self_ty() == inp; if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred); then { - if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.term.ty()) { + if ord_preds.iter().any(|ord| Some(ord.self_ty()) == + return_ty_pred.term.ty()) { args_to_check.push((i, "Ord".to_string())); - } else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.term.ty()) { + } else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.term.ty().unwrap()) { args_to_check.push((i, "PartialOrd".to_string())); } } From f396888c4d816f7d0980aba041014169dd71a2a7 Mon Sep 17 00:00:00 2001 From: kadmin Date: Tue, 11 Jan 2022 19:18:18 +0000 Subject: [PATCH 5/7] Update w/ comments Removes uses of ty() where a method is implemented on TypeFoldable, and also directly formats a Term. --- compiler/rustc_middle/src/ty/print/pretty.rs | 8 +++++++- compiler/rustc_middle/src/ty/sty.rs | 7 +++---- compiler/rustc_privacy/src/lib.rs | 10 ++-------- .../rustc_trait_selection/src/traits/auto_trait.rs | 3 +-- compiler/rustc_typeck/src/check/closure.rs | 2 +- compiler/rustc_typeck/src/check/method/suggest.rs | 9 +++------ compiler/rustc_typeck/src/check/mod.rs | 5 +---- .../src/impl_wf_check/min_specialization.rs | 2 +- src/librustdoc/clean/types.rs | 5 +---- src/tools/clippy/clippy_lints/src/methods/mod.rs | 2 +- 10 files changed, 21 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6fcb6ac5f4c0b..c6b03739927a3 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -905,7 +905,13 @@ pub trait PrettyPrinter<'tcx>: } for (assoc_item_def_id, term) in assoc_items { - let ty = if let Term::Ty(ty) = term.skip_binder() { ty } else { continue }; + let ty = match term.skip_binder() { + Term::Ty(ty) => ty, + Term::Const(c) => { + p!(print(c)); + continue; + } + }; if !first { p!(", "); } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 453e380f6e3a0..ffc339f358883 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1580,10 +1580,9 @@ impl<'tcx> ExistentialProjection<'tcx> { ) -> Self { // Assert there is a Self. projection_predicate.projection_ty.substs.type_at(0); - let ty = if let Term::Ty(ty) = projection_predicate.term { - ty - } else { - panic!("Only types are permitted here"); + let ty = match projection_predicate.term { + Term::Ty(ty) => ty, + Term::Const(_c) => unimplemented!(), }; Self { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 73873c8cf0d91..66767e2b81fdc 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -128,10 +128,7 @@ where polarity: _, }) => self.visit_trait(trait_ref), ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { - match term { - ty::Term::Ty(ty) => ty.visit_with(self)?, - ty::Term::Const(ct) => ct.visit_with(self)?, - } + term.visit_with(self)?; self.visit_projection_ty(projection_ty) } ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => { @@ -1189,10 +1186,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { for (poly_predicate, _) in bounds.projection_bounds { let pred = poly_predicate.skip_binder(); - let poly_pred_term = match pred.term { - ty::Term::Ty(ty) => self.visit(ty), - ty::Term::Const(ct) => self.visit(ct), - }; + let poly_pred_term = self.visit(pred.term); if poly_pred_term.is_break() || self.visit_projection_ty(pred.projection_ty).is_break() { diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index cc20c1179452c..8a33d26fa8658 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -779,8 +779,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // However, we should always make progress (either by generating // subobligations or getting an error) when we started off with // inference variables - if p.term().skip_binder().ty().map_or(false, |ty| ty.has_infer_types()) - { + if p.term().skip_binder().ty().has_infer_types() { panic!("Unexpected result when selecting {:?} {:?}", ty, obligation) } } diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 504807e87b69a..e88099afa0353 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -709,7 +709,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // does not have any regions in it. let output_ty = self.resolve_vars_if_possible(predicate.term); debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty); - // FIXME(...): How to handle consts here? Will this always be a const? + // This is a projection on a Fn trait so will always be a type. Some(output_ty.ty().unwrap()) } diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index bf362357ed073..56f4d5afe400d 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -789,13 +789,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_def_id: projection_ty.item_def_id, }; - let fmt = match pred.skip_binder().term { - ty::Term::Ty(ty) => format!("{}", ty), - ty::Term::Const(c) => format!("{}", c), - }; + let term = pred.skip_binder().term; - let obligation = format!("{} = {}", projection_ty, fmt); - let quiet = format!("{} = {}", quiet_projection_ty, fmt); + let obligation = format!("{} = {}", projection_ty, term); + let quiet = format!("{} = {}", quiet_projection_ty, term); bound_span_label(projection_ty.self_ty(), &obligation, &quiet); Some((obligation, projection_ty.self_ty())) diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 9f67713d585bd..f748b88d90ce3 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -694,10 +694,7 @@ fn bounds_from_generic_predicates<'tcx>( where_clauses.push(format!( "{} = {}", tcx.def_path_str(p.projection_ty.item_def_id), - match p.term { - ty::Term::Ty(ty) => format!("{}", ty), - ty::Term::Const(c) => format!("{}", c), - } + p.term, )); } let where_clauses = if where_clauses.is_empty() { 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 5e6704c9864fc..d87e670a8fb5a 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -199,7 +199,7 @@ fn unconstrained_parent_impl_substs<'tcx>( for (predicate, _) in impl_generic_predicates.predicates.iter() { if let ty::PredicateKind::Projection(proj) = predicate.kind().skip_binder() { let projection_ty = proj.projection_ty; - let projected_ty = proj.term.ty(); + let projected_ty = proj.term; let unbound_trait_ref = projection_ty.trait_ref(tcx); if Some(unbound_trait_ref) == impl_trait_ref { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index ba771c0c1a1a4..fac1a0817e033 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1309,10 +1309,7 @@ impl FnDecl { GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => { let bindings = trait_.bindings().unwrap(); let ret_ty = bindings[0].term(); - let ty = match ret_ty { - Term::Type(ty) => ty, - Term::Constant(_c) => unreachable!(), - }; + let ty = ret_ty.ty().expect("Unexpected constant return term"); FnRetTy::Return(ty.clone()) } _ => panic!("unexpected desugaring of async function"), diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index ca8bbbd8f9169..d5b928de4a81a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -2143,7 +2143,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() { let assoc_ty = match projection_predicate.term { ty::Term::Ty(ty) => ty, - ty::Term::Const(c) => c.ty, + ty::Term::Const(_c) => continue, }; // walk the associated type and check for Self if let Some(self_adt) = self_ty.ty_adt_def() { From 1c1ce2fbda9c5d385fcb222d98d948aa4616fe91 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 13 Jan 2022 07:39:58 +0000 Subject: [PATCH 6/7] Add term to ExistentialProjection Also prevent ICE when adding a const in associated const equality. --- compiler/rustc_ast_passes/src/feature_gate.rs | 1 + .../src/debuginfo/type_names.rs | 5 ++- compiler/rustc_feature/src/active.rs | 2 + .../src/infer/error_reporting/mod.rs | 8 +--- compiler/rustc_middle/src/ty/diagnostics.rs | 12 ++++-- compiler/rustc_middle/src/ty/flags.rs | 5 ++- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 38 ++++++++++--------- compiler/rustc_middle/src/ty/relate.rs | 8 ++-- .../rustc_middle/src/ty/structural_impls.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 10 ++--- compiler/rustc_middle/src/ty/walk.rs | 7 +++- compiler/rustc_parse/src/parser/path.rs | 5 ++- compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_symbol_mangling/src/v0.rs | 5 ++- .../src/traits/auto_trait.rs | 5 +-- .../src/traits/error_reporting/mod.rs | 2 +- .../src/traits/object_safety.rs | 2 +- .../src/traits/project.rs | 2 +- compiler/rustc_traits/src/chalk/lowering.rs | 4 +- compiler/rustc_typeck/src/astconv/mod.rs | 11 +++++- .../rustc_typeck/src/variance/constraints.rs | 13 ++++--- src/etc/check_missing_items.py | 4 +- src/librustdoc/clean/mod.rs | 2 +- src/test/ui/associated-consts/assoc-const.rs | 6 ++- .../ui/associated-consts/assoc-const.stderr | 33 ++++++++++++++++ .../issue-89013-no-kw.rs | 1 + .../issue-89013-no-kw.stderr | 13 ++++++- .../parser-error-recovery/issue-89013.rs | 1 + .../parser-error-recovery/issue-89013.stderr | 13 ++++++- .../feature-gate-associated_const_equality.rs | 16 ++++++++ ...ture-gate-associated_const_equality.stderr | 18 +++++++++ .../parser/recover-assoc-const-constraint.rs | 4 +- .../recover-assoc-const-constraint.stderr | 21 ++++++++++ src/tools/rustfmt/src/types.rs | 2 +- 35 files changed, 213 insertions(+), 71 deletions(-) create mode 100644 src/test/ui/associated-consts/assoc-const.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-associated_const_equality.rs create mode 100644 src/test/ui/feature-gates/feature-gate-associated_const_equality.stderr create mode 100644 src/test/ui/parser/recover-assoc-const-constraint.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0cc74a1ac0b62..89671788255a9 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -724,6 +724,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); gate_all!(inline_const, "inline-const is experimental"); gate_all!(inline_const_pat, "inline-const in pattern position is experimental"); + gate_all!(associated_const_equality, "associated const equality is incomplete"); // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 61322a6e556ed..9687fd09a53bc 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -203,8 +203,9 @@ fn push_debuginfo_type_name<'tcx>( let projection_bounds: SmallVec<[_; 4]> = trait_data .projection_bounds() .map(|bound| { - let ExistentialProjection { item_def_id, ty, .. } = bound.skip_binder(); - (item_def_id, ty) + let ExistentialProjection { item_def_id, term, .. } = bound.skip_binder(); + // FIXME(associated_const_equality): allow for consts here + (item_def_id, term.ty().unwrap()) }) .collect(); diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index ebd12d6ab4e2d..47010ea3ab613 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -288,6 +288,8 @@ declare_features! ( (active, asm_sym, "1.58.0", Some(72016), None), /// Allows the `may_unwind` option in inline assembly. (active, asm_unwind, "1.58.0", Some(72016), None), + /// Allows users to enforce equality of associated constants `TraitImpl`. + (active, associated_const_equality, "1.58.0", Some(92827), None), /// Allows the user of associated type bounds. (active, associated_type_bounds, "1.34.0", Some(52662), None), /// Allows associated type defaults. diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index f1e99faba01bd..e98b9c3b03c5a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -69,7 +69,7 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ self, subst::{GenericArgKind, Subst, SubstsRef}, - Region, Term, Ty, TyCtxt, TypeFoldable, + Region, Ty, TyCtxt, TypeFoldable, }; use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span}; use rustc_target::spec::abi; @@ -1780,11 +1780,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { { if projection_predicate.projection_ty.item_def_id == item_def_id { // We don't account for multiple `Future::Output = Ty` contraints. - match projection_predicate.term { - Term::Ty(ty) => return Some(ty), - // Can return None, but not sure if that makes sense? - Term::Const(_c) => todo!(), - } + return projection_predicate.term.ty(); } } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index ee00f6c62f345..b4c9cc7782c7b 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -4,7 +4,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::TyKind::*; use crate::ty::{ ConstKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, InferTy, - ProjectionTy, TyCtxt, TyS, TypeAndMut, + ProjectionTy, Term, TyCtxt, TyS, TypeAndMut, }; use rustc_errors::{Applicability, DiagnosticBuilder}; @@ -105,8 +105,14 @@ impl<'tcx> TyS<'tcx> { ExistentialPredicate::Trait(ExistentialTraitRef { substs, .. }) => { substs.iter().all(generic_arg_is_suggestible) } - ExistentialPredicate::Projection(ExistentialProjection { substs, ty, .. }) => { - ty.is_suggestable() && substs.iter().all(generic_arg_is_suggestible) + ExistentialPredicate::Projection(ExistentialProjection { + substs, term, .. + }) => { + let term_is_suggestable = match term { + Term::Ty(ty) => ty.is_suggestable(), + Term::Const(c) => const_is_suggestable(c.val), + }; + term_is_suggestable && substs.iter().all(generic_arg_is_suggestible) } _ => true, }), diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index be9021dc61989..f06a1b09cd82a 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -320,7 +320,10 @@ impl FlagComputation { fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) { self.add_substs(projection.substs); - self.add_ty(projection.ty); + match projection.term { + ty::Term::Ty(ty) => self.add_ty(ty), + ty::Term::Const(ct) => self.add_const(ct), + } } fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 42e6f3f6ef584..4bc3e23f4a588 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -795,7 +795,7 @@ pub struct CoercePredicate<'tcx> { } pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable)] pub enum Term<'tcx> { Ty(Ty<'tcx>), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index c6b03739927a3..bbdaf248a9e72 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -905,29 +905,27 @@ pub trait PrettyPrinter<'tcx>: } for (assoc_item_def_id, term) in assoc_items { - let ty = match term.skip_binder() { - Term::Ty(ty) => ty, - Term::Const(c) => { - p!(print(c)); - continue; - } - }; if !first { p!(", "); } p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).ident)); - // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks - match ty.kind() { - ty::Projection(ty::ProjectionTy { item_def_id, .. }) - if Some(*item_def_id) == self.tcx().lang_items().generator_return() => - { - p!("[async output]") + match term.skip_binder() { + Term::Ty(ty) => { + // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks + if matches!( + ty.kind(), ty::Projection(ty::ProjectionTy { item_def_id, .. }) + if Some(*item_def_id) == self.tcx().lang_items().generator_return() + ) { + p!("[async output]") + } else { + p!(print(ty)) + } } - _ => { - p!(print(ty)) + Term::Const(c) => { + p!(print(c)); } - } + }; first = false; } @@ -1031,7 +1029,11 @@ pub trait PrettyPrinter<'tcx>: let mut projections = predicates.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect(); - p!(pretty_fn_sig(&tys, false, proj.skip_binder().ty)); + p!(pretty_fn_sig( + &tys, + false, + proj.skip_binder().term.ty().expect("Return type was a const") + )); resugared = true; } } @@ -2454,7 +2456,7 @@ define_print_and_forward_display! { ty::ExistentialProjection<'tcx> { let name = cx.tcx().associated_item(self.item_def_id).ident; - p!(write("{} = ", name), print(self.ty)) + p!(write("{} = ", name), print(self.term)) } ty::ExistentialPredicate<'tcx> { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index bd6c24445ef51..bb040acd2703d 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -291,11 +291,11 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { b.item_def_id, ))) } else { - let ty = relation.relate_with_variance( + let term = relation.relate_with_variance( ty::Invariant, ty::VarianceDiagInfo::default(), - a.ty, - b.ty, + a.term, + b.term, )?; let substs = relation.relate_with_variance( ty::Invariant, @@ -303,7 +303,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { a.substs, b.substs, )?; - Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty }) + Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, term }) } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 3cbea92ae6714..1c5bc7860db2d 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -423,7 +423,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> { fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { tcx.lift(self.substs).map(|substs| ty::ExistentialProjection { substs, - ty: tcx.lift(self.ty).expect("type must lift when substs do"), + term: tcx.lift(self.term).expect("type must lift when substs do"), item_def_id: self.item_def_id, }) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index ffc339f358883..20db25f7899dd 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1540,7 +1540,7 @@ impl From for BoundTy { pub struct ExistentialProjection<'tcx> { pub item_def_id: DefId, pub substs: SubstsRef<'tcx>, - pub ty: Ty<'tcx>, + pub term: Term<'tcx>, } pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>; @@ -1570,7 +1570,7 @@ impl<'tcx> ExistentialProjection<'tcx> { item_def_id: self.item_def_id, substs: tcx.mk_substs_trait(self_ty, self.substs), }, - term: self.ty.into(), + term: self.term, } } @@ -1580,15 +1580,11 @@ impl<'tcx> ExistentialProjection<'tcx> { ) -> Self { // Assert there is a Self. projection_predicate.projection_ty.substs.type_at(0); - let ty = match projection_predicate.term { - Term::Ty(ty) => ty, - Term::Const(_c) => unimplemented!(), - }; Self { item_def_id: projection_predicate.projection_ty.item_def_id, substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]), - ty, + term: projection_predicate.term, } } } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 6808316a23095..38aa76333851f 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -157,7 +157,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) stack.extend(obj.iter().rev().flat_map(|predicate| { let (substs, opt_ty) = match predicate.skip_binder() { ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), - ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.ty)), + ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.term)), ty::ExistentialPredicate::AutoTrait(_) => // Empty iterator { @@ -165,7 +165,10 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) } }; - substs.iter().rev().chain(opt_ty.map(|ty| ty.into())) + substs.iter().rev().chain(opt_ty.map(|term| match term { + ty::Term::Ty(ty) => ty.into(), + ty::Term::Const(ct) => ct.into(), + })) })); } ty::Adt(_, substs) diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 531cac1f57e56..4e60b7593c651 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -505,7 +505,10 @@ impl<'a> Parser<'a> { let span = ident.span.to(self.prev_token.span); let term = match arg { Some(GenericArg::Type(ty)) => ty.into(), - Some(GenericArg::Const(c)) => c.into(), + Some(GenericArg::Const(c)) => { + self.sess.gated_spans.gate(sym::associated_const_equality, span); + c.into() + } Some(GenericArg::Lifetime(lt)) => { self.struct_span_err(span, "associated lifetimes are not supported") .span_label(lt.ident.span, "the lifetime is given here") diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8020893e1663c..2ff888bfb48a2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -343,6 +343,7 @@ symbols! { assert_receiver_is_total_eq, assert_uninit_valid, assert_zero_valid, + associated_const_equality, associated_consts, associated_type_bounds, associated_type_defaults, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 14e12bed59e1e..809b973252974 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -559,7 +559,10 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { let name = cx.tcx.associated_item(projection.item_def_id).ident; cx.push("p"); cx.push_ident(name.as_str()); - cx = projection.ty.print(cx)?; + cx = match projection.term { + ty::Term::Ty(ty) => ty.print(cx), + ty::Term::Const(c) => c.print(cx), + }?; } ty::ExistentialPredicate::AutoTrait(def_id) => { cx = cx.print_def_path(*def_id, &[])?; diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 8a33d26fa8658..e2afea76b77f5 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -756,8 +756,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // when we started out trying to unify // some inference variables. See the comment above // for more infomration - if p.term().skip_binder().ty().map_or(false, |ty| ty.has_infer_types()) - { + if p.term().skip_binder().ty().has_infer_types() { if !self.evaluate_nested_obligations( ty, v.into_iter(), @@ -779,7 +778,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // However, we should always make progress (either by generating // subobligations or getting an error) when we started off with // inference variables - if p.term().skip_binder().ty().has_infer_types() { + if p.term().skip_binder().has_infer_types() { panic!("Unexpected result when selecting {:?} {:?}", ty, obligation) } } 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 43a961c5c9116..65385851d054f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1314,7 +1314,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::ObjectCastObligation(_) | ObligationCauseCode::OpaqueType ); - // FIXME(...): Handle Consts here + // FIXME(associated_const_equality): Handle Consts here let data_ty = data.term.ty().unwrap(); if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( is_normalized_ty_expected, diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 185d64eab707a..7bfedecbdc7c9 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -571,7 +571,7 @@ fn object_ty_for_trait<'tcx>( // `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`. super_trait_ref.map_bound(|super_trait_ref| { ty::ExistentialPredicate::Projection(ty::ExistentialProjection { - ty: tcx.mk_projection(item.def_id, super_trait_ref.substs), + term: tcx.mk_projection(item.def_id, super_trait_ref.substs).into(), item_def_id: item.def_id, substs: super_trait_ref.substs, }) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 4b53b624c72f1..2bbdb72a4fb8a 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -212,7 +212,7 @@ fn project_and_unify_type<'cx, 'tcx>( debug!(?normalized_ty, ?obligations, "project_and_unify_type result"); let infcx = selcx.infcx(); - // FIXME(...): Handle consts here as well as types. + // FIXME(associated_const_equality): Handle consts here as well as types. let obligation_pred_ty = obligation.predicate.term.ty().unwrap(); match infcx.at(&obligation.cause, obligation.param_env).eq(normalized_ty, obligation_pred_ty) { Ok(InferOk { obligations: inferred_obligations, value: () }) => { diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index dd98e4ae81b34..67d0ba39667d3 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -226,6 +226,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq>> for rustc_middle::ty::ProjectionPredicate<'tcx> { fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq> { + // FIXME(associated_const_equality): teach chalk about terms for alias eq. chalk_ir::AliasEq { ty: self.term.ty().unwrap().lower_into(interner), alias: self.projection_ty.lower_into(interner), @@ -663,7 +664,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders chalk_ir::Binders::new( diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index a13eaa6f178de..a1f1adb80581d 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1136,9 +1136,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .associated_items(candidate.def_id()) .filter_by_name_unhygienic(assoc_ident.name) .find(|i| { - i.kind == ty::AssocKind::Type && i.ident.normalize_to_macros_2_0() == assoc_ident + (i.kind == ty::AssocKind::Type || i.kind == ty::AssocKind::Const) + && i.ident.normalize_to_macros_2_0() == assoc_ident }) .expect("missing associated type"); + // FIXME(associated_const_equality): need to handle assoc_consts here as well. + if assoc_ty.kind == ty::AssocKind::Const { + tcx.sess + .struct_span_err(path_span, &format!("associated const equality is incomplete")) + .span_label(path_span, "cannot yet relate associated const") + .emit(); + return Err(ErrorReported); + } if !assoc_ty.vis.is_accessible_from(def_scope, tcx) { tcx.sess diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs index b2b607a2ffc28..7c504a0d89c59 100644 --- a/compiler/rustc_typeck/src/variance/constraints.rs +++ b/compiler/rustc_typeck/src/variance/constraints.rs @@ -308,11 +308,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } for projection in data.projection_bounds() { - self.add_constraints_from_ty( - current, - projection.skip_binder().ty, - self.invariant, - ); + match projection.skip_binder().term { + ty::Term::Ty(ty) => { + self.add_constraints_from_ty(current, ty, self.invariant); + } + ty::Term::Const(c) => { + self.add_constraints_from_const(current, c, self.invariant) + } + } } } diff --git a/src/etc/check_missing_items.py b/src/etc/check_missing_items.py index 7ed317c778fce..de1717b3f3f9a 100644 --- a/src/etc/check_missing_items.py +++ b/src/etc/check_missing_items.py @@ -83,7 +83,9 @@ def check_type(ty): check_type(arg["const"]["type"]) for binding in args["angle_bracketed"]["bindings"]: if "equality" in binding["binding"]: - check_type(binding["binding"]["equality"]) + term = binding["binding"]["equality"] + if "type" in term: check_type(term["type"]) + elif "const" in term: check_type(term["const"]) elif "constraint" in binding["binding"]: for bound in binding["binding"]["constraint"]: check_generic_bound(bound) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6a3cdcc2c20da..e759baa045892 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1523,7 +1523,7 @@ impl<'tcx> Clean for Ty<'tcx> { bindings.push(TypeBinding { name: cx.tcx.associated_item(pb.item_def_id()).ident.name, kind: TypeBindingKind::Equality { - term: pb.skip_binder().ty.clean(cx).into(), + term: pb.skip_binder().term.clean(cx).into(), }, }); } diff --git a/src/test/ui/associated-consts/assoc-const.rs b/src/test/ui/associated-consts/assoc-const.rs index 582d0a6922985..9e6bfa346ec0d 100644 --- a/src/test/ui/associated-consts/assoc-const.rs +++ b/src/test/ui/associated-consts/assoc-const.rs @@ -1,5 +1,3 @@ -// run-pass - pub trait Foo { const N: usize; } @@ -14,6 +12,10 @@ const TEST:usize = 3; fn foo>() {} +//~^ ERROR associated const equality is incomplete +//~| ERROR associated const equality is incomplete fn bar>() {} +//~^ ERROR associated const equality is incomplete +//~| ERROR associated const equality is incomplete fn main() {} diff --git a/src/test/ui/associated-consts/assoc-const.stderr b/src/test/ui/associated-consts/assoc-const.stderr new file mode 100644 index 0000000000000..07da190bc8f90 --- /dev/null +++ b/src/test/ui/associated-consts/assoc-const.stderr @@ -0,0 +1,33 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/assoc-const.rs:14:15 + | +LL | fn foo>() {} + | ^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0658]: associated const equality is incomplete + --> $DIR/assoc-const.rs:17:15 + | +LL | fn bar>() {} + | ^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error: associated const equality is incomplete + --> $DIR/assoc-const.rs:14:15 + | +LL | fn foo>() {} + | ^^^ cannot yet relate associated const + +error: associated const equality is incomplete + --> $DIR/assoc-const.rs:17:15 + | +LL | fn bar>() {} + | ^^^^^^^^ cannot yet relate associated const + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs index 32b08fb97f271..b126b24853ff7 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs @@ -9,6 +9,7 @@ const T: usize = 42; impl Foo for Bar { //~^ ERROR this trait takes 1 generic argument but 0 generic arguments were supplied //~| ERROR associated type bindings are not allowed here +//~| ERROR associated const equality is incomplete fn do_x(&self) -> [u8; 3] { [0u8; 3] } diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr index 455f6f61aada3..59ba054aa1127 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr @@ -1,3 +1,12 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/issue-89013-no-kw.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/issue-89013-no-kw.rs:9:6 | @@ -20,7 +29,7 @@ error[E0229]: associated type bindings are not allowed here LL | impl Foo for Bar { | ^^^^^ associated type not allowed here -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0107, E0229. +Some errors have detailed explanations: E0107, E0229, E0658. For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs index 97c22fa7862d5..9431779faf859 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs @@ -10,6 +10,7 @@ impl Foo for Bar { //~^ ERROR expected lifetime, type, or constant, found keyword `const` //~| ERROR this trait takes 1 generic //~| ERROR associated type bindings are not allowed here +//~| ERROR associated const equality is incomplete fn do_x(&self) -> [u8; 3] { [0u8; 3] } diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr index 57108d718cfde..9d4739926700b 100644 --- a/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr +++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr @@ -10,6 +10,15 @@ LL - impl Foo for Bar { LL + impl Foo for Bar { | +error[E0658]: associated const equality is incomplete + --> $DIR/issue-89013.rs:9:10 + | +LL | impl Foo for Bar { + | ^^^^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/issue-89013.rs:9:6 | @@ -32,7 +41,7 @@ error[E0229]: associated type bindings are not allowed here LL | impl Foo for Bar { | ^^^^^^^^^^^ associated type not allowed here -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0107, E0229. +Some errors have detailed explanations: E0107, E0229, E0658. For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/feature-gates/feature-gate-associated_const_equality.rs b/src/test/ui/feature-gates/feature-gate-associated_const_equality.rs new file mode 100644 index 0000000000000..b51ead2a18866 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-associated_const_equality.rs @@ -0,0 +1,16 @@ +pub trait TraitWAssocConst { + const A: usize; +} +pub struct Demo {} + +impl TraitWAssocConst for Demo { + const A: usize = 32; +} + +fn foo>() {} +//~^ ERROR associated const equality +//~| ERROR associated const equality + +fn main() { + foo::(); +} diff --git a/src/test/ui/feature-gates/feature-gate-associated_const_equality.stderr b/src/test/ui/feature-gates/feature-gate-associated_const_equality.stderr new file mode 100644 index 0000000000000..f4db49c4af884 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-associated_const_equality.stderr @@ -0,0 +1,18 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/feature-gate-associated_const_equality.rs:10:28 + | +LL | fn foo>() {} + | ^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error: associated const equality is incomplete + --> $DIR/feature-gate-associated_const_equality.rs:10:28 + | +LL | fn foo>() {} + | ^^^^ cannot yet relate associated const + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/parser/recover-assoc-const-constraint.rs b/src/test/ui/parser/recover-assoc-const-constraint.rs index 3f7423dcb8e0c..1453e6cb5cd7c 100644 --- a/src/test/ui/parser/recover-assoc-const-constraint.rs +++ b/src/test/ui/parser/recover-assoc-const-constraint.rs @@ -1,9 +1,9 @@ -// run-pass - #[cfg(FALSE)] fn syntax() { bar::(); + //~^ ERROR associated const equality is incomplete bar::(); + //~^ ERROR associated const equality is incomplete } fn main() {} diff --git a/src/test/ui/parser/recover-assoc-const-constraint.stderr b/src/test/ui/parser/recover-assoc-const-constraint.stderr new file mode 100644 index 0000000000000..2d36ce4e98632 --- /dev/null +++ b/src/test/ui/parser/recover-assoc-const-constraint.stderr @@ -0,0 +1,21 @@ +error[E0658]: associated const equality is incomplete + --> $DIR/recover-assoc-const-constraint.rs:3:11 + | +LL | bar::(); + | ^^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0658]: associated const equality is incomplete + --> $DIR/recover-assoc-const-constraint.rs:5:11 + | +LL | bar::(); + | ^^^^^^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 9d5f790e80956..5de30129266a3 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -211,7 +211,7 @@ impl Rewrite for ast::AssocConstraintKind { match self { ast::AssocConstraintKind::Equality { term } => match term { Term::Ty(ty) => ty.rewrite(context, shape), - Term::Const(c) => c.rewrite(context,shape), + Term::Const(c) => c.rewrite(context, shape), }, ast::AssocConstraintKind::Bound { bounds } => bounds.rewrite(context, shape), } From b77bb5cb2589246cf684431ad2a184466940633d Mon Sep 17 00:00:00 2001 From: kadmin Date: Fri, 14 Jan 2022 19:01:35 +0000 Subject: [PATCH 7/7] Update with final comments --- .../src/traits/auto_trait.rs | 2 +- .../src/traits/error_reporting/mod.rs | 4 +-- .../src/traits/project.rs | 2 +- compiler/rustc_typeck/src/astconv/mod.rs | 4 +-- src/test/ui/associated-consts/assoc-const.rs | 4 +-- .../ui/associated-consts/assoc-const.stderr | 25 +++---------------- 6 files changed, 10 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index e2afea76b77f5..f2ed5ae26a3c2 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -756,7 +756,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // when we started out trying to unify // some inference variables. See the comment above // for more infomration - if p.term().skip_binder().ty().has_infer_types() { + if p.term().skip_binder().has_infer_types() { if !self.evaluate_nested_obligations( ty, v.into_iter(), 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 65385851d054f..f89349505bec5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1804,11 +1804,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { } ty::PredicateKind::Projection(data) => { let self_ty = data.projection_ty.self_ty(); - let ty = data.term.ty(); + let term = data.term; if predicate.references_error() || self.is_tainted_by_errors() { return; } - if self_ty.needs_infer() && ty.needs_infer() { + if self_ty.needs_infer() && term.needs_infer() { // We do this for the `foo.collect()?` case to produce a suggestion. let mut err = self.emit_inference_failure_err( body_id, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 2bbdb72a4fb8a..f49f53351aac8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1802,7 +1802,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>( Ok(InferOk { value: _, obligations }) => { nested_obligations.extend(obligations); assoc_ty_own_obligations(selcx, obligation, &mut nested_obligations); - // FIXME(...): Handle consts here as well? Maybe this progress type should just take + // FIXME(associated_const_equality): Handle consts here as well? Maybe this progress type should just take // a term instead. Progress { ty: cache_entry.term.ty().unwrap(), obligations: nested_obligations } } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index a1f1adb80581d..7c53e49e280d6 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1403,9 +1403,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // `trait_object_dummy_self`, so check for that. let references_self = match pred.skip_binder().term { ty::Term::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), - ty::Term::Const(c) => { - c.ty.walk().any(|arg| arg == dummy_self.into()) - } + ty::Term::Const(c) => c.ty.walk().any(|arg| arg == dummy_self.into()), }; // If the projection output contains `Self`, force the user to diff --git a/src/test/ui/associated-consts/assoc-const.rs b/src/test/ui/associated-consts/assoc-const.rs index 9e6bfa346ec0d..cd4b42f9f84c8 100644 --- a/src/test/ui/associated-consts/assoc-const.rs +++ b/src/test/ui/associated-consts/assoc-const.rs @@ -1,3 +1,5 @@ +#![feature(associated_const_equality)] + pub trait Foo { const N: usize; } @@ -13,9 +15,7 @@ const TEST:usize = 3; fn foo>() {} //~^ ERROR associated const equality is incomplete -//~| ERROR associated const equality is incomplete fn bar>() {} //~^ ERROR associated const equality is incomplete -//~| ERROR associated const equality is incomplete fn main() {} diff --git a/src/test/ui/associated-consts/assoc-const.stderr b/src/test/ui/associated-consts/assoc-const.stderr index 07da190bc8f90..ccaa6fa8ee884 100644 --- a/src/test/ui/associated-consts/assoc-const.stderr +++ b/src/test/ui/associated-consts/assoc-const.stderr @@ -1,33 +1,14 @@ -error[E0658]: associated const equality is incomplete - --> $DIR/assoc-const.rs:14:15 - | -LL | fn foo>() {} - | ^^^ - | - = note: see issue #92827 for more information - = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable - -error[E0658]: associated const equality is incomplete - --> $DIR/assoc-const.rs:17:15 - | -LL | fn bar>() {} - | ^^^^^^^^ - | - = note: see issue #92827 for more information - = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable - error: associated const equality is incomplete - --> $DIR/assoc-const.rs:14:15 + --> $DIR/assoc-const.rs:16:15 | LL | fn foo>() {} | ^^^ cannot yet relate associated const error: associated const equality is incomplete - --> $DIR/assoc-const.rs:17:15 + --> $DIR/assoc-const.rs:18:15 | LL | fn bar>() {} | ^^^^^^^^ cannot yet relate associated const -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`.