From 316742edb73a81edc231b1c8dc086fae1f3142d9 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sun, 22 Jan 2023 15:46:53 +0100 Subject: [PATCH 01/14] =?UTF-8?q?io:=20soften=20=E2=80=98at=20most=20one?= =?UTF-8?q?=20write=20attempt=E2=80=99=20requirement=20in=20io::Write::wri?= =?UTF-8?q?te?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At the moment, documentation of std::io::Write::write indicates that call to it ‘represents at most one attempt to write to any wrapped object’. It seems that such wording was put there to contrast it with pre-1.0 interface which attempted to write all the data (it has since been changed in [RFC 517]). However, the requirement puts unnecessary constraints and may complicate adaptors which perform non-trivial transformations on the data. For example, they may maintain an internal buffer which needs to be written out before the write method accepts more data. It might be natural to code the method such that it flushes the buffer and then grabs another chunk of user data. With the current wording in the documentation, the adaptor would be forced to return Ok(0). This commit softens the wording such that implementations can choose code structure which makes most sense for their particular use case. While at it, elaborate on the meaning of `Ok(0)` return pointing out that the write_all methods interprets it as an error. [RFC 517]: https://rust-lang.github.io/rfcs/0517-io-os-reform.html --- library/std/src/io/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index de528e85368cb..aa34d4be19242 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1385,17 +1385,18 @@ pub trait Write { /// /// This function will attempt to write the entire contents of `buf`, but /// the entire write might not succeed, or the write may also generate an - /// error. A call to `write` represents *at most one* attempt to write to + /// error. Typically, a call to `write` represents one attempt to write to /// any wrapped object. /// /// Calls to `write` are not guaranteed to block waiting for data to be /// written, and a write which would otherwise block can be indicated through /// an [`Err`] variant. /// - /// If the return value is [`Ok(n)`] then it must be guaranteed that - /// `n <= buf.len()`. A return value of `0` typically means that the - /// underlying object is no longer able to accept bytes and will likely not - /// be able to in the future as well, or that the buffer provided is empty. + /// If the return value is [`Ok(n)`] then it must be guaranteed that `n <= + /// buf.len()`. Unless `input` is empty, this function shouldn’t return `0` + /// since caller may interpret that as an error (the default implementation + /// of [`Write::write_all`] does exactly that). To indicate lack of space + /// function should return [`ErrorKind::StorageFull`] error instead. /// /// # Errors /// From 8654669ed4569216fde2c16edb49d05cd373f038 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Fri, 3 Feb 2023 18:38:51 +0100 Subject: [PATCH 02/14] Update library/std/src/io/mod.rs --- library/std/src/io/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index aa34d4be19242..d4f8c3123b287 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1392,10 +1392,10 @@ pub trait Write { /// written, and a write which would otherwise block can be indicated through /// an [`Err`] variant. /// - /// If the return value is [`Ok(n)`] then it must be guaranteed that `n <= - /// buf.len()`. Unless `input` is empty, this function shouldn’t return `0` - /// since caller may interpret that as an error (the default implementation - /// of [`Write::write_all`] does exactly that). To indicate lack of space + /// If this method consumed `n > 0` bytes of `buf` it must return [`Ok(n)`]. + /// If the return value is `Ok(n)` it must hold than `n <= buf.len()`. + /// Unless `input` is empty, this function shouldn’t return `Ok(0)` since + /// caller may interpret that as an error. To indicate lack of space /// function should return [`ErrorKind::StorageFull`] error instead. /// /// # Errors From 5451dfe6c0c841c0a01d812eebb62e60576dbf89 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Wed, 1 Mar 2023 00:48:22 +0100 Subject: [PATCH 03/14] Update library/std/src/io/mod.rs Co-authored-by: Andrew Gallant --- library/std/src/io/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index d4f8c3123b287..8e8fa147c0d57 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1394,9 +1394,9 @@ pub trait Write { /// /// If this method consumed `n > 0` bytes of `buf` it must return [`Ok(n)`]. /// If the return value is `Ok(n)` it must hold than `n <= buf.len()`. - /// Unless `input` is empty, this function shouldn’t return `Ok(0)` since - /// caller may interpret that as an error. To indicate lack of space - /// function should return [`ErrorKind::StorageFull`] error instead. + /// Unless `buf` is empty, this function shouldn’t return `Ok(0)` since the + /// caller may interpret that as an error. To indicate lack of space, + /// implementors should return [`ErrorKind::StorageFull`] error instead. /// /// # Errors /// From 7d57cd524a33179be58287737b7fd603a9d4a759 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Fri, 3 Mar 2023 03:16:56 +0100 Subject: [PATCH 04/14] Update library/std/src/io/mod.rs Co-authored-by: Jacob Lifshay --- library/std/src/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 8e8fa147c0d57..b2fcb966032a1 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1393,7 +1393,7 @@ pub trait Write { /// an [`Err`] variant. /// /// If this method consumed `n > 0` bytes of `buf` it must return [`Ok(n)`]. - /// If the return value is `Ok(n)` it must hold than `n <= buf.len()`. + /// If the return value is `Ok(n)` then `n` must satisfy `n <= buf.len()`. /// Unless `buf` is empty, this function shouldn’t return `Ok(0)` since the /// caller may interpret that as an error. To indicate lack of space, /// implementors should return [`ErrorKind::StorageFull`] error instead. From 3a9a8d4abf440eab3465b18ed65a1bade78666d5 Mon Sep 17 00:00:00 2001 From: ltdk Date: Tue, 13 Jun 2023 22:30:38 -0400 Subject: [PATCH 05/14] Alter `Display` for `Ipv6Addr` for IPv4-compatible addresses --- library/core/src/net/ip_addr.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 954d88d548e82..c51913fa8ab8d 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1770,14 +1770,8 @@ impl fmt::Display for Ipv6Addr { f.write_str("::") } else if self.is_loopback() { f.write_str("::1") - } else if let Some(ipv4) = self.to_ipv4() { - match segments[5] { - // IPv4 Compatible address - 0 => write!(f, "::{}", ipv4), - // IPv4 Mapped address - 0xffff => write!(f, "::ffff:{}", ipv4), - _ => unreachable!(), - } + } else if let Some(ipv4) = self.to_ipv4_mapped() { + write!(f, "::ffff:{}", ipv4) } else { #[derive(Copy, Clone, Default)] struct Span { From 2f2c3f55a967dc8e48f3a9755980757f06233bef Mon Sep 17 00:00:00 2001 From: ltdk Date: Wed, 14 Jun 2023 14:25:25 -0400 Subject: [PATCH 06/14] Fix `Ipv6Addr: Display` tests --- library/core/tests/net/ip_addr.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs index 5a6ac08c08815..7530fc084874d 100644 --- a/library/core/tests/net/ip_addr.rs +++ b/library/core/tests/net/ip_addr.rs @@ -139,7 +139,7 @@ fn ipv6_addr_to_string() { // ipv4-compatible address let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280); - assert_eq!(a1.to_string(), "::192.0.2.128"); + assert_eq!(a1.to_string(), "::c000:280"); // v6 address with no zero segments assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f"); @@ -316,7 +316,7 @@ fn ip_properties() { check!("::", unspec); check!("::1", loopback); - check!("::0.0.0.2", global); + check!("::2", global); check!("1::", global); check!("fc00::"); check!("fdff:ffff::"); @@ -607,7 +607,7 @@ fn ipv6_properties() { check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback); - check!("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], global | unicast_global); + check!("::2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], global | unicast_global); check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global); From 2dce58d0f624b20633f4e6d22335b4681ec48089 Mon Sep 17 00:00:00 2001 From: ltdk Date: Wed, 14 Jun 2023 14:59:11 -0400 Subject: [PATCH 07/14] Fix `SocketAddrV6: Display` tests --- library/core/tests/net/socket_addr.rs | 2 +- library/std/src/net/socket_addr/tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/tests/net/socket_addr.rs b/library/core/tests/net/socket_addr.rs index 68c7cd94d322f..35a69cead4826 100644 --- a/library/core/tests/net/socket_addr.rs +++ b/library/core/tests/net/socket_addr.rs @@ -34,7 +34,7 @@ fn ipv6_socket_addr_to_string() { // IPv4-compatible address. assert_eq!( SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280), 8080, 0, 0).to_string(), - "[::192.0.2.128]:8080" + "[::c000:280]:8080" ); // IPv6 address with no zero segments. diff --git a/library/std/src/net/socket_addr/tests.rs b/library/std/src/net/socket_addr/tests.rs index dfc6dabbed1ed..6a065cfba2105 100644 --- a/library/std/src/net/socket_addr/tests.rs +++ b/library/std/src/net/socket_addr/tests.rs @@ -85,7 +85,7 @@ fn ipv6_socket_addr_to_string() { // IPv4-compatible address. assert_eq!( SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280), 8080, 0, 0).to_string(), - "[::192.0.2.128]:8080" + "[::c000:280]:8080" ); // IPv6 address with no zero segments. From 886085a4d567bc882038ce5ec8498c45b436412d Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 15 Jun 2023 15:56:00 -0700 Subject: [PATCH 08/14] std: only depend on dlmalloc for wasm*-unknown It was already filtered out for emscripten, but wasi doesn't need dlmalloc either since it reuses `unix/alloc.rs`. --- library/std/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index e6b051838861a..af74efa6bf84d 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -38,7 +38,7 @@ features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } rand_xorshift = "0.3.0" -[target.'cfg(any(all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] +[target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] From 7a2490eba3f161c81ad243c7d957b337dd70a2af Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 13 Jun 2023 18:25:15 -0400 Subject: [PATCH 09/14] Launch a non-unwinding panic for misaligned pointer deref --- compiler/rustc_mir_transform/src/check_alignment.rs | 10 ++++------ library/core/src/panicking.rs | 5 +++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index ef64f70fdf349..2787092566f26 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -9,7 +9,6 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::{Ty, TyCtxt, TypeAndMut}; use rustc_session::Session; -use rustc_target::spec::PanicStrategy; pub struct CheckAlignment; @@ -237,11 +236,10 @@ fn insert_alignment_check<'tcx>( required: Operand::Copy(alignment), found: Operand::Copy(addr), }), - unwind: if tcx.sess.panic_strategy() == PanicStrategy::Unwind { - UnwindAction::Terminate - } else { - UnwindAction::Unreachable - }, + // The panic symbol that this calls is #[rustc_nounwind]. We never want to insert an + // unwind into unsafe code, because unwinding could make a failing UB check turn into + // much worse UB when we start unwinding. + unwind: UnwindAction::Unreachable, }, }); } diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 81be3fb22eec4..f0fcdab00ada1 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -166,14 +166,15 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[track_caller] #[lang = "panic_misaligned_pointer_dereference"] // needed by codegen for panic on misaligned pointer deref +#[rustc_nounwind] // `CheckAlignment` MIR pass requires this function to never unwind fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() } - panic!( + panic_nounwind_fmt(format_args!( "misaligned pointer dereference: address must be a multiple of {required:#x} but is {found:#x}" - ) + )) } /// Panic because we cannot unwind out of a function. From 3078de76368a78ed0b481295393327b7296dcc95 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Fri, 16 Jun 2023 13:39:55 -0700 Subject: [PATCH 10/14] add dry_run check --- src/bootstrap/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 13a10b0d3a506..01d0dbafd1ef6 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1766,7 +1766,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the // // Note that if we encounter `PATH` we make sure to append to our own `PATH` // rather than stomp over it. - if target.contains("msvc") { + if !builder.config.dry_run() && target.contains("msvc") { for &(ref k, ref v) in builder.cc.borrow()[&target].env() { if k != "PATH" { cmd.env(k, v); From f874345784b0e1ac3cb7d03eb73cd23b2fc4dd85 Mon Sep 17 00:00:00 2001 From: dswij Date: Sat, 17 Jun 2023 15:59:56 +0800 Subject: [PATCH 11/14] `Bound::predicates` to return `Clause` --- .../rustc_hir_analysis/src/astconv/mod.rs | 6 ++-- compiler/rustc_hir_analysis/src/bounds.rs | 29 ++++++++++++------- .../src/collect/item_bounds.rs | 12 ++++++-- .../src/collect/predicates_of.rs | 21 ++++++++++---- compiler/rustc_middle/src/ty/mod.rs | 7 +++++ compiler/rustc_privacy/src/lib.rs | 6 ++-- 6 files changed, 57 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 221c7ce4f6ff8..7827890c51ec9 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -31,9 +31,10 @@ use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef}; +use rustc_middle::ty::DynKind; use rustc_middle::ty::GenericParamDefKind; +use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; -use rustc_middle::ty::{DynKind, ToPredicate}; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; @@ -1509,7 +1510,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut trait_bounds = vec![]; let mut projection_bounds = vec![]; - for (pred, span) in bounds.predicates() { + for (clause, span) in bounds.predicates() { + let pred: ty::Predicate<'tcx> = clause.to_predicate(tcx); let bound_pred = pred.kind(); match bound_pred.skip_binder() { ty::PredicateKind::Clause(clause) => match clause { diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 686066abbf079..8a318e984d7ae 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -2,6 +2,7 @@ //! `ty` form from the HIR. use rustc_hir::LangItem; +use rustc_middle::ty::Binder; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; @@ -23,52 +24,58 @@ use rustc_span::Span; /// include the self type (e.g., `trait_bounds`) but in others we do not #[derive(Default, PartialEq, Eq, Clone, Debug)] pub struct Bounds<'tcx> { - pub predicates: Vec<(ty::Predicate<'tcx>, Span)>, + pub predicates: Vec<(Binder<'tcx, ty::Clause<'tcx>>, Span)>, } impl<'tcx> Bounds<'tcx> { pub fn push_region_bound( &mut self, - tcx: TyCtxt<'tcx>, + _tcx: TyCtxt<'tcx>, region: ty::PolyTypeOutlivesPredicate<'tcx>, span: Span, ) { - self.predicates.push((region.to_predicate(tcx), span)); + self.predicates.push((region.map_bound(|p| ty::Clause::TypeOutlives(p)), span)); } pub fn push_trait_bound( &mut self, - tcx: TyCtxt<'tcx>, + _tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, span: Span, constness: ty::BoundConstness, polarity: ty::ImplPolarity, ) { self.predicates.push(( - trait_ref - .map_bound(|trait_ref| ty::TraitPredicate { trait_ref, constness, polarity }) - .to_predicate(tcx), + trait_ref.map_bound(|trait_ref| { + ty::Clause::Trait(ty::TraitPredicate { trait_ref, constness, polarity }) + }), span, )); } pub fn push_projection_bound( &mut self, - tcx: TyCtxt<'tcx>, + _tcx: TyCtxt<'tcx>, projection: ty::PolyProjectionPredicate<'tcx>, span: Span, ) { - self.predicates.push((projection.to_predicate(tcx), span)); + self.predicates.push((projection.map_bound(|proj| ty::Clause::Projection(proj)), span)); } pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) { let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span)); let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]); // Preferable to put this obligation first, since we report better errors for sized ambiguity. - self.predicates.insert(0, (trait_ref.without_const().to_predicate(tcx), span)); + self.predicates.insert( + 0, + ( + ty::Binder::dummy(ty::Clause::Trait(trait_ref.without_const().to_predicate(tcx))), + span, + ), + ); } - pub fn predicates(&self) -> impl Iterator, Span)> + '_ { + pub fn predicates(&self) -> impl Iterator>, Span)> + '_ { self.predicates.iter().cloned() } } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 90e8e523ea3e8..0479efceaad90 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -3,6 +3,7 @@ use crate::astconv::{AstConv, OnlySelfBounds}; use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::Span; @@ -44,7 +45,12 @@ fn associated_type_bounds<'tcx>( } }); - let all_bounds = tcx.arena.alloc_from_iter(bounds.predicates().chain(bounds_from_parent)); + let all_bounds = tcx.arena.alloc_from_iter( + bounds + .predicates() + .map(|(clause, span)| (clause.to_predicate(tcx), span)) + .chain(bounds_from_parent), + ); debug!( "associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id.to_def_id()), @@ -72,7 +78,9 @@ fn opaque_type_bounds<'tcx>( icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); debug!(?bounds); - tcx.arena.alloc_from_iter(bounds.predicates()) + tcx.arena.alloc_from_iter( + bounds.predicates().map(|(clause, span)| (clause.to_predicate(tcx), span)), + ) }) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index dcb5790292879..fcbc5d5fcc1ff 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -126,7 +126,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen predicates.extend( icx.astconv() .compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false)) - .predicates(), + .predicates() + .map(|(clause, span)| (clause.to_predicate(tcx), span)), ); } @@ -175,7 +176,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen param.span, ); trace!(?bounds); - predicates.extend(bounds.predicates()); + predicates.extend( + bounds.predicates().map(|(clause, span)| (clause.to_predicate(tcx), span)), + ); trace!(?predicates); } GenericParamKind::Const { .. } => { @@ -234,7 +237,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen bound_vars, OnlySelfBounds(false), ); - predicates.extend(bounds.predicates()); + predicates.extend( + bounds.predicates().map(|(clause, span)| (clause.to_predicate(tcx), span)), + ); } hir::WherePredicate::RegionPredicate(region_pred) => { @@ -658,8 +663,12 @@ pub(super) fn implied_predicates_with_filter( }; // Combine the two lists to form the complete set of superbounds: - let implied_bounds = - &*tcx.arena.alloc_from_iter(superbounds.predicates().chain(where_bounds_that_match)); + let implied_bounds = &*tcx.arena.alloc_from_iter( + superbounds + .predicates() + .map(|(clause, span)| (clause.to_predicate(tcx), span)) + .chain(where_bounds_that_match), + ); debug!(?implied_bounds); // Now require that immediate supertraits are converted, which will, in @@ -816,7 +825,7 @@ impl<'tcx> ItemCtxt<'tcx> { ); } - bounds.predicates().collect() + bounds.predicates().map(|(clause, span)| (clause.to_predicate(self.tcx), span)).collect() } #[instrument(level = "trace", skip(self))] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ff5d99794f1e2..32aeecea33ec0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1214,6 +1214,13 @@ impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { } } +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, Clause<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))) + } +} + impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 5ef11acadcedd..c2bbca737e55d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1270,13 +1270,13 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { ); for (pred, _) in bounds.predicates() { - match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => { + match pred.skip_binder() { + ty::Clause::Trait(trait_predicate) => { if self.visit_trait(trait_predicate.trait_ref).is_break() { return; } } - ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) => { + ty::Clause::Projection(proj_predicate) => { let term = self.visit(proj_predicate.term); if term.is_break() || self.visit_projection_ty(proj_predicate.projection_ty).is_break() From 52d3fc93f2194b0646e5447f29e6702b7c71ddae Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Jun 2023 16:59:01 +0000 Subject: [PATCH 12/14] Move WF goal to clause --- .../src/region_infer/opaque_types.rs | 3 ++- compiler/rustc_borrowck/src/type_check/mod.rs | 10 ++++++---- compiler/rustc_hir_analysis/src/astconv/mod.rs | 7 ++++--- compiler/rustc_hir_analysis/src/check/check.rs | 3 ++- .../src/check/compare_impl_item.rs | 4 +++- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 5 +++-- .../src/collect/predicates_of.rs | 2 +- compiler/rustc_hir_analysis/src/hir_wf_check.rs | 2 +- .../src/impl_wf_check/min_specialization.rs | 2 +- .../rustc_hir_analysis/src/outlives/explicit.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 4 ++-- compiler/rustc_hir_typeck/src/method/mod.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- compiler/rustc_hir_typeck/src/method/suggest.rs | 5 ++++- compiler/rustc_infer/src/infer/combine.rs | 2 +- compiler/rustc_infer/src/infer/outlives/mod.rs | 2 +- compiler/rustc_infer/src/traits/util.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_middle/src/ty/flags.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 16 ++++++++-------- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/structural_impls.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 2 +- .../rustc_trait_selection/src/solve/eval_ctxt.rs | 2 +- .../rustc_trait_selection/src/solve/fulfill.rs | 1 - .../src/traits/auto_trait.rs | 2 +- .../src/traits/error_reporting/mod.rs | 4 ++-- .../rustc_trait_selection/src/traits/fulfill.rs | 4 ++-- .../src/traits/object_safety.rs | 4 ++-- .../traits/query/type_op/ascribe_user_type.rs | 9 ++++++--- .../query/type_op/implied_outlives_bounds.rs | 2 +- .../src/traits/select/mod.rs | 2 +- compiler/rustc_trait_selection/src/traits/wf.rs | 16 ++++++++++------ compiler/rustc_traits/src/chalk/lowering.rs | 8 ++++---- .../src/normalize_erasing_regions.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- .../clippy_utils/src/qualify_min_const_fn.rs | 2 +- 37 files changed, 81 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index b5d5071dc0536..6ca702cfdfc3e 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -330,7 +330,8 @@ fn check_opaque_type_well_formed<'tcx>( // Require the hidden type to be well-formed with only the generics of the opaque type. // Defining use functions may have more bounds than the opaque type, which is ok, as long as the // hidden type is well formed even without those bounds. - let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())); + let predicate = + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(definition_ty.into()))); ocx.register_obligation(Obligation::misc(tcx, definition_span, def_id, param_env, predicate)); // Check that all obligations are satisfied by the implementation's diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6697e1aff7dd0..33f75437478b5 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1419,9 +1419,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // // See #91068 for an example. self.prove_predicates( - sig.inputs_and_output - .iter() - .map(|ty| ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()))), + sig.inputs_and_output.iter().map(|ty| { + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed( + ty.into(), + ))) + }), term_location.to_locations(), ConstraintCategory::Boring, ); @@ -1850,7 +1852,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let array_ty = rvalue.ty(body.local_decls(), tcx); self.prove_predicate( - ty::PredicateKind::WellFormed(array_ty.into()), + ty::PredicateKind::Clause(ty::Clause::WellFormed(array_ty.into())), Locations::Single(location), ConstraintCategory::Boring, ); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 221c7ce4f6ff8..3b55c52c34205 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1527,10 +1527,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::Clause::TypeOutlives(_) => { // Do nothing, we deal with regions separately } - ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) => bug!(), + ty::Clause::RegionOutlives(_) + | ty::Clause::ConstArgHasType(..) + | ty::Clause::WellFormed(_) => bug!(), }, - ty::PredicateKind::WellFormed(_) - | ty::PredicateKind::AliasRelate(..) + ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ClosureKind(_, _, _) | ty::PredicateKind::Subtype(_) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 17be5fe66cf62..c09734d6e6983 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -439,7 +439,8 @@ fn check_opaque_meets_bounds<'tcx>( // Additionally require the hidden type to be well-formed with only the generics of the opaque type. // Defining use functions may have more bounds than the opaque type, which is ok, as long as the // hidden type is well formed even without those bounds. - let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_ty.into())); + let predicate = + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(hidden_ty.into()))); ocx.register_obligation(Obligation::new(tcx, misc_cause, param_env, predicate)); // Check that all obligations are satisfied by the implementation's diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 4fbe68b8b6c54..838b212ef8782 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -321,7 +321,9 @@ fn compare_method_predicate_entailment<'tcx>( infcx.tcx, ObligationCause::dummy(), param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(unnormalized_impl_fty.into())), + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed( + unnormalized_impl_fty.into(), + ))), )); } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f93f395caed68..132335e74ef9d 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -81,7 +81,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { self.tcx(), cause, param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(arg))), )); } } @@ -1876,7 +1876,8 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { // We lower empty bounds like `Vec:` as // `WellFormed(Vec)`, which will later get checked by // regular WF checking - if let ty::PredicateKind::WellFormed(..) = pred.kind().skip_binder() { + if let ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) = pred.kind().skip_binder() + { continue; } // Match the existing behavior. diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index dcb5790292879..843896d85aa0c 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -219,7 +219,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } else { let span = bound_pred.bounded_ty.span; let predicate = ty::Binder::bind_with_vars( - ty::PredicateKind::WellFormed(ty.into()), + ty::PredicateKind::Clause(ty::Clause::WellFormed(ty.into())), bound_vars, ); predicates.insert((predicate.to_predicate(tcx), span)); diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index a653a65223138..f2618b3daf147 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -79,7 +79,7 @@ fn diagnostic_hir_wf_check<'tcx>( self.tcx, cause, self.param_env, - ty::PredicateKind::WellFormed(tcx_ty.into()), + ty::PredicateKind::Clause(ty::Clause::WellFormed(tcx_ty.into())), )); for error in ocx.select_all_or_error() { diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index e84da2519ae81..4517d24d154a9 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -542,7 +542,7 @@ fn trait_predicate_kind<'tcx>( | ty::PredicateKind::Clause(ty::Clause::Projection(_)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::WellFormed(_) + | ty::PredicateKind::Clause(ty::Clause::WellFormed(_)) | ty::PredicateKind::Subtype(_) | ty::PredicateKind::Coerce(_) | ty::PredicateKind::ObjectSafe(_) diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index 7ce48fe1c012f..ecdf8dca5c120 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -55,7 +55,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { ty::PredicateKind::Clause(ty::Clause::Trait(..)) | ty::PredicateKind::Clause(ty::Clause::Projection(..)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index fb56b7e74cb54..9b593ddccfdd9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -483,7 +483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, cause, self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(arg))), )); } @@ -668,7 +668,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::PredicateKind::Coerce(..) | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) - | ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ConstEvaluatable(..) diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 6f4d674ba103b..cca97d1051720 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -452,7 +452,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx, obligation.cause, self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())), + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(method_ty.into()))), )); let callee = MethodCallee { def_id, substs, sig: fn_sig }; diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index b7b11ff8942f9..e4c2f61da5626 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -838,7 +838,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::PredicateKind::Coerce(..) | ty::PredicateKind::Clause(ty::Clause::Projection(..)) | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) - | ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7a484e7ddc51e..66e771b794aad 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -696,7 +696,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Don't point out the span of `WellFormed` predicates. - if !matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) { + if !matches!( + p.kind().skip_binder(), + ty::PredicateKind::Clause(ty::Clause::Projection(..) | ty::Clause::Trait(..)) + ) { continue; }; diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index bb2bd2faec208..152c56572b691 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -417,7 +417,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { self.tcx(), self.trace.cause.clone(), self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(b_ty.into())), + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(b_ty.into()))), )); } diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 8a44d5031596f..3edf98cc869cf 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -29,7 +29,7 @@ pub fn explicit_outlives_bounds<'tcx>( | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::Subtype(..) - | ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 74a78f38024e0..66056de03b572 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -227,7 +227,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { debug!(?data, ?obligations, "super_predicates"); self.extend_deduped(obligations); } - ty::PredicateKind::WellFormed(..) => { + ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) => { // Currently, we do not elaborate WF predicates, // although we easily could. } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index f02f3668dc1fb..6262d875552b4 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1610,7 +1610,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { Clause(Clause::Projection(..)) | AliasRelate(..) | // Ignore bounds that a user can't type - WellFormed(..) | + Clause(Clause::WellFormed(..)) | ObjectSafe(..) | ClosureKind(..) | Subtype(..) | diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 9cce9d64d5d20..aa2af5bb2b085 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -270,7 +270,7 @@ impl FlagComputation { self.add_alias_ty(projection_ty); self.add_term(term); } - ty::PredicateKind::WellFormed(arg) => { + ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => { self.add_substs(slice::from_ref(&arg)); } ty::PredicateKind::ObjectSafe(_def_id) => {} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ff5d99794f1e2..155adda02a953 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -523,7 +523,7 @@ impl<'tcx> Predicate<'tcx> { ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { tcx.trait_is_coinductive(data.def_id()) } - ty::PredicateKind::WellFormed(_) => true, + ty::PredicateKind::Clause(ty::Clause::WellFormed(_)) => true, _ => false, } } @@ -536,7 +536,7 @@ impl<'tcx> Predicate<'tcx> { #[inline] pub fn allow_normalization(self) -> bool { match self.kind().skip_binder() { - PredicateKind::WellFormed(_) => false, + PredicateKind::Clause(Clause::WellFormed(_)) => false, PredicateKind::Clause(Clause::Trait(_)) | PredicateKind::Clause(Clause::RegionOutlives(_)) | PredicateKind::Clause(Clause::TypeOutlives(_)) @@ -584,6 +584,9 @@ pub enum Clause<'tcx> { /// Ensures that a const generic argument to a parameter `const N: u8` /// is of type `u8`. ConstArgHasType(Const<'tcx>, Ty<'tcx>), + + /// No syntax: `T` well-formed. + WellFormed(GenericArg<'tcx>), } impl<'tcx> Binder<'tcx, Clause<'tcx>> { @@ -610,9 +613,6 @@ pub enum PredicateKind<'tcx> { /// Prove a clause Clause(Clause<'tcx>), - /// No syntax: `T` well-formed. - WellFormed(GenericArg<'tcx>), - /// Trait must be object-safe. ObjectSafe(DefId), @@ -1324,7 +1324,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(Clause::RegionOutlives(..)) - | PredicateKind::WellFormed(..) + | PredicateKind::Clause(Clause::WellFormed(..)) | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) | PredicateKind::Clause(Clause::TypeOutlives(..)) @@ -1345,7 +1345,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(Clause::RegionOutlives(..)) - | PredicateKind::WellFormed(..) + | PredicateKind::Clause(Clause::WellFormed(..)) | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) | PredicateKind::Clause(Clause::TypeOutlives(..)) @@ -1367,7 +1367,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(Clause::RegionOutlives(..)) - | PredicateKind::WellFormed(..) + | PredicateKind::Clause(Clause::WellFormed(..)) | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) | PredicateKind::ConstEvaluatable(..) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f36b8ad8df6c7..4f8566c215c1a 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2877,7 +2877,7 @@ define_print_and_forward_display! { ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => { p!("the constant `", print(ct), "` has type `", print(ty), "`") }, - ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"), + ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => p!(print(arg), " well-formed"), ty::PredicateKind::ObjectSafe(trait_def_id) => { p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe") } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a965450d27d43..6db49c7300f41 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -179,6 +179,7 @@ impl<'tcx> fmt::Debug for ty::Clause<'tcx> { ty::Clause::RegionOutlives(ref pair) => pair.fmt(f), ty::Clause::TypeOutlives(ref pair) => pair.fmt(f), ty::Clause::Projection(ref pair) => pair.fmt(f), + ty::Clause::WellFormed(ref data) => write!(f, "WellFormed({:?})", data), } } } @@ -189,7 +190,6 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { ty::PredicateKind::Clause(ref a) => a.fmt(f), ty::PredicateKind::Subtype(ref pair) => pair.fmt(f), ty::PredicateKind::Coerce(ref pair) => pair.fmt(f), - ty::PredicateKind::WellFormed(data) => write!(f, "WellFormed({:?})", data), ty::PredicateKind::ObjectSafe(trait_def_id) => { write!(f, "ObjectSafe({:?})", trait_def_id) } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 5ef11acadcedd..0c23ae2b68f58 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -183,7 +183,7 @@ where ty.visit_with(self) } ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self), - ty::PredicateKind::WellFormed(arg) => arg.visit_with(self), + ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => arg.visit_with(self), ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ClosureKind(_, _, _) diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 8592fc164d049..c353ddf6fdd7e 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -319,7 +319,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ty::PredicateKind::ObjectSafe(trait_def_id) => { self.compute_object_safe_goal(trait_def_id) } - ty::PredicateKind::WellFormed(arg) => { + ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => { self.compute_well_formed_goal(Goal { param_env, predicate: arg }) } ty::PredicateKind::Ambiguous => { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 212327448c874..ddc28e6128d7c 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -119,7 +119,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { ) } ty::PredicateKind::Clause(_) - | ty::PredicateKind::WellFormed(_) | ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ClosureKind(_, _, _) | ty::PredicateKind::ConstEvaluatable(_) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 62d2aad5277f6..03e01d61996f6 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -826,7 +826,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // we start out with a `ParamEnv` with no inference variables, // and these don't correspond to adding any new bounds to // the `ParamEnv`. - ty::PredicateKind::WellFormed(..) + ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(..) 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 ffbe2888bf848..558cd9ebf21a0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1048,7 +1048,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.report_closure_error(&obligation, closure_def_id, found_kind, kind) } - ty::PredicateKind::WellFormed(ty) => { + ty::PredicateKind::Clause(ty::Clause::WellFormed(ty)) => { match self.tcx.sess.opts.unstable_opts.trait_solver { TraitSolver::Classic => { // WF predicates cannot themselves make @@ -2415,7 +2415,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err } - ty::PredicateKind::WellFormed(arg) => { + ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => { // Same hacky approach as above to avoid deluging user // with error messages. if arg.references_error() diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 88d2091de0f52..c29e017860161 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -354,7 +354,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::Clause(ty::Clause::RegionOutlives(_)) | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::WellFormed(_) + | ty::PredicateKind::Clause(ty::Clause::WellFormed(_)) | ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(_) @@ -433,7 +433,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } } - ty::PredicateKind::WellFormed(arg) => { + ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => { match wf::obligations( self.selcx.infcx, obligation.param_env, diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index b2771915eef8e..3a197d78c5f24 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -310,7 +310,7 @@ fn predicate_references_self<'tcx>( ty::PredicateKind::AliasRelate(..) => bug!("`AliasRelate` not allowed as assumption"), - ty::PredicateKind::WellFormed(..) + ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) @@ -361,7 +361,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) - | ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs index 01d7a1e7913b5..7405ca31cdead 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs @@ -67,7 +67,8 @@ fn relate_mir_and_user_ty<'tcx>( ocx.eq(&cause, param_env, mir_ty, user_ty)?; // FIXME(#104764): We should check well-formedness before normalization. - let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(user_ty.into())); + let predicate = + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(user_ty.into()))); ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate)); Ok(()) } @@ -119,7 +120,9 @@ fn relate_mir_and_user_substs<'tcx>( let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty); ocx.eq(&cause, param_env, self_ty, impl_self_ty)?; - let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into())); + let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed( + impl_self_ty.into(), + ))); ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate)); } @@ -134,7 +137,7 @@ fn relate_mir_and_user_substs<'tcx>( // them? This would only be relevant if some input // type were ill-formed but did not appear in `ty`, // which...could happen with normalization... - let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())); + let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(ty.into()))); ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate)); Ok(()) } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 9989fc9c479a3..90683d7e06650 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -137,7 +137,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} // We need to search through *all* WellFormed predicates - ty::PredicateKind::WellFormed(arg) => { + ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => { wf_args.push(arg); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e72d3ca97d7c9..0a64ffc42b281 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -674,7 +674,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::PredicateKind::WellFormed(arg) => { + ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => { // So, there is a bit going on here. First, `WellFormed` predicates // are coinductive, like trait predicates with auto traits. // This means that we need to detect if we have recursively diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 92d899b0f1382..ee609c34d1bd1 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -160,7 +160,7 @@ pub fn predicate_obligations<'tcx>( wf.compute(ct.into()); wf.compute(ty.into()); } - ty::PredicateKind::WellFormed(arg) => { + ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => { wf.compute(arg); } @@ -386,7 +386,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, depth, param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(arg))), ) }), ); @@ -478,7 +478,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause.clone(), depth, param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(arg))), ) }), ); @@ -541,7 +541,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, self.recursion_depth, self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())), + ty::Binder::dummy(ty::PredicateKind::Clause( + ty::Clause::WellFormed(ct.into()), + )), )); } ty::ConstKind::Expr(_) => { @@ -784,7 +786,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, self.recursion_depth, param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())), + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed( + ty.into(), + ))), )); } } @@ -969,7 +973,7 @@ pub(crate) fn required_region_bounds<'tcx>( | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index f9a7c8c386ae9..8112c3ed3b14b 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -122,7 +122,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment match arg.unpack() { + ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => match arg.unpack() { ty::GenericArgKind::Type(ty) => chalk_ir::DomainGoal::WellFormed( chalk_ir::WellFormed::Ty(ty.lower_into(interner)), ), @@ -192,7 +192,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)), )) } - ty::PredicateKind::WellFormed(arg) => match arg.unpack() { + ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => match arg.unpack() { GenericArgKind::Type(ty) => match ty.kind() { // FIXME(chalk): In Chalk, a placeholder is WellFormed if it // `FromEnv`. However, when we "lower" Params, we don't update @@ -672,7 +672,7 @@ impl<'tcx> LowerInto<'tcx, Option { Some(chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner))) } - ty::PredicateKind::WellFormed(_ty) => None, + ty::PredicateKind::Clause(ty::Clause::WellFormed(_ty)) => None, ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None, ty::PredicateKind::ObjectSafe(..) @@ -807,7 +807,7 @@ impl<'tcx> LowerInto<'tcx, Option None, - ty::PredicateKind::WellFormed(_ty) => None, + ty::PredicateKind::Clause(ty::Clause::WellFormed(_ty)) => None, ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None, ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 94c33efaeff7a..71357efae9bf3 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -62,7 +62,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { | ty::PredicateKind::Clause(ty::Clause::Projection(..)) | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9f698a3b6bf9d..4ebe7e3227603 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -345,7 +345,7 @@ pub(crate) fn clean_predicate<'tcx>( } // FIXME(generic_const_exprs): should this do something? ty::PredicateKind::ConstEvaluatable(..) => None, - ty::PredicateKind::WellFormed(..) => None, + ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) => None, ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None, ty::PredicateKind::Subtype(..) diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index c0d2c835d63d4..b132e69269d8d 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -33,7 +33,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) | ty::Clause::Trait(..) | ty::Clause::ConstArgHasType(..), ) - | ty::PredicateKind::WellFormed(_) + | ty::PredicateKind::Clause(ty::Clause::WellFormed(_)) | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, From 6594c75449fcf53474fb47182f1326b230cbcbe8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Jun 2023 18:35:52 +0000 Subject: [PATCH 13/14] Move ConstEvaluatable to Clause --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 4 ++-- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 4 ++-- .../src/collect/predicates_of.rs | 2 +- .../src/impl_wf_check/min_specialization.rs | 2 +- .../rustc_hir_analysis/src/outlives/explicit.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- compiler/rustc_infer/src/infer/outlives/mod.rs | 2 +- compiler/rustc_infer/src/traits/util.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 4 ++-- compiler/rustc_middle/src/ty/flags.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 16 +++++++--------- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/structural_impls.rs | 6 +++--- compiler/rustc_privacy/src/lib.rs | 2 +- .../rustc_trait_selection/src/solve/eval_ctxt.rs | 2 +- .../rustc_trait_selection/src/solve/fulfill.rs | 1 - .../src/traits/auto_trait.rs | 2 +- .../src/traits/const_evaluatable.rs | 2 +- .../src/traits/error_reporting/mod.rs | 6 +++--- .../rustc_trait_selection/src/traits/fulfill.rs | 4 ++-- .../src/traits/object_safety.rs | 4 ++-- .../query/type_op/implied_outlives_bounds.rs | 2 +- .../src/traits/select/mod.rs | 2 +- compiler/rustc_trait_selection/src/traits/wf.rs | 14 ++++++++------ compiler/rustc_traits/src/chalk/lowering.rs | 8 ++++---- .../src/normalize_erasing_regions.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- .../clippy_utils/src/qualify_min_const_fn.rs | 2 +- 30 files changed, 54 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 3b55c52c34205..f29ed903c95d7 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1529,14 +1529,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) - | ty::Clause::WellFormed(_) => bug!(), + | ty::Clause::WellFormed(_) + | ty::Clause::ConstEvaluatable(_) => bug!(), }, ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ClosureKind(_, _, _) | ty::PredicateKind::Subtype(_) | ty::PredicateKind::Coerce(_) - | ty::PredicateKind::ConstEvaluatable(_) | ty::PredicateKind::ConstEquate(_, _) | ty::PredicateKind::TypeWellFormedFromEnv(_) | ty::PredicateKind::Ambiguous => bug!(), diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 132335e74ef9d..73a7ba005b330 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1032,9 +1032,9 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b tcx, cause, wfcx.param_env, - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable( + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable( ty::Const::from_anon_const(tcx, discr_def_id.expect_local()), - )), + ))), )); } } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 843896d85aa0c..c67f82968f06a 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -353,7 +353,7 @@ fn const_evaluatable_predicates_of( if let ty::ConstKind::Unevaluated(_) = ct.kind() { let span = self.tcx.def_span(c.def_id); self.preds.insert(( - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)) + ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(ct))) .to_predicate(self.tcx), span, )); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 4517d24d154a9..201cb94f0b319 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -547,7 +547,7 @@ fn trait_predicate_kind<'tcx>( | ty::PredicateKind::Coerce(_) | ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index ecdf8dca5c120..79c56490f3c1a 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -61,7 +61,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => (), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 9b593ddccfdd9..34f98f4310ee4 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -671,7 +671,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) // N.B., this predicate is created by breaking down a // `ClosureType: FnFoo()` predicate, where diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 3efdab534384b..2135643cbeb93 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -32,7 +32,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(arg, ty)) => { vec![ty.into(), arg.into()] } - ty::PredicateKind::ConstEvaluatable(e) => vec![e.into()], + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(e)) => vec![e.into()], _ => return false, }; diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index e4c2f61da5626..91347c01327c3 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -842,7 +842,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::AliasRelate(..) diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 3edf98cc869cf..c1f0b9253a5e8 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -33,7 +33,7 @@ pub fn explicit_outlives_bounds<'tcx>( | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 66056de03b572..5622062ef7ef7 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -249,7 +249,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { ty::PredicateKind::ClosureKind(..) => { // Nothing to elaborate when waiting for a closure's kind to be inferred. } - ty::PredicateKind::ConstEvaluatable(..) => { + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) => { // Currently, we do not elaborate const-evaluatable // predicates. } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 6262d875552b4..785adc0b4fb69 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1611,12 +1611,12 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { AliasRelate(..) | // Ignore bounds that a user can't type Clause(Clause::WellFormed(..)) | + // FIXME(generic_const_exprs): `ConstEvaluatable` can be written + Clause(Clause::ConstEvaluatable(..)) | ObjectSafe(..) | ClosureKind(..) | Subtype(..) | Coerce(..) | - // FIXME(generic_const_exprs): `ConstEvaluatable` can be written - ConstEvaluatable(..) | ConstEquate(..) | Ambiguous | TypeWellFormedFromEnv(..) => continue, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index aa2af5bb2b085..684af1abdf6f6 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -277,7 +277,7 @@ impl FlagComputation { ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => { self.add_substs(substs); } - ty::PredicateKind::ConstEvaluatable(uv) => { + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(uv)) => { self.add_const(uv); } ty::PredicateKind::ConstEquate(expected, found) => { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 155adda02a953..e516e843d06c7 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -547,7 +547,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::ClosureKind(_, _, _) | PredicateKind::Subtype(_) | PredicateKind::Coerce(_) - | PredicateKind::ConstEvaluatable(_) + | PredicateKind::Clause(Clause::ConstEvaluatable(_)) | PredicateKind::ConstEquate(_, _) | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(_) => true, @@ -587,6 +587,9 @@ pub enum Clause<'tcx> { /// No syntax: `T` well-formed. WellFormed(GenericArg<'tcx>), + + /// Constant initializer must evaluate successfully. + ConstEvaluatable(ty::Const<'tcx>), } impl<'tcx> Binder<'tcx, Clause<'tcx>> { @@ -638,9 +641,6 @@ pub enum PredicateKind<'tcx> { /// logic. Coerce(CoercePredicate<'tcx>), - /// Constant initializer must evaluate successfully. - ConstEvaluatable(ty::Const<'tcx>), - /// Constants must be equal. The first component is the const that is expected. ConstEquate(Const<'tcx>, Const<'tcx>), @@ -1328,7 +1328,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) | PredicateKind::Clause(Clause::TypeOutlives(..)) - | PredicateKind::ConstEvaluatable(..) + | PredicateKind::Clause(Clause::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, @@ -1349,7 +1349,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) | PredicateKind::Clause(Clause::TypeOutlives(..)) - | PredicateKind::ConstEvaluatable(..) + | PredicateKind::Clause(Clause::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, @@ -1370,7 +1370,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(Clause::WellFormed(..)) | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) - | PredicateKind::ConstEvaluatable(..) + | PredicateKind::Clause(Clause::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, @@ -1384,10 +1384,8 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) - | PredicateKind::WellFormed(..) | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) - | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 4f8566c215c1a..4bfed74f7054d 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2886,7 +2886,7 @@ define_print_and_forward_display! { print_value_path(closure_def_id, &[]), write("` implements the trait `{}`", kind) ), - ty::PredicateKind::ConstEvaluatable(ct) => { + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(ct)) => { p!("the constant `", print(ct), "` can be evaluated") } ty::PredicateKind::ConstEquate(c1, c2) => { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 6db49c7300f41..a4a2fec07ec3a 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -180,6 +180,9 @@ impl<'tcx> fmt::Debug for ty::Clause<'tcx> { ty::Clause::TypeOutlives(ref pair) => pair.fmt(f), ty::Clause::Projection(ref pair) => pair.fmt(f), ty::Clause::WellFormed(ref data) => write!(f, "WellFormed({:?})", data), + ty::Clause::ConstEvaluatable(ct) => { + write!(f, "ConstEvaluatable({ct:?})") + } } } } @@ -196,9 +199,6 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => { write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind) } - ty::PredicateKind::ConstEvaluatable(ct) => { - write!(f, "ConstEvaluatable({ct:?})") - } ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2), ty::PredicateKind::TypeWellFormedFromEnv(ty) => { write!(f, "TypeWellFormedFromEnv({:?})", ty) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 0c23ae2b68f58..0809919016852 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -182,7 +182,7 @@ where ct.visit_with(self)?; ty.visit_with(self) } - ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self), + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(ct)) => ct.visit_with(self), ty::PredicateKind::Clause(ty::Clause::WellFormed(arg)) => arg.visit_with(self), ty::PredicateKind::ObjectSafe(_) diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index c353ddf6fdd7e..8625958ff5a2c 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -326,7 +326,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } // FIXME: implement this predicate :) - ty::PredicateKind::ConstEvaluatable(_) => { + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(_)) => { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } ty::PredicateKind::ConstEquate(_, _) => { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index ddc28e6128d7c..65c8d9c8f6979 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -121,7 +121,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { ty::PredicateKind::Clause(_) | ty::PredicateKind::ObjectSafe(_) | ty::PredicateKind::ClosureKind(_, _, _) - | ty::PredicateKind::ConstEvaluatable(_) | ty::PredicateKind::Ambiguous => { FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 03e01d61996f6..56fde8cd70cb3 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -833,7 +833,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) // FIXME(generic_const_exprs): you can absolutely add this as a where clauses - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::Coerce(..) => {} ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("predicate should only exist in the environment: {bound_predicate:?}") diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index bd1ea43a78e92..f8789b554b1ad 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -207,7 +207,7 @@ fn satisfied_from_param_env<'tcx>( for pred in param_env.caller_bounds() { match pred.kind().skip_binder() { - ty::PredicateKind::ConstEvaluatable(ce) => { + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(ce)) => { let b_ct = tcx.expand_abstract_consts(ce); let mut v = Visitor { ct, infcx, param_env, single_match }; let _ = b_ct.visit_with(&mut v); 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 558cd9ebf21a0..398ec28a42638 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1069,7 +1069,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - ty::PredicateKind::ConstEvaluatable(..) => { + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) => { // Errors for `ConstEvaluatable` predicates show up as // `SelectionError::ConstEvalFailure`, // not `Unimplemented`. @@ -2487,7 +2487,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - ty::PredicateKind::ConstEvaluatable(data) => { + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(data)) => { if predicate.references_error() || self.tainted_by_errors().is_some() { return; } @@ -3325,7 +3325,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } match obligation.predicate.kind().skip_binder() { - ty::PredicateKind::ConstEvaluatable(ct) => { + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(ct)) => { let ty::ConstKind::Unevaluated(uv) = ct.kind() else { bug!("const evaluatable failed for non-unevaluated const `{ct:?}`"); }; diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index c29e017860161..6e4bda3df03e7 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -359,7 +359,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(_) | ty::PredicateKind::Coerce(_) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) => { let pred = ty::Binder::dummy(infcx.instantiate_binder_with_placeholders(binder)); @@ -498,7 +498,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } } - ty::PredicateKind::ConstEvaluatable(uv) => { + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(uv)) => { match const_evaluatable::is_const_evaluatable( self.selcx.infcx, uv, diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 3a197d78c5f24..8c42df6e012d3 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -318,7 +318,7 @@ fn predicate_references_self<'tcx>( | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) // FIXME(generic_const_exprs): this can mention `Self` - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, @@ -365,7 +365,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Ambiguous diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 90683d7e06650..8761f4fea6c2c 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -130,7 +130,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( | ty::PredicateKind::Clause(ty::Clause::Projection(..)) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::AliasRelate(..) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 0a64ffc42b281..ca2ae9b523509 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -862,7 +862,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - ty::PredicateKind::ConstEvaluatable(uv) => { + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(uv)) => { match const_evaluatable::is_const_evaluatable( self.infcx, uv, diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index ee609c34d1bd1..676978fabe4d1 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -164,7 +164,7 @@ pub fn predicate_obligations<'tcx>( wf.compute(arg); } - ty::PredicateKind::ConstEvaluatable(ct) => { + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(ct)) => { wf.compute(ct.into()); } @@ -521,8 +521,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let obligations = self.nominal_obligations(uv.def, uv.substs); self.out.extend(obligations); - let predicate = - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)); + let predicate = ty::Binder::dummy(ty::PredicateKind::Clause( + ty::Clause::ConstEvaluatable(ct), + )); let cause = self.cause(traits::WellFormed(None)); self.out.push(traits::Obligation::with_depth( self.tcx(), @@ -554,8 +555,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // the future we may allow directly lowering to `ConstKind::Expr` in which case // we would not be proving bounds we should. - let predicate = - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)); + let predicate = ty::Binder::dummy(ty::PredicateKind::Clause( + ty::Clause::ConstEvaluatable(ct), + )); let cause = self.cause(traits::WellFormed(None)); self.out.push(traits::Obligation::with_depth( self.tcx(), @@ -977,7 +979,7 @@ pub(crate) fn required_region_bounds<'tcx>( | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::AliasRelate(..) diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 8112c3ed3b14b..1d4219bc0c0b1 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -137,7 +137,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment bug!("unexpected predicate {}", predicate), }; @@ -231,7 +231,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::Ambiguous | ty::PredicateKind::ConstEquate(..) => { chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner)) @@ -680,7 +680,7 @@ impl<'tcx> LowerInto<'tcx, Option { @@ -816,7 +816,7 @@ impl<'tcx> LowerInto<'tcx, Option { diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 71357efae9bf3..7f6d53fe86043 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -67,7 +67,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { | ty::PredicateKind::ClosureKind(..) | ty::PredicateKind::Subtype(..) | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::TypeWellFormedFromEnv(..) => true, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4ebe7e3227603..29c11e1f3359d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -344,7 +344,7 @@ pub(crate) fn clean_predicate<'tcx>( Some(clean_projection_predicate(bound_predicate.rebind(pred), cx)) } // FIXME(generic_const_exprs): should this do something? - ty::PredicateKind::ConstEvaluatable(..) => None, + ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) => None, ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) => None, ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None, diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index b132e69269d8d..860a489494c88 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -34,7 +34,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) | ty::Clause::ConstArgHasType(..), ) | ty::PredicateKind::Clause(ty::Clause::WellFormed(_)) - | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => continue, ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"), From 4343d360793e428460f69d6df81acf6944d48fe8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 16 Jun 2023 18:24:43 +0000 Subject: [PATCH 14/14] Move some bounds computation out of astconv into its own file --- .../rustc_hir_analysis/src/astconv/bounds.rs | 583 ++++++++++++++++++ .../rustc_hir_analysis/src/astconv/mod.rs | 569 +---------------- 2 files changed, 585 insertions(+), 567 deletions(-) create mode 100644 compiler/rustc_hir_analysis/src/astconv/bounds.rs diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs new file mode 100644 index 0000000000000..e4eb0e6abd435 --- /dev/null +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -0,0 +1,583 @@ +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::struct_span_err; +use rustc_hir as hir; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_lint_defs::Applicability; +use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt}; +use rustc_span::symbol::Ident; +use rustc_span::{ErrorGuaranteed, Span}; +use rustc_trait_selection::traits; + +use crate::astconv::{AstConv, ConvertedBinding, ConvertedBindingKind}; +use crate::bounds::Bounds; +use crate::errors::{MultipleRelaxedDefaultBounds, ValueOfAssociatedStructAlreadySpecified}; + +use super::OnlySelfBounds; + +impl<'tcx> dyn AstConv<'tcx> + '_ { + /// Sets `implicitly_sized` to true on `Bounds` if necessary + pub(crate) fn add_implicitly_sized( + &self, + bounds: &mut Bounds<'tcx>, + self_ty: Ty<'tcx>, + ast_bounds: &'tcx [hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + span: Span, + ) { + let tcx = self.tcx(); + + // Try to find an unbound in bounds. + let mut unbound = None; + let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| { + for ab in ast_bounds { + if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { + if unbound.is_none() { + unbound = Some(&ptr.trait_ref); + } else { + tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span }); + } + } + } + }; + search_bounds(ast_bounds); + if let Some((self_ty, where_clause)) = self_ty_where_predicates { + for clause in where_clause { + if let hir::WherePredicate::BoundPredicate(pred) = clause { + if pred.is_param_bound(self_ty.to_def_id()) { + search_bounds(pred.bounds); + } + } + } + } + + let sized_def_id = tcx.lang_items().sized_trait(); + match (&sized_def_id, unbound) { + (Some(sized_def_id), Some(tpb)) + if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) => + { + // There was in fact a `?Sized` bound, return without doing anything + return; + } + (_, Some(_)) => { + // There was a `?Trait` bound, but it was not `?Sized`; warn. + tcx.sess.span_warn( + span, + "default bound relaxed for a type parameter, but \ + this does nothing because the given bound is not \ + a default; only `?Sized` is supported", + ); + // Otherwise, add implicitly sized if `Sized` is available. + } + _ => { + // There was no `?Sized` bound; add implicitly sized if `Sized` is available. + } + } + if sized_def_id.is_none() { + // No lang item for `Sized`, so we can't add it as a bound. + return; + } + bounds.push_sized(tcx, self_ty, span); + } + + /// This helper takes a *converted* parameter type (`param_ty`) + /// and an *unconverted* list of bounds: + /// + /// ```text + /// fn foo + /// ^ ^^^^^ `ast_bounds` parameter, in HIR form + /// | + /// `param_ty`, in ty form + /// ``` + /// + /// It adds these `ast_bounds` into the `bounds` structure. + /// + /// **A note on binders:** there is an implied binder around + /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` + /// for more details. + #[instrument(level = "debug", skip(self, ast_bounds, bounds))] + pub(crate) fn add_bounds<'hir, I: Iterator>>( + &self, + param_ty: Ty<'tcx>, + ast_bounds: I, + bounds: &mut Bounds<'tcx>, + bound_vars: &'tcx ty::List, + only_self_bounds: OnlySelfBounds, + ) { + for ast_bound in ast_bounds { + match ast_bound { + hir::GenericBound::Trait(poly_trait_ref, modifier) => { + let (constness, polarity) = match modifier { + hir::TraitBoundModifier::MaybeConst => { + (ty::BoundConstness::ConstIfConst, ty::ImplPolarity::Positive) + } + hir::TraitBoundModifier::None => { + (ty::BoundConstness::NotConst, ty::ImplPolarity::Positive) + } + hir::TraitBoundModifier::Negative => { + (ty::BoundConstness::NotConst, ty::ImplPolarity::Negative) + } + hir::TraitBoundModifier::Maybe => continue, + }; + let _ = self.instantiate_poly_trait_ref( + &poly_trait_ref.trait_ref, + poly_trait_ref.span, + constness, + polarity, + param_ty, + bounds, + false, + only_self_bounds, + ); + } + &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { + self.instantiate_lang_item_trait_ref( + lang_item, + span, + hir_id, + args, + param_ty, + bounds, + only_self_bounds, + ); + } + hir::GenericBound::Outlives(lifetime) => { + let region = self.ast_region_to_region(lifetime, None); + bounds.push_region_bound( + self.tcx(), + ty::Binder::bind_with_vars( + ty::OutlivesPredicate(param_ty, region), + bound_vars, + ), + lifetime.ident.span, + ); + } + } + } + } + + /// Translates a list of bounds from the HIR into the `Bounds` data structure. + /// The self-type for the bounds is given by `param_ty`. + /// + /// Example: + /// + /// ```ignore (illustrative) + /// fn foo() { } + /// // ^ ^^^^^^^^^ ast_bounds + /// // param_ty + /// ``` + /// + /// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be + /// considered `Sized` unless there is an explicit `?Sized` bound. This would be true in the + /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`. + /// + /// `span` should be the declaration size of the parameter. + pub(crate) fn compute_bounds( + &self, + param_ty: Ty<'tcx>, + ast_bounds: &[hir::GenericBound<'_>], + only_self_bounds: OnlySelfBounds, + ) -> Bounds<'tcx> { + let mut bounds = Bounds::default(); + self.add_bounds( + param_ty, + ast_bounds.iter(), + &mut bounds, + ty::List::empty(), + only_self_bounds, + ); + debug!(?bounds); + + bounds + } + + /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type + /// named `assoc_name` into ty::Bounds. Ignore the rest. + pub(crate) fn compute_bounds_that_match_assoc_item( + &self, + param_ty: Ty<'tcx>, + ast_bounds: &[hir::GenericBound<'_>], + assoc_name: Ident, + ) -> Bounds<'tcx> { + let mut result = Vec::new(); + + for ast_bound in ast_bounds { + if let Some(trait_ref) = ast_bound.trait_ref() + && let Some(trait_did) = trait_ref.trait_def_id() + && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name) + { + result.push(ast_bound.clone()); + } + } + + let mut bounds = Bounds::default(); + self.add_bounds( + param_ty, + result.iter(), + &mut bounds, + ty::List::empty(), + OnlySelfBounds(true), + ); + debug!(?bounds); + + bounds + } + + /// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates + /// onto `bounds`. + /// + /// **A note on binders:** given something like `T: for<'a> Iterator`, the + /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside* + /// the binder (e.g., `&'a u32`) and hence may reference bound regions. + #[instrument(level = "debug", skip(self, bounds, speculative, dup_bindings, path_span))] + pub(super) fn add_predicates_for_ast_type_binding( + &self, + hir_ref_id: hir::HirId, + trait_ref: ty::PolyTraitRef<'tcx>, + binding: &ConvertedBinding<'_, 'tcx>, + bounds: &mut Bounds<'tcx>, + speculative: bool, + dup_bindings: &mut FxHashMap, + path_span: Span, + constness: ty::BoundConstness, + only_self_bounds: OnlySelfBounds, + polarity: ty::ImplPolarity, + ) -> Result<(), ErrorGuaranteed> { + // Given something like `U: SomeTrait`, we want to produce a + // predicate like `::T = X`. This is somewhat + // subtle in the event that `T` is defined in a supertrait of + // `SomeTrait`, because in that case we need to upcast. + // + // That is, consider this case: + // + // ``` + // trait SubTrait: SuperTrait { } + // trait SuperTrait { type T; } + // + // ... B: SubTrait ... + // ``` + // + // We want to produce `>::T == foo`. + + let tcx = self.tcx(); + + let return_type_notation = + binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation; + + let candidate = if return_type_notation { + if self.trait_defines_associated_item_named( + trait_ref.def_id(), + ty::AssocKind::Fn, + binding.item_name, + ) { + trait_ref + } else { + self.one_bound_for_assoc_method( + traits::supertraits(tcx, trait_ref), + trait_ref.print_only_trait_path(), + binding.item_name, + path_span, + )? + } + } else if self.trait_defines_associated_item_named( + trait_ref.def_id(), + ty::AssocKind::Type, + binding.item_name, + ) { + // Simple case: X is defined in the current trait. + trait_ref + } else { + // Otherwise, we have to walk through the supertraits to find + // those that do. + self.one_bound_for_assoc_type( + || traits::supertraits(tcx, trait_ref), + trait_ref.skip_binder().print_only_trait_name(), + binding.item_name, + path_span, + match binding.kind { + ConvertedBindingKind::Equality(term) => Some(term), + _ => None, + }, + )? + }; + + let (assoc_ident, def_scope) = + tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); + + // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead + // of calling `filter_by_name_and_kind`. + let find_item_of_kind = |kind| { + tcx.associated_items(candidate.def_id()) + .filter_by_name_unhygienic(assoc_ident.name) + .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident) + }; + let assoc_item = if return_type_notation { + find_item_of_kind(ty::AssocKind::Fn) + } else { + find_item_of_kind(ty::AssocKind::Type) + .or_else(|| find_item_of_kind(ty::AssocKind::Const)) + } + .expect("missing associated type"); + + if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) { + tcx.sess + .struct_span_err( + binding.span, + format!("{} `{}` is private", assoc_item.kind, binding.item_name), + ) + .span_label(binding.span, format!("private {}", assoc_item.kind)) + .emit(); + } + tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); + + if !speculative { + dup_bindings + .entry(assoc_item.def_id) + .and_modify(|prev_span| { + tcx.sess.emit_err(ValueOfAssociatedStructAlreadySpecified { + span: binding.span, + prev_span: *prev_span, + item_name: binding.item_name, + def_path: tcx.def_path_str(assoc_item.container_id(tcx)), + }); + }) + .or_insert(binding.span); + } + + let projection_ty = if return_type_notation { + let mut emitted_bad_param_err = false; + // If we have an method return type bound, then we need to substitute + // the method's early bound params with suitable late-bound params. + let mut num_bound_vars = candidate.bound_vars().len(); + let substs = + candidate.skip_binder().substs.extend_to(tcx, assoc_item.def_id, |param, _| { + let subst = match param.kind { + ty::GenericParamDefKind::Lifetime => ty::Region::new_late_bound( + tcx, + ty::INNERMOST, + ty::BoundRegion { + var: ty::BoundVar::from_usize(num_bound_vars), + kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name), + }, + ) + .into(), + ty::GenericParamDefKind::Type { .. } => { + if !emitted_bad_param_err { + tcx.sess.emit_err( + crate::errors::ReturnTypeNotationIllegalParam::Type { + span: path_span, + param_span: tcx.def_span(param.def_id), + }, + ); + emitted_bad_param_err = true; + } + tcx.mk_bound( + ty::INNERMOST, + ty::BoundTy { + var: ty::BoundVar::from_usize(num_bound_vars), + kind: ty::BoundTyKind::Param(param.def_id, param.name), + }, + ) + .into() + } + ty::GenericParamDefKind::Const { .. } => { + if !emitted_bad_param_err { + tcx.sess.emit_err( + crate::errors::ReturnTypeNotationIllegalParam::Const { + span: path_span, + param_span: tcx.def_span(param.def_id), + }, + ); + emitted_bad_param_err = true; + } + let ty = tcx + .type_of(param.def_id) + .no_bound_vars() + .expect("ct params cannot have early bound vars"); + tcx.mk_const( + ty::ConstKind::Bound( + ty::INNERMOST, + ty::BoundVar::from_usize(num_bound_vars), + ), + ty, + ) + .into() + } + }; + num_bound_vars += 1; + subst + }); + + // Next, we need to check that the return-type notation is being used on + // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait). + let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output(); + let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind() + && tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder + { + alias_ty + } else { + return Err(self.tcx().sess.emit_err( + crate::errors::ReturnTypeNotationOnNonRpitit { + span: binding.span, + ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output), + fn_span: tcx.hir().span_if_local(assoc_item.def_id), + note: (), + }, + )); + }; + + // Finally, move the fn return type's bound vars over to account for the early bound + // params (and trait ref's late bound params). This logic is very similar to + // `Predicate::subst_supertrait`, and it's no coincidence why. + let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); + let subst_output = ty::EarlyBinder::bind(shifted_output).subst(tcx, substs); + + let bound_vars = tcx.late_bound_vars(binding.hir_id); + ty::Binder::bind_with_vars(subst_output, bound_vars) + } else { + // Include substitutions for generic parameters of associated types + candidate.map_bound(|trait_ref| { + let ident = Ident::new(assoc_item.name, binding.item_name.span); + let item_segment = hir::PathSegment { + ident, + hir_id: binding.hir_id, + res: Res::Err, + args: Some(binding.gen_args), + infer_args: false, + }; + + let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item( + path_span, + assoc_item.def_id, + &item_segment, + trait_ref.substs, + ); + + debug!(?substs_trait_ref_and_assoc_item); + + tcx.mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item) + }) + }; + + if !speculative { + // Find any late-bound regions declared in `ty` that are not + // declared in the trait-ref or assoc_item. These are not well-formed. + // + // Example: + // + // for<'a> ::Item = &'a str // <-- 'a is bad + // for<'a> >::Output = &'a str // <-- 'a is ok + if let ConvertedBindingKind::Equality(ty) = binding.kind { + let late_bound_in_trait_ref = + tcx.collect_constrained_late_bound_regions(&projection_ty); + let late_bound_in_ty = + tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty)); + debug!(?late_bound_in_trait_ref); + debug!(?late_bound_in_ty); + + // FIXME: point at the type params that don't have appropriate lifetimes: + // struct S1 Fn(&i32, &i32) -> &'a i32>(F); + // ---- ---- ^^^^^^^ + self.validate_late_bound_regions( + late_bound_in_trait_ref, + late_bound_in_ty, + |br_name| { + struct_span_err!( + tcx.sess, + binding.span, + E0582, + "binding for associated type `{}` references {}, \ + which does not appear in the trait input types", + binding.item_name, + br_name + ) + }, + ); + } + } + + match binding.kind { + ConvertedBindingKind::Equality(..) if return_type_notation => { + return Err(self.tcx().sess.emit_err( + crate::errors::ReturnTypeNotationEqualityBound { span: binding.span }, + )); + } + ConvertedBindingKind::Equality(mut term) => { + // "Desugar" a constraint like `T: Iterator` this to + // the "projection predicate" for: + // + // `::Item = u32` + let assoc_item_def_id = projection_ty.skip_binder().def_id; + let def_kind = tcx.def_kind(assoc_item_def_id); + match (def_kind, term.unpack()) { + (hir::def::DefKind::AssocTy, ty::TermKind::Ty(_)) + | (hir::def::DefKind::AssocConst, ty::TermKind::Const(_)) => (), + (_, _) => { + let got = if let Some(_) = term.ty() { "type" } else { "constant" }; + let expected = tcx.def_descr(assoc_item_def_id); + let mut err = tcx.sess.struct_span_err( + binding.span, + format!("expected {expected} bound, found {got}"), + ); + err.span_note( + tcx.def_span(assoc_item_def_id), + format!("{expected} defined here"), + ); + + if let hir::def::DefKind::AssocConst = def_kind + && let Some(t) = term.ty() && (t.is_enum() || t.references_error()) + && tcx.features().associated_const_equality { + err.span_suggestion( + binding.span, + "if equating a const, try wrapping with braces", + format!("{} = {{ const }}", binding.item_name), + Applicability::HasPlaceholders, + ); + } + let reported = err.emit(); + term = match def_kind { + hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(), + hir::def::DefKind::AssocConst => tcx + .const_error( + tcx.type_of(assoc_item_def_id) + .subst(tcx, projection_ty.skip_binder().substs), + reported, + ) + .into(), + _ => unreachable!(), + }; + } + } + bounds.push_projection_bound( + tcx, + projection_ty + .map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }), + binding.span, + ); + } + ConvertedBindingKind::Constraint(ast_bounds) => { + // "Desugar" a constraint like `T: Iterator` to + // + // `::Item: Debug` + // + // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` + // parameter to have a skipped binder. + // + // NOTE: If `only_self_bounds` is true, do NOT expand this associated + // type bound into a trait predicate, since we only want to add predicates + // for the `Self` type. + if !only_self_bounds.0 { + let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder()); + self.add_bounds( + param_ty, + ast_bounds.iter(), + bounds, + projection_ty.bound_vars(), + only_self_bounds, + ); + } + } + } + Ok(()) + } +} diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index f29ed903c95d7..d6645b784c439 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2,6 +2,7 @@ //! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an //! instance of `AstConv`. +mod bounds; mod errors; pub mod generics; mod lint; @@ -11,8 +12,7 @@ use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generi use crate::bounds::Bounds; use crate::collect::HirPlaceholderCollector; use crate::errors::{ - AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits, - TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified, + AmbiguousLifetimeBound, TraitObjectDeclaredWithNoTraits, TypeofReservedKeywordUsed, }; use crate::middle::resolve_bound_vars as rbv; use crate::require_c_abi_if_c_variadic; @@ -885,571 +885,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .is_some() } - /// Sets `implicitly_sized` to true on `Bounds` if necessary - pub(crate) fn add_implicitly_sized( - &self, - bounds: &mut Bounds<'tcx>, - self_ty: Ty<'tcx>, - ast_bounds: &'tcx [hir::GenericBound<'tcx>], - self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, - span: Span, - ) { - let tcx = self.tcx(); - - // Try to find an unbound in bounds. - let mut unbound = None; - let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| { - for ab in ast_bounds { - if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { - if unbound.is_none() { - unbound = Some(&ptr.trait_ref); - } else { - tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span }); - } - } - } - }; - search_bounds(ast_bounds); - if let Some((self_ty, where_clause)) = self_ty_where_predicates { - for clause in where_clause { - if let hir::WherePredicate::BoundPredicate(pred) = clause { - if pred.is_param_bound(self_ty.to_def_id()) { - search_bounds(pred.bounds); - } - } - } - } - - let sized_def_id = tcx.lang_items().sized_trait(); - match (&sized_def_id, unbound) { - (Some(sized_def_id), Some(tpb)) - if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) => - { - // There was in fact a `?Sized` bound, return without doing anything - return; - } - (_, Some(_)) => { - // There was a `?Trait` bound, but it was not `?Sized`; warn. - tcx.sess.span_warn( - span, - "default bound relaxed for a type parameter, but \ - this does nothing because the given bound is not \ - a default; only `?Sized` is supported", - ); - // Otherwise, add implicitly sized if `Sized` is available. - } - _ => { - // There was no `?Sized` bound; add implicitly sized if `Sized` is available. - } - } - if sized_def_id.is_none() { - // No lang item for `Sized`, so we can't add it as a bound. - return; - } - bounds.push_sized(tcx, self_ty, span); - } - - /// This helper takes a *converted* parameter type (`param_ty`) - /// and an *unconverted* list of bounds: - /// - /// ```text - /// fn foo - /// ^ ^^^^^ `ast_bounds` parameter, in HIR form - /// | - /// `param_ty`, in ty form - /// ``` - /// - /// It adds these `ast_bounds` into the `bounds` structure. - /// - /// **A note on binders:** there is an implied binder around - /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` - /// for more details. - #[instrument(level = "debug", skip(self, ast_bounds, bounds))] - pub(crate) fn add_bounds<'hir, I: Iterator>>( - &self, - param_ty: Ty<'tcx>, - ast_bounds: I, - bounds: &mut Bounds<'tcx>, - bound_vars: &'tcx ty::List, - only_self_bounds: OnlySelfBounds, - ) { - for ast_bound in ast_bounds { - match ast_bound { - hir::GenericBound::Trait(poly_trait_ref, modifier) => { - let (constness, polarity) = match modifier { - hir::TraitBoundModifier::MaybeConst => { - (ty::BoundConstness::ConstIfConst, ty::ImplPolarity::Positive) - } - hir::TraitBoundModifier::None => { - (ty::BoundConstness::NotConst, ty::ImplPolarity::Positive) - } - hir::TraitBoundModifier::Negative => { - (ty::BoundConstness::NotConst, ty::ImplPolarity::Negative) - } - hir::TraitBoundModifier::Maybe => continue, - }; - let _ = self.instantiate_poly_trait_ref( - &poly_trait_ref.trait_ref, - poly_trait_ref.span, - constness, - polarity, - param_ty, - bounds, - false, - only_self_bounds, - ); - } - &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { - self.instantiate_lang_item_trait_ref( - lang_item, - span, - hir_id, - args, - param_ty, - bounds, - only_self_bounds, - ); - } - hir::GenericBound::Outlives(lifetime) => { - let region = self.ast_region_to_region(lifetime, None); - bounds.push_region_bound( - self.tcx(), - ty::Binder::bind_with_vars( - ty::OutlivesPredicate(param_ty, region), - bound_vars, - ), - lifetime.ident.span, - ); - } - } - } - } - - /// Translates a list of bounds from the HIR into the `Bounds` data structure. - /// The self-type for the bounds is given by `param_ty`. - /// - /// Example: - /// - /// ```ignore (illustrative) - /// fn foo() { } - /// // ^ ^^^^^^^^^ ast_bounds - /// // param_ty - /// ``` - /// - /// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be - /// considered `Sized` unless there is an explicit `?Sized` bound. This would be true in the - /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`. - /// - /// `span` should be the declaration size of the parameter. - pub(crate) fn compute_bounds( - &self, - param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], - only_self_bounds: OnlySelfBounds, - ) -> Bounds<'tcx> { - let mut bounds = Bounds::default(); - self.add_bounds( - param_ty, - ast_bounds.iter(), - &mut bounds, - ty::List::empty(), - only_self_bounds, - ); - debug!(?bounds); - - bounds - } - - /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type - /// named `assoc_name` into ty::Bounds. Ignore the rest. - pub(crate) fn compute_bounds_that_match_assoc_item( - &self, - param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], - assoc_name: Ident, - ) -> Bounds<'tcx> { - let mut result = Vec::new(); - - for ast_bound in ast_bounds { - if let Some(trait_ref) = ast_bound.trait_ref() - && let Some(trait_did) = trait_ref.trait_def_id() - && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name) - { - result.push(ast_bound.clone()); - } - } - - let mut bounds = Bounds::default(); - self.add_bounds( - param_ty, - result.iter(), - &mut bounds, - ty::List::empty(), - OnlySelfBounds(true), - ); - debug!(?bounds); - - bounds - } - - /// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates - /// onto `bounds`. - /// - /// **A note on binders:** given something like `T: for<'a> Iterator`, the - /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside* - /// the binder (e.g., `&'a u32`) and hence may reference bound regions. - #[instrument(level = "debug", skip(self, bounds, speculative, dup_bindings, path_span))] - fn add_predicates_for_ast_type_binding( - &self, - hir_ref_id: hir::HirId, - trait_ref: ty::PolyTraitRef<'tcx>, - binding: &ConvertedBinding<'_, 'tcx>, - bounds: &mut Bounds<'tcx>, - speculative: bool, - dup_bindings: &mut FxHashMap, - path_span: Span, - constness: ty::BoundConstness, - only_self_bounds: OnlySelfBounds, - polarity: ty::ImplPolarity, - ) -> Result<(), ErrorGuaranteed> { - // Given something like `U: SomeTrait`, we want to produce a - // predicate like `::T = X`. This is somewhat - // subtle in the event that `T` is defined in a supertrait of - // `SomeTrait`, because in that case we need to upcast. - // - // That is, consider this case: - // - // ``` - // trait SubTrait: SuperTrait { } - // trait SuperTrait { type T; } - // - // ... B: SubTrait ... - // ``` - // - // We want to produce `>::T == foo`. - - let tcx = self.tcx(); - - let return_type_notation = - binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation; - - let candidate = if return_type_notation { - if self.trait_defines_associated_item_named( - trait_ref.def_id(), - ty::AssocKind::Fn, - binding.item_name, - ) { - trait_ref - } else { - self.one_bound_for_assoc_method( - traits::supertraits(tcx, trait_ref), - trait_ref.print_only_trait_path(), - binding.item_name, - path_span, - )? - } - } else if self.trait_defines_associated_item_named( - trait_ref.def_id(), - ty::AssocKind::Type, - binding.item_name, - ) { - // Simple case: X is defined in the current trait. - trait_ref - } else { - // Otherwise, we have to walk through the supertraits to find - // those that do. - self.one_bound_for_assoc_type( - || traits::supertraits(tcx, trait_ref), - trait_ref.skip_binder().print_only_trait_name(), - binding.item_name, - path_span, - match binding.kind { - ConvertedBindingKind::Equality(term) => Some(term), - _ => None, - }, - )? - }; - - let (assoc_ident, def_scope) = - tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); - - // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead - // of calling `filter_by_name_and_kind`. - let find_item_of_kind = |kind| { - tcx.associated_items(candidate.def_id()) - .filter_by_name_unhygienic(assoc_ident.name) - .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident) - }; - let assoc_item = if return_type_notation { - find_item_of_kind(ty::AssocKind::Fn) - } else { - find_item_of_kind(ty::AssocKind::Type) - .or_else(|| find_item_of_kind(ty::AssocKind::Const)) - } - .expect("missing associated type"); - - if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) { - tcx.sess - .struct_span_err( - binding.span, - format!("{} `{}` is private", assoc_item.kind, binding.item_name), - ) - .span_label(binding.span, format!("private {}", assoc_item.kind)) - .emit(); - } - tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); - - if !speculative { - dup_bindings - .entry(assoc_item.def_id) - .and_modify(|prev_span| { - tcx.sess.emit_err(ValueOfAssociatedStructAlreadySpecified { - span: binding.span, - prev_span: *prev_span, - item_name: binding.item_name, - def_path: tcx.def_path_str(assoc_item.container_id(tcx)), - }); - }) - .or_insert(binding.span); - } - - let projection_ty = if return_type_notation { - let mut emitted_bad_param_err = false; - // If we have an method return type bound, then we need to substitute - // the method's early bound params with suitable late-bound params. - let mut num_bound_vars = candidate.bound_vars().len(); - let substs = - candidate.skip_binder().substs.extend_to(tcx, assoc_item.def_id, |param, _| { - let subst = match param.kind { - GenericParamDefKind::Lifetime => ty::Region::new_late_bound( - tcx, - ty::INNERMOST, - ty::BoundRegion { - var: ty::BoundVar::from_usize(num_bound_vars), - kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name), - }, - ) - .into(), - GenericParamDefKind::Type { .. } => { - if !emitted_bad_param_err { - tcx.sess.emit_err( - crate::errors::ReturnTypeNotationIllegalParam::Type { - span: path_span, - param_span: tcx.def_span(param.def_id), - }, - ); - emitted_bad_param_err = true; - } - tcx.mk_bound( - ty::INNERMOST, - ty::BoundTy { - var: ty::BoundVar::from_usize(num_bound_vars), - kind: ty::BoundTyKind::Param(param.def_id, param.name), - }, - ) - .into() - } - GenericParamDefKind::Const { .. } => { - if !emitted_bad_param_err { - tcx.sess.emit_err( - crate::errors::ReturnTypeNotationIllegalParam::Const { - span: path_span, - param_span: tcx.def_span(param.def_id), - }, - ); - emitted_bad_param_err = true; - } - let ty = tcx - .type_of(param.def_id) - .no_bound_vars() - .expect("ct params cannot have early bound vars"); - tcx.mk_const( - ty::ConstKind::Bound( - ty::INNERMOST, - ty::BoundVar::from_usize(num_bound_vars), - ), - ty, - ) - .into() - } - }; - num_bound_vars += 1; - subst - }); - - // Next, we need to check that the return-type notation is being used on - // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait). - let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output(); - let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind() - && tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder - { - alias_ty - } else { - return Err(self.tcx().sess.emit_err( - crate::errors::ReturnTypeNotationOnNonRpitit { - span: binding.span, - ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output), - fn_span: tcx.hir().span_if_local(assoc_item.def_id), - note: (), - }, - )); - }; - - // Finally, move the fn return type's bound vars over to account for the early bound - // params (and trait ref's late bound params). This logic is very similar to - // `Predicate::subst_supertrait`, and it's no coincidence why. - let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); - let subst_output = ty::EarlyBinder::bind(shifted_output).subst(tcx, substs); - - let bound_vars = tcx.late_bound_vars(binding.hir_id); - ty::Binder::bind_with_vars(subst_output, bound_vars) - } else { - // Include substitutions for generic parameters of associated types - candidate.map_bound(|trait_ref| { - let ident = Ident::new(assoc_item.name, binding.item_name.span); - let item_segment = hir::PathSegment { - ident, - hir_id: binding.hir_id, - res: Res::Err, - args: Some(binding.gen_args), - infer_args: false, - }; - - let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item( - path_span, - assoc_item.def_id, - &item_segment, - trait_ref.substs, - ); - - debug!(?substs_trait_ref_and_assoc_item); - - tcx.mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item) - }) - }; - - if !speculative { - // Find any late-bound regions declared in `ty` that are not - // declared in the trait-ref or assoc_item. These are not well-formed. - // - // Example: - // - // for<'a> ::Item = &'a str // <-- 'a is bad - // for<'a> >::Output = &'a str // <-- 'a is ok - if let ConvertedBindingKind::Equality(ty) = binding.kind { - let late_bound_in_trait_ref = - tcx.collect_constrained_late_bound_regions(&projection_ty); - let late_bound_in_ty = - tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty)); - debug!(?late_bound_in_trait_ref); - debug!(?late_bound_in_ty); - - // FIXME: point at the type params that don't have appropriate lifetimes: - // struct S1 Fn(&i32, &i32) -> &'a i32>(F); - // ---- ---- ^^^^^^^ - self.validate_late_bound_regions( - late_bound_in_trait_ref, - late_bound_in_ty, - |br_name| { - struct_span_err!( - tcx.sess, - binding.span, - E0582, - "binding for associated type `{}` references {}, \ - which does not appear in the trait input types", - binding.item_name, - br_name - ) - }, - ); - } - } - - match binding.kind { - ConvertedBindingKind::Equality(..) if return_type_notation => { - return Err(self.tcx().sess.emit_err( - crate::errors::ReturnTypeNotationEqualityBound { span: binding.span }, - )); - } - ConvertedBindingKind::Equality(mut term) => { - // "Desugar" a constraint like `T: Iterator` this to - // the "projection predicate" for: - // - // `::Item = u32` - let assoc_item_def_id = projection_ty.skip_binder().def_id; - let def_kind = tcx.def_kind(assoc_item_def_id); - match (def_kind, term.unpack()) { - (hir::def::DefKind::AssocTy, ty::TermKind::Ty(_)) - | (hir::def::DefKind::AssocConst, ty::TermKind::Const(_)) => (), - (_, _) => { - let got = if let Some(_) = term.ty() { "type" } else { "constant" }; - let expected = tcx.def_descr(assoc_item_def_id); - let mut err = tcx.sess.struct_span_err( - binding.span, - format!("expected {expected} bound, found {got}"), - ); - err.span_note( - tcx.def_span(assoc_item_def_id), - format!("{expected} defined here"), - ); - - if let hir::def::DefKind::AssocConst = def_kind - && let Some(t) = term.ty() && (t.is_enum() || t.references_error()) - && tcx.features().associated_const_equality { - err.span_suggestion( - binding.span, - "if equating a const, try wrapping with braces", - format!("{} = {{ const }}", binding.item_name), - Applicability::HasPlaceholders, - ); - } - let reported = err.emit(); - term = match def_kind { - hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(), - hir::def::DefKind::AssocConst => tcx - .const_error( - tcx.type_of(assoc_item_def_id) - .subst(tcx, projection_ty.skip_binder().substs), - reported, - ) - .into(), - _ => unreachable!(), - }; - } - } - bounds.push_projection_bound( - tcx, - projection_ty - .map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }), - binding.span, - ); - } - ConvertedBindingKind::Constraint(ast_bounds) => { - // "Desugar" a constraint like `T: Iterator` to - // - // `::Item: Debug` - // - // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` - // parameter to have a skipped binder. - // - // NOTE: If `only_self_bounds` is true, do NOT expand this associated - // type bound into a trait predicate, since we only want to add predicates - // for the `Self` type. - if !only_self_bounds.0 { - let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder()); - self.add_bounds( - param_ty, - ast_bounds.iter(), - bounds, - projection_ty.bound_vars(), - only_self_bounds, - ); - } - } - } - Ok(()) - } - fn ast_path_to_ty( &self, span: Span,