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/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 079b9e43373fa..d0732b35b6e9e 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,38 @@ 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`. - Equality { ty: P }, +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`, `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 564a8a8c8729e..a81a227629539 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,11 @@ 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 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); } @@ -555,7 +554,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..73e9297549cd4 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,17 @@ 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 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 7eb08b8754a29..47b610670555c 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,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; let kind = match constraint.kind { - AssocTyConstraintKind::Equality { ref ty } => { - hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) } + 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 } } - AssocTyConstraintKind::Bound { ref bounds } => { + 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. @@ -1078,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_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 45920bb27d5b6..eb7c75cac0520 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -138,10 +138,10 @@ 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::Bound { .. } => { if self.is_assoc_ty_bound_banned { self.err_handler().span_err( constraint.span, @@ -150,7 +150,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 +1277,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,12 +1586,12 @@ 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 { - ty: predicate.rhs_ty.clone(), + kind: AssocConstraintKind::Equality { + term: predicate.rhs_ty.clone().into(), }, 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..89671788255a9 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) { @@ -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_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..17941058ed6f0 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}; @@ -952,18 +952,19 @@ 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 { term } => { self.word_space("="); - self.print_type(ty); - } - ast::AssocTyConstraintKind::Bound { bounds } => { - self.print_type_bounds(":", &*bounds); + 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_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_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_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 369b5e6da2d28..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,19 +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`, `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 6347a64fa8502..cfdcd1618ba42 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -801,12 +801,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::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 7675778ff881b..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,9 +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); + 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..e98b9c3b03c5a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1780,7 +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. - return Some(projection_predicate.ty); + return projection_predicate.term.ty(); } } } 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..4851e637d3a62 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -584,8 +584,7 @@ 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. + if projection.term.references_error() { return tcx.ty_error(); } } 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_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index cb51555f5cadf..3921187baa55e 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)] @@ -738,9 +738,14 @@ 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 } => { - involves_impl_trait(ty) + ast::AssocConstraintKind::Bound { .. } => true, + 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/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index a29a7d241e3f3..d68c5514821a9 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 b6e673983fd4e..f06a1b09cd82a 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) => self.add_const(c), + } } ty::PredicateKind::WellFormed(arg) => { self.add_substs(slice::from_ref(&arg)); @@ -317,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 d6e89e52b95ed..4bc3e23f4a588 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,6 +795,31 @@ pub struct CoercePredicate<'tcx> { } pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, 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) -> Option> { + if let Term::Ty(ty) = self { Some(ty) } else { None } + } +} + /// This kind of predicate has no *direct* correspondent in the /// syntax, but it roughly corresponds to the syntactic forms: /// @@ -811,7 +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>, + pub term: Term<'tcx>, } pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; @@ -836,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| predicate.ty) + 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 94cd650e39e6f..bbdaf248a9e72 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,23 +904,28 @@ pub trait PrettyPrinter<'tcx>: first = false; } - for (assoc_item_def_id, ty) in assoc_items { + for (assoc_item_def_id, term) in assoc_items { 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() { - 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; } @@ -943,8 +950,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(); @@ -1019,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; } } @@ -2442,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> { @@ -2499,7 +2513,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> { @@ -2709,5 +2730,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 9e381cabdfe84..bb040acd2703d 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; @@ -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 }) } } } @@ -833,6 +833,20 @@ 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, @@ -841,7 +855,7 @@ impl<'tcx> Relate<'tcx> for 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)?, + term: relation.relate(a.term, b.term)?.into(), }) } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a27169d59e13f..1c5bc7860db2d 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 }) } } @@ -413,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 92fb7612688c0..20db25f7899dd 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; @@ -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), }, - ty: self.ty, + term: self.term, } } @@ -1584,7 +1584,7 @@ impl<'tcx> ExistentialProjection<'tcx> { 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, + 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 7f8fadb33bd8a..4e60b7593c651 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,25 @@ 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 term = match arg { + Some(GenericArg::Type(ty)) => ty.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") .help("if you meant to specify a trait object, write `dyn Trait + 'lifetime`") .emit(); + self.mk_ty(span, ast::TyKind::Err).into() } None => { let after_eq = eq.shrink_to_hi(); @@ -542,8 +542,8 @@ impl<'a> Parser<'a> { }; return Err(err); } - } - Ok(self.mk_ty(span, ast::TyKind::Err)) + }; + Ok(AssocConstraintKind::Equality { term }) } /// 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 5cc958ef54971..6cf1aa480d298 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -332,9 +332,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_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 7bee2ebf2f977..2c96899197351 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -127,8 +127,8 @@ where constness: _, polarity: _, }) => self.visit_trait(trait_ref), - ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => { - ty.visit_with(self)?; + ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { + term.visit_with(self)?; self.visit_projection_ty(projection_ty) } ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => { @@ -1185,10 +1185,10 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { } for (poly_predicate, _) in bounds.projection_bounds { - if self.visit(poly_predicate.skip_binder().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 = self.visit(pred.term); + if poly_pred_term.is_break() + || self.visit_projection_ty(pred.projection_ty).is_break() { return; } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 21f4312de3516..075a9764d4c7f 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 05d2a373dc639..f2ed5ae26a3c2 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,7 @@ 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().has_infer_types() { if !self.evaluate_nested_obligations( ty, v.into_iter(), @@ -774,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.ty().skip_binder().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 d1958f8552192..0760f62685127 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,7 @@ 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, ); let is_normalized_ty_expected = !matches!( @@ -1314,16 +1314,17 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::ObjectCastObligation(_) | ObligationCauseCode::OpaqueType ); - + // 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, normalized_ty, - data.ty, + data_ty, ) { values = Some(infer::ValuePairs::Types(ExpectedFound::new( is_normalized_ty_expected, normalized_ty, - data.ty, + data_ty, ))); err_buf = error; @@ -1803,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.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/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 577b96f3a400b..f49f53351aac8 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.ty) - { + // 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: () }) => { obligations.extend(inferred_obligations); Ok(Ok(Some(obligations))) @@ -1615,7 +1614,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 +1640,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 +1673,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 +1746,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 +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.ty, obligations: nested_obligations } + // 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 } } 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..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.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 f6e98f427108f..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.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.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 36c536c0ba3b2..67d0ba39667d3 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -226,13 +226,26 @@ 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.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)); @@ -651,7 +664,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders chalk_ir::Binders::new( @@ -787,7 +801,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().unwrap().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 2ada1c0ddf4fa..7c53e49e280d6 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -123,7 +123,7 @@ struct ConvertedBinding<'a, 'tcx> { #[derive(Debug)] enum ConvertedBindingKind<'a, 'tcx> { - Equality(Ty<'tcx>), + Equality(ty::Term<'tcx>), Constraint(&'a [hir::GenericBound<'a>]), } @@ -601,10 +601,17 @@ 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::Constraint { bounds } => { + hir::TypeBindingKind::Equality { ref term } => match term { + hir::Term::Ty(ref 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::Equality(c.into()) + } + }, + hir::TypeBindingKind::Constraint { ref bounds } => { ConvertedBindingKind::Constraint(bounds) } }; @@ -867,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>( @@ -1118,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 @@ -1215,18 +1242,15 @@ 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: // // `::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: term, }), binding.span, )); @@ -1377,8 +1401,10 @@ 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().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. @@ -1601,7 +1627,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/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 8bc3a48e5b506..6a28bb16a20ac 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -48,14 +48,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 +69,22 @@ 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)); + + 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..e88099afa0353 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().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.ty); + let output_ty = self.resolve_vars_if_possible(predicate.term); debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty); - Some(output_ty) + // This is a projection on a Fn trait so will always be a type. + Some(output_ty.ty().unwrap()) } /// Converts the types that the user supplied, in case that doing diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 3984d8b74257f..94648d5702c89 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1353,7 +1353,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..56f4d5afe400d 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -789,10 +789,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_def_id: projection_ty.item_def_id, }; - let ty = pred.skip_binder().ty; + let term = pred.skip_binder().term; - let obligation = format!("{} = {}", projection_ty, ty); - let quiet = format!("{} = {}", quiet_projection_ty, ty); + 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 059d4a7f3a4bc..34caabe44d6d9 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -716,7 +716,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, + )); } 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 314174e0f8501..403aa16689fcf 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -659,7 +659,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()) @@ -2527,7 +2531,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..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 bounds = bounds.predicates(tcx, item_ty); - - debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds); - - tcx.arena.alloc_slice(&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..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.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/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/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 a5bc70a74ae92..e759baa045892 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,10 +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, ty } = self; - WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) } + let ty::ProjectionPredicate { projection_ty, term } = self; + WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: term.clean(cx) } } } @@ -613,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,11 +646,16 @@ fn clean_ty_generics( ); let proj = projection - .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty)); + .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; @@ -647,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 { @@ -1495,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().term.clean(cx).into(), + }, }); } @@ -1566,7 +1595,7 @@ impl<'tcx> Clean for Ty<'tcx> { .ident .name, kind: TypeBindingKind::Equality { - ty: proj.ty.clean(cx), + term: proj.term.clean(cx), }, }) } else { @@ -2114,10 +2143,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::Equality { ref term } => { + TypeBindingKind::Equality { term: term.clean(cx) } } - hir::TypeBindingKind::Constraint { bounds } => TypeBindingKind::Constraint { + 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..fac1a0817e033 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,9 @@ 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 = ret_ty.ty().expect("Unexpected constant return term"); + FnRetTy::Return(ty.clone()) } _ => panic!("unexpected desugaring of async function"), }, @@ -2121,6 +2123,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 +2303,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/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/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/associated-consts/assoc-const.rs b/src/test/ui/associated-consts/assoc-const.rs new file mode 100644 index 0000000000000..cd4b42f9f84c8 --- /dev/null +++ b/src/test/ui/associated-consts/assoc-const.rs @@ -0,0 +1,21 @@ +#![feature(associated_const_equality)] + +pub trait Foo { + const N: usize; +} + +pub struct Bar; + +impl Foo for Bar { + const N: usize = 3; +} + +const TEST:usize = 3; + + +fn foo>() {} +//~^ ERROR associated const equality is incomplete +fn bar>() {} +//~^ 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..ccaa6fa8ee884 --- /dev/null +++ b/src/test/ui/associated-consts/assoc-const.stderr @@ -0,0 +1,14 @@ +error: associated const equality is incomplete + --> $DIR/assoc-const.rs:16:15 + | +LL | fn foo>() {} + | ^^^ cannot yet relate associated const + +error: associated const equality is incomplete + --> $DIR/assoc-const.rs:18:15 + | +LL | fn bar>() {} + | ^^^^^^^^ cannot yet relate associated const + +error: aborting due to 2 previous errors + 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..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 @@ -7,8 +7,9 @@ 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 +//~| 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 bbca92ad63a91..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,11 +1,27 @@ -error: cannot constrain an associated constant to a value +error[E0658]: associated const equality is incomplete --> $DIR/issue-89013-no-kw.rs:9:10 | LL | impl Foo for Bar { - | -^^^- - | | | - | | ...cannot be constrained to this value - | this associated constant... + | ^^^^^ + | + = 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 + | +LL | impl Foo for Bar { + | ^^^ 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 @@ -13,6 +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 -For more information about this error, try `rustc --explain 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 ca1158a2f6d16..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 @@ -8,8 +8,9 @@ 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 +//~| 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 85379d3f06e4b..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,14 +10,30 @@ LL - impl Foo for Bar { LL + impl Foo for Bar { | -error: cannot constrain an associated constant to a value +error[E0658]: associated const equality is incomplete --> $DIR/issue-89013.rs:9:10 | LL | impl Foo for Bar { - | -^^^^^^^^^- - | | | - | | ...cannot be constrained to this value - | this associated constant... + | ^^^^^^^^^^^ + | + = 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 + | +LL | impl Foo for Bar { + | ^^^ 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 @@ -25,6 +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 -For more information about this error, try `rustc --explain 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 06be3cdcc1a95..1453e6cb5cd7c 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 @@ #[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::(); + //~^ 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 index c6733b33faa58..2d36ce4e98632 100644 --- a/src/test/ui/parser/recover-assoc-const-constraint.stderr +++ b/src/test/ui/parser/recover-assoc-const-constraint.stderr @@ -1,20 +1,21 @@ -error: cannot constrain an associated constant to a value +error[E0658]: associated const equality is incomplete --> $DIR/recover-assoc-const-constraint.rs:3:11 | LL | bar::(); - | ----^^^-- - | | | - | | ...cannot be constrained to this value - | this associated constant... + | ^^^^^^^^^ + | + = note: see issue #92827 for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable -error: cannot constrain an associated constant to a value - --> $DIR/recover-assoc-const-constraint.rs:4:11 +error[E0658]: associated const equality is incomplete + --> $DIR/recover-assoc-const-constraint.rs:5:11 | LL | bar::(); - | ----^^^------ - | | | - | | ...cannot be constrained to this value - | this associated constant... + | ^^^^^^^^^^^^^ + | + = 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/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/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 7357219f7b47c..a9a06c3db7554 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -2178,12 +2178,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) => continue, + }; // 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(assoc_ty, self_adt) { return; } - } else if contains_ty(projection_predicate.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 e5b6d296b2d25..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.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 fe35ff33d35a4..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.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.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())); } } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 3d3180521ab7a..604c95d2bc81f 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -645,11 +645,19 @@ pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool { } } -pub fn eq_assoc_constraint(l: &AssocTyConstraint, r: &AssocTyConstraint) -> bool { - use AssocTyConstraintKind::*; +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), _ => false, } 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 diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 88f5dc4324510..5de30129266a3 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}; @@ -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}; let mut result = String::with_capacity(128); result.push_str(rewrite_ident(context, self.ident)); @@ -206,11 +206,14 @@ 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 { 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), } } }