From 780319a75ba1ce24c5a4cec37051d9ad0a4f90de Mon Sep 17 00:00:00 2001 From: Connor Tsui Date: Sat, 23 Aug 2025 09:01:38 -0400 Subject: [PATCH 01/17] stabilize unstable `rwlock_downgrade` feature Signed-off-by: Connor Tsui --- library/std/src/sync/nonpoison/rwlock.rs | 5 +---- library/std/src/sync/poison/rwlock.rs | 6 +----- library/std/tests/sync/lib.rs | 1 - 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/library/std/src/sync/nonpoison/rwlock.rs b/library/std/src/sync/nonpoison/rwlock.rs index eb0aef99cc1e..0e0d7e058b07 100644 --- a/library/std/src/sync/nonpoison/rwlock.rs +++ b/library/std/src/sync/nonpoison/rwlock.rs @@ -638,7 +638,6 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { /// /// ``` /// #![feature(nonpoison_rwlock)] - /// #![feature(rwlock_downgrade)] /// /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard}; /// @@ -657,7 +656,6 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { /// /// ``` /// #![feature(nonpoison_rwlock)] - /// #![feature(rwlock_downgrade)] /// /// use std::sync::Arc; /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard}; @@ -690,8 +688,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { /// # let final_check = rw.read(); /// # assert_eq!(*final_check, 3); /// ``` - #[unstable(feature = "rwlock_downgrade", issue = "128203")] - // #[unstable(feature = "nonpoison_rwlock", issue = "134645")] + #[unstable(feature = "nonpoison_rwlock", issue = "134645")] pub fn downgrade(s: Self) -> RwLockReadGuard<'rwlock, T> { let lock = s.lock; diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index 0a463f3f9c7e..1d52992ec2e0 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -813,8 +813,6 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { /// `downgrade` takes ownership of the `RwLockWriteGuard` and returns a [`RwLockReadGuard`]. /// /// ``` - /// #![feature(rwlock_downgrade)] - /// /// use std::sync::{RwLock, RwLockWriteGuard}; /// /// let rw = RwLock::new(0); @@ -831,8 +829,6 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { /// thread calling `downgrade` and any reads it performs after downgrading. /// /// ``` - /// #![feature(rwlock_downgrade)] - /// /// use std::sync::{Arc, RwLock, RwLockWriteGuard}; /// /// let rw = Arc::new(RwLock::new(1)); @@ -863,7 +859,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { /// # let final_check = rw.read().unwrap(); /// # assert_eq!(*final_check, 3); /// ``` - #[unstable(feature = "rwlock_downgrade", issue = "128203")] + #[stable(feature = "rwlock_downgrade", since = "CURRENT_RUSTC_VERSION")] pub fn downgrade(s: Self) -> RwLockReadGuard<'rwlock, T> { let lock = s.lock; diff --git a/library/std/tests/sync/lib.rs b/library/std/tests/sync/lib.rs index f874c2ba3895..d44a4d693574 100644 --- a/library/std/tests/sync/lib.rs +++ b/library/std/tests/sync/lib.rs @@ -4,7 +4,6 @@ #![feature(once_cell_try)] #![feature(lock_value_accessors)] #![feature(reentrant_lock)] -#![feature(rwlock_downgrade)] #![feature(std_internals)] #![feature(sync_nonpoison)] #![feature(nonpoison_mutex)] From fa9162d06fe101ecb5301146281882341fded5ec Mon Sep 17 00:00:00 2001 From: Jynn Nelson Date: Tue, 7 Oct 2025 10:56:02 -0400 Subject: [PATCH 02/17] Allow printing a fully-qualified path in `def_path_str` Previously, the local crate would always be printed as a leading `crate::`. Allow resolving it to the crate name instead. This allows printing a fully qualified path with: ```rust let qualified_name = with_no_visible_paths!(with_resolve_crate_name!( with_no_trimmed_paths!(tcx.def_path_str(def_id)) )); ``` I found this useful for an out-of-tree rustc-driver. I do not currently have a usecase in mind upstream; I'm ok if you don't want this PR for that reason. This does not currently have tests. I am not aware of an easy way to test def-id printing, since it requires having access to a TyCtxt. --- compiler/rustc_middle/src/ty/print/pretty.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 8f7c8170f7ad..978345d13f1e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -31,6 +31,7 @@ use crate::ty::{ thread_local! { static FORCE_IMPL_FILENAME_LINE: Cell = const { Cell::new(false) }; + static SHOULD_PREFIX_WITH_CRATE_NAME: Cell = const { Cell::new(false) }; static SHOULD_PREFIX_WITH_CRATE: Cell = const { Cell::new(false) }; static NO_TRIMMED_PATH: Cell = const { Cell::new(false) }; static FORCE_TRIMMED_PATH: Cell = const { Cell::new(false) }; @@ -98,7 +99,18 @@ define_helper!( /// cycle errors, this can result in extra or suboptimal error output, /// so this variable disables that check. fn with_forced_impl_filename_line(ForcedImplGuard, FORCE_IMPL_FILENAME_LINE); + /// Adds the crate name prefix to paths where appropriate. + /// Unlike `with_crate_prefix`, this unconditionally uses `tcx.crate_name` instead of sometimes + /// using `crate::` for local items. + /// + /// Overrides `with_crate_prefix`. + + // This function is not currently used in-tree, but it's used by a downstream rustc-driver in + // Ferrocene. Please check with them before removing it. + fn with_resolve_crate_name(CrateNamePrefixGuard, SHOULD_PREFIX_WITH_CRATE_NAME); /// Adds the `crate::` prefix to paths where appropriate. + /// + /// Ignored if `with_resolve_crate_name` is active. fn with_crate_prefix(CratePrefixGuard, SHOULD_PREFIX_WITH_CRATE); /// Prevent path trimming if it is turned on. Path trimming affects `Display` impl /// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`, @@ -2313,7 +2325,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> { self.empty_path = true; - if cnum == LOCAL_CRATE { + if cnum == LOCAL_CRATE && !with_resolve_crate_name() { if self.tcx.sess.at_least_rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. if with_crate_prefix() { From 4dfbf116443c8cd16135a95c15bae60857bd891a Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 14 Oct 2025 11:31:32 +0200 Subject: [PATCH 03/17] cleanup ErrorGuaranteed handling --- .../rustc_hir_analysis/src/check/wfcheck.rs | 4 +- .../rustc_hir_analysis/src/coherence/mod.rs | 8 ++-- .../rustc_hir_analysis/src/impl_wf_check.rs | 37 +++++-------------- compiler/rustc_hir_typeck/src/expr.rs | 4 +- 4 files changed, 16 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 7921e34ae4bd..6e537c668843 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1651,9 +1651,7 @@ fn check_method_receiver<'tcx>( // If the receiver already has errors reported, consider it valid to avoid // unnecessary errors (#58712). - if receiver_ty.references_error() { - return Ok(()); - } + receiver_ty.error_reported()?; let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers() { Some(ArbitrarySelfTypesLevel::WithPointers) diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index ed8f78216ff2..fbb442440bea 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -39,9 +39,7 @@ fn check_impl<'tcx>( // Skip impls where one of the self type is an error type. // This occurs with e.g., resolve failures (#30589). - if trait_ref.references_error() { - return Ok(()); - } + trait_ref.error_reported()?; enforce_trait_manually_implementable(tcx, impl_def_id, trait_ref.def_id, trait_def) .and(enforce_empty_impls_for_marker_traits(tcx, impl_def_id, trait_ref.def_id, trait_def)) @@ -188,9 +186,9 @@ fn check_object_overlap<'tcx>( ) -> Result<(), ErrorGuaranteed> { let trait_def_id = trait_ref.def_id; - if trait_ref.references_error() { + if let Err(guar) = trait_ref.error_reported() { debug!("coherence: skipping impl {:?} with error {:?}", impl_def_id, trait_ref); - return Ok(()); + return Err(guar); } // check for overlap with the automatic `impl Trait for dyn Trait` diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index cbdc501291bc..19ba166fa42a 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -76,20 +76,10 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained( impl_def_id: LocalDefId, ) -> Result<(), ErrorGuaranteed> { let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity(); - if impl_self_ty.references_error() { - // Don't complain about unconstrained type params when self ty isn't known due to errors. - // (#36836) - tcx.dcx().span_delayed_bug( - tcx.def_span(impl_def_id), - format!( - "potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}", - ), - ); - // This is super fishy, but our current `rustc_hir_analysis::check_crate` pipeline depends on - // `type_of` having been called much earlier, and thus this value being read from cache. - // Compilation must continue in order for other important diagnostics to keep showing up. - return Ok(()); - } + + // Don't complain about unconstrained type params when self ty isn't known due to errors. + // (#36836) + impl_self_ty.error_reported()?; let impl_generics = tcx.generics_of(impl_def_id); let impl_predicates = tcx.predicates_of(impl_def_id); @@ -174,20 +164,11 @@ pub(crate) fn enforce_impl_non_lifetime_params_are_constrained( impl_def_id: LocalDefId, ) -> Result<(), ErrorGuaranteed> { let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity(); - if impl_self_ty.references_error() { - // Don't complain about unconstrained type params when self ty isn't known due to errors. - // (#36836) - tcx.dcx().span_delayed_bug( - tcx.def_span(impl_def_id), - format!( - "potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}", - ), - ); - // This is super fishy, but our current `rustc_hir_analysis::check_crate` pipeline depends on - // `type_of` having been called much earlier, and thus this value being read from cache. - // Compilation must continue in order for other important diagnostics to keep showing up. - return Ok(()); - } + + // Don't complain about unconstrained type params when self ty isn't known due to errors. + // (#36836) + impl_self_ty.error_reported()?; + let impl_generics = tcx.generics_of(impl_def_id); let impl_predicates = tcx.predicates_of(impl_def_id); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 1aaf02646c79..026bc35cfa06 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -685,9 +685,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); let ty = self.check_expr_with_expectation_and_needs(oprnd, hint, Needs::maybe_mut_place(mutbl)); + if let Err(guar) = ty.error_reported() { + return Ty::new_error(self.tcx, guar); + } match kind { - _ if ty.references_error() => Ty::new_misc_error(self.tcx), hir::BorrowKind::Raw => { self.check_named_place_expr(oprnd); Ty::new_ptr(self.tcx, ty, mutbl) From 3941b4299309df315acbdb97be3520c670558860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Tue, 14 Oct 2025 15:21:27 +0200 Subject: [PATCH 04/17] return spans out of is_doc_comment to reduce reliance on .span() on attrs --- compiler/rustc_ast/src/attr/mod.rs | 11 ++++++----- compiler/rustc_attr_parsing/src/attributes/util.rs | 3 ++- compiler/rustc_hir/src/hir.rs | 10 +++++++--- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_query_system/src/ich/impls_syntax.rs | 2 +- compiler/rustc_resolve/src/rustdoc.rs | 3 +-- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/passes/propagate_doc_cfg.rs | 2 +- .../clippy/clippy_lints/src/four_forward_slashes.rs | 2 +- .../clippy_lints/src/undocumented_unsafe_blocks.rs | 2 +- 10 files changed, 22 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 6ada93b4c89b..901b645b8c4e 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -86,10 +86,10 @@ impl AttributeExt for Attribute { /// Returns `true` if it is a sugared doc comment (`///` or `//!` for example). /// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not /// a doc comment) will return `false`. - fn is_doc_comment(&self) -> bool { + fn is_doc_comment(&self) -> Option { match self.kind { - AttrKind::Normal(..) => false, - AttrKind::DocComment(..) => true, + AttrKind::Normal(..) => None, + AttrKind::DocComment(..) => Some(self.span), } } @@ -776,7 +776,7 @@ pub trait AttributeExt: Debug { /// Returns `true` if it is a sugared doc comment (`///` or `//!` for example). /// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not /// a doc comment) will return `false`. - fn is_doc_comment(&self) -> bool; + fn is_doc_comment(&self) -> Option; #[inline] fn has_name(&self, name: Symbol) -> bool { @@ -863,8 +863,9 @@ impl Attribute { AttributeExt::path_matches(self, name) } + // on ast attributes we return a bool since that's what most code already expects pub fn is_doc_comment(&self) -> bool { - AttributeExt::is_doc_comment(self) + AttributeExt::is_doc_comment(self).is_some() } #[inline] diff --git a/compiler/rustc_attr_parsing/src/attributes/util.rs b/compiler/rustc_attr_parsing/src/attributes/util.rs index 62b72798e969..520fd9da7c2a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/util.rs +++ b/compiler/rustc_attr_parsing/src/attributes/util.rs @@ -28,7 +28,8 @@ pub fn parse_version(s: Symbol) -> Option { } pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool { - attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name)) + attr.is_doc_comment().is_some() + || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name)) } pub fn is_doc_alias_attrs_contain_symbol<'tcx, T: AttributeExt + 'tcx>( diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index bc1c47e95c3a..7886cce5cdd4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1304,8 +1304,12 @@ impl AttributeExt for Attribute { } #[inline] - fn is_doc_comment(&self) -> bool { - matches!(self, Attribute::Parsed(AttributeKind::DocComment { .. })) + fn is_doc_comment(&self) -> Option { + if let Attribute::Parsed(AttributeKind::DocComment { span, .. }) = self { + Some(*span) + } else { + None + } } #[inline] @@ -1425,7 +1429,7 @@ impl Attribute { } #[inline] - pub fn is_doc_comment(&self) -> bool { + pub fn is_doc_comment(&self) -> Option { AttributeExt::is_doc_comment(self) } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8a525eb11f7b..183b23418745 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -391,7 +391,7 @@ pub struct MissingDoc; impl_lint_pass!(MissingDoc => [MISSING_DOCS]); fn has_doc(attr: &hir::Attribute) -> bool { - if attr.is_doc_comment() { + if attr.is_doc_comment().is_some() { return true; } diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs index 1dcd5d9058f4..044b97c2fea1 100644 --- a/compiler/rustc_query_system/src/ich/impls_syntax.rs +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -22,7 +22,7 @@ impl<'a> HashStable> for [hir::Attribute] { let filtered: SmallVec<[&hir::Attribute; 8]> = self .iter() .filter(|attr| { - !attr.is_doc_comment() + attr.is_doc_comment().is_none() // FIXME(jdonszelmann) have a better way to handle ignored attrs && !attr.ident().is_some_and(|ident| hcx.is_ignored_attr(ident.name)) }) diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 804792c6f286..944311a85824 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -214,8 +214,7 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>( for (attr, item_id) in attrs { if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() { let doc = beautify_doc_string(doc_str, comment_kind); - let (span, kind, from_expansion) = if attr.is_doc_comment() { - let span = attr.span(); + let (span, kind, from_expansion) = if let Some(span) = attr.is_doc_comment() { (span, DocFragmentKind::SugaredDoc, span.from_expansion()) } else { let attr_span = attr.span(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4fd8d245089e..46717367d83b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2719,7 +2719,7 @@ fn add_without_unwanted_attributes<'hir>( import_parent: Option, ) { for attr in new_attrs { - if attr.is_doc_comment() { + if attr.is_doc_comment().is_some() { attrs.push((Cow::Borrowed(attr), import_parent)); continue; } diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index d5b20f2b9410..c0b48ab51c7e 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -65,7 +65,7 @@ fn filter_non_cfg_tokens_from_list(args_tokens: &TokenStream) -> Vec /// it and put them into `attrs`. fn add_only_cfg_attributes(attrs: &mut Vec, new_attrs: &[Attribute]) { for attr in new_attrs { - if attr.is_doc_comment() { + if attr.is_doc_comment().is_some() { continue; } let mut attr = attr.clone(); diff --git a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs index a7b0edeb7991..5a0cee40a155 100644 --- a/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs +++ b/src/tools/clippy/clippy_lints/src/four_forward_slashes.rs @@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes { .tcx .hir_attrs(item.hir_id()) .iter() - .filter(|i| i.is_doc_comment()) + .filter(|i| i.is_doc_comment().is_some()) .fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span())); let (Some(file), _, _, end_line, _) = sm.span_to_location_info(span) else { return; diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index ba0d4de5f3b3..751e9b003427 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -475,7 +475,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool { fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span { span.to(cx.tcx.hir_attrs(hir_id).iter().fold(span, |acc, attr| { - if attr.is_doc_comment() { + if attr.is_doc_comment().is_some() { return acc; } acc.to(attr.span()) From 0935df7829c466f8ef94248429095ea79dc0fa73 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 15 Oct 2025 09:05:09 +0800 Subject: [PATCH 05/17] Fix ICE when using contracts on async functions --- compiler/rustc_builtin_macros/src/contracts.rs | 8 ++++++++ .../contracts/async-fn-contract-ice-145333.rs | 10 ++++++++++ .../async-fn-contract-ice-145333.stderr | 17 +++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 tests/ui/contracts/async-fn-contract-ice-145333.rs create mode 100644 tests/ui/contracts/async-fn-contract-ice-145333.stderr diff --git a/compiler/rustc_builtin_macros/src/contracts.rs b/compiler/rustc_builtin_macros/src/contracts.rs index 6a24af361fe7..13c63268e1e8 100644 --- a/compiler/rustc_builtin_macros/src/contracts.rs +++ b/compiler/rustc_builtin_macros/src/contracts.rs @@ -71,6 +71,14 @@ fn expand_contract_clause( .span_err(attr_span, "contract annotations can only be used on functions")); } + // Contracts are not yet supported on async/gen functions + if new_tts.iter().any(|tt| is_kw(tt, kw::Async) || is_kw(tt, kw::Gen)) { + return Err(ecx.sess.dcx().span_err( + attr_span, + "contract annotations are not yet supported on async or gen functions", + )); + } + // Found the `fn` keyword, now find either the `where` token or the function body. let next_tt = loop { let Some(tt) = cursor.next() else { diff --git a/tests/ui/contracts/async-fn-contract-ice-145333.rs b/tests/ui/contracts/async-fn-contract-ice-145333.rs new file mode 100644 index 000000000000..a6de8a786af9 --- /dev/null +++ b/tests/ui/contracts/async-fn-contract-ice-145333.rs @@ -0,0 +1,10 @@ +//@ compile-flags: --crate-type=lib +//@ edition: 2021 +#![feature(contracts)] +//~^ WARN the feature `contracts` is incomplete + +#[core::contracts::ensures(|ret| *ret)] +//~^ ERROR contract annotations are not yet supported on async or gen functions +async fn _always_true(b: bool) -> bool { + b +} diff --git a/tests/ui/contracts/async-fn-contract-ice-145333.stderr b/tests/ui/contracts/async-fn-contract-ice-145333.stderr new file mode 100644 index 000000000000..77f5379e6fb5 --- /dev/null +++ b/tests/ui/contracts/async-fn-contract-ice-145333.stderr @@ -0,0 +1,17 @@ +error: contract annotations are not yet supported on async or gen functions + --> $DIR/async-fn-contract-ice-145333.rs:6:1 + | +LL | #[core::contracts::ensures(|ret| *ret)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/async-fn-contract-ice-145333.rs:3:12 + | +LL | #![feature(contracts)] + | ^^^^^^^^^ + | + = note: see issue #128044 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted + From 491bc5008c59a7ee16e96a3e4e7d2b52e108902e Mon Sep 17 00:00:00 2001 From: ltdk Date: Tue, 14 Oct 2025 20:39:39 -0400 Subject: [PATCH 06/17] const mem::drop --- library/core/src/mem/mod.rs | 9 +++- .../traits/next-solver/alias-bound-unsound.rs | 6 ++- .../next-solver/alias-bound-unsound.stderr | 46 +++++++++---------- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index c484551187cc..a53726928477 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -6,7 +6,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::alloc::Layout; -use crate::marker::DiscriminantKind; +use crate::marker::{Destruct, DiscriminantKind}; use crate::panic::const_assert; use crate::{clone, cmp, fmt, hash, intrinsics, ptr}; @@ -958,8 +958,13 @@ pub const fn replace(dest: &mut T, src: T) -> T { /// [`RefCell`]: crate::cell::RefCell #[inline] #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_destruct", issue = "133214")] #[rustc_diagnostic_item = "mem_drop"] -pub fn drop(_x: T) {} +pub const fn drop(_x: T) +where + T: [const] Destruct, +{ +} /// Bitwise-copies a value. /// diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs index 0236826c3ed2..57fc88d87cf6 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs @@ -4,6 +4,10 @@ #![feature(trivial_bounds)] +// we use identity instead of drop because the presence of [const] Destruct means that there +// are additional bounds on the function, which result in additional errors +use std::convert::identity; + trait Foo { type Item: Copy where @@ -21,7 +25,7 @@ impl Foo for () { fn main() { let x = String::from("hello, world"); - drop(<() as Foo>::copy_me(&x)); + let _ = identity(<() as Foo>::copy_me(&x)); //~^ ERROR overflow evaluating the requirement `String <: <() as Foo>::Item` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed` //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed` diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr index 7e3737d120bf..1079c27fa815 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr @@ -1,11 +1,11 @@ error[E0275]: overflow evaluating the requirement `String: Copy` - --> $DIR/alias-bound-unsound.rs:18:38 + --> $DIR/alias-bound-unsound.rs:22:38 | LL | type Item = String where String: Copy; | ^^^^ | note: the requirement `String: Copy` appears on the `impl`'s associated type `Item` but not on the corresponding trait's associated type - --> $DIR/alias-bound-unsound.rs:8:10 + --> $DIR/alias-bound-unsound.rs:12:10 | LL | trait Foo { | --- in this trait @@ -13,50 +13,50 @@ LL | type Item: Copy | ^^^^ this trait's associated type doesn't have the requirement `String: Copy` error[E0275]: overflow evaluating the requirement `String <: <() as Foo>::Item` - --> $DIR/alias-bound-unsound.rs:24:31 + --> $DIR/alias-bound-unsound.rs:28:43 | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^ +LL | let _ = identity(<() as Foo>::copy_me(&x)); + | ^^ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` - --> $DIR/alias-bound-unsound.rs:24:10 + --> $DIR/alias-bound-unsound.rs:28:22 | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _ = identity(<() as Foo>::copy_me(&x)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` - --> $DIR/alias-bound-unsound.rs:24:10 + --> $DIR/alias-bound-unsound.rs:28:22 | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _ = identity(<() as Foo>::copy_me(&x)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0275]: overflow evaluating the requirement `&<() as Foo>::Item well-formed` - --> $DIR/alias-bound-unsound.rs:24:31 + --> $DIR/alias-bound-unsound.rs:28:43 | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^ +LL | let _ = identity(<() as Foo>::copy_me(&x)); + | ^^ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item well-formed` - --> $DIR/alias-bound-unsound.rs:24:10 + --> $DIR/alias-bound-unsound.rs:28:22 | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _ = identity(<() as Foo>::copy_me(&x)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` - --> $DIR/alias-bound-unsound.rs:24:10 + --> $DIR/alias-bound-unsound.rs:28:22 | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _ = identity(<() as Foo>::copy_me(&x)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` - --> $DIR/alias-bound-unsound.rs:24:31 + --> $DIR/alias-bound-unsound.rs:28:43 | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^ +LL | let _ = identity(<() as Foo>::copy_me(&x)); + | ^^ error: aborting due to 8 previous errors From 07df2adbdfd897a6dad194d06cc6b43db78cb2fb Mon Sep 17 00:00:00 2001 From: zhetaicheleba Date: Wed, 15 Oct 2025 14:23:28 +0800 Subject: [PATCH 07/17] Fix some comments Signed-off-by: zhetaicheleba --- compiler/rustc_attr_parsing/src/attributes/mod.rs | 2 +- compiler/rustc_data_structures/src/graph/scc/mod.rs | 2 +- compiler/rustc_sanitizers/src/cfi/typeid/mod.rs | 2 +- .../src/error_reporting/traits/on_unimplemented.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 8dbf4c0ef32e..639c75d7c5e4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -302,7 +302,7 @@ pub(crate) trait CombineAttributeParser: 'static { type Item; /// A function that converts individual items (of type [`Item`](Self::Item)) into the final attribute. /// - /// For example, individual representations fomr `#[repr(...)]` attributes into an `AttributeKind::Repr(x)`, + /// For example, individual representations from `#[repr(...)]` attributes into an `AttributeKind::Repr(x)`, /// where `x` is a vec of these individual reprs. const CONVERT: ConvertFn; diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index 518817ea0f53..1882e6e835a4 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -289,7 +289,7 @@ enum NodeState { #[derive(Copy, Clone, Debug)] enum WalkReturn { /// The walk found a cycle, but the entire component is not known to have - /// been fully walked yet. We only know the minimum depth of this + /// been fully walked yet. We only know the minimum depth of this /// component in a minimum spanning tree of the graph. This component /// is tentatively represented by the state of the first node of this /// cycle we met, which is at `min_depth`. diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/mod.rs b/compiler/rustc_sanitizers/src/cfi/typeid/mod.rs index 5d1ee3d79788..3de0c3121256 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/mod.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/mod.rs @@ -21,7 +21,7 @@ bitflags! { const GENERALIZE_REPR_C = 2; /// Normalizes integers for compatibility with Clang /// `-fsanitize-cfi-icall-experimental-normalize-integers` option for cross-language LLVM - /// CFI and KCFI support. + /// CFI and KCFI support. const NORMALIZE_INTEGERS = 4; /// Do not perform self type erasure for attaching a secondary type id to methods with their /// concrete self so they can be used as function pointers. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 00c123981e1c..b7d470df0cf4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -309,7 +309,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { pub struct OnUnimplementedFormatString { /// Symbol of the format string, i.e. `"content"` symbol: Symbol, - ///The span of the format string, i.e. `"content"` + /// The span of the format string, i.e. `"content"` span: Span, is_diagnostic_namespace_variant: bool, } From efaeacfc96315137f1fe3aa3a92244618224411a Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 17 Jul 2025 09:10:37 +0000 Subject: [PATCH 08/17] revert: PR144016 - `MetaSized` does not always hold --- .../rustc_trait_selection/src/traits/util.rs | 7 --- ...st-size_of_val-align_of_val-extern-type.rs | 4 +- ...ize_of_val-align_of_val-extern-type.stderr | 38 +++++++++++--- tests/ui/extern/extern-types-size_of_val.rs | 5 +- .../ui/extern/extern-types-size_of_val.stderr | 39 ++++++++++++++ tests/ui/extern/extern-types-unsized.rs | 2 + tests/ui/extern/extern-types-unsized.stderr | 30 ++++++++++- tests/ui/extern/unsized-extern-derefmove.rs | 4 ++ .../ui/extern/unsized-extern-derefmove.stderr | 52 ++++++++++++++++++- .../layout/unconstrained-param-ice-137308.rs | 1 + .../unconstrained-param-ice-137308.stderr | 11 +++- tests/ui/nll/issue-50716.rs | 2 +- tests/ui/nll/issue-50716.stderr | 18 ++++++- ...ete-inference-issue-143992.current.stderr} | 4 +- ...mplete-inference-issue-143992.next.stderr} | 4 +- .../incomplete-inference-issue-143992.rs | 12 ++--- .../sized-hierarchy/overflow.current.stderr | 45 ++++++++++++++++ tests/ui/sized-hierarchy/overflow.rs | 7 ++- .../normalizes-to-is-not-productive.stderr | 7 +++ .../normalize/normalize-param-env-2.stderr | 19 ++++++- .../normalize-param-env-4.next.stderr | 16 +++++- .../resolve-impl-before-constrain-check.rs | 1 + ...resolve-impl-before-constrain-check.stderr | 11 +++- 23 files changed, 294 insertions(+), 45 deletions(-) create mode 100644 tests/ui/extern/extern-types-size_of_val.stderr rename tests/ui/sized-hierarchy/{incomplete-inference-issue-143992.current_sized_hierarchy.stderr => incomplete-inference-issue-143992.current.stderr} (80%) rename tests/ui/sized-hierarchy/{incomplete-inference-issue-143992.next_sized_hierarchy.stderr => incomplete-inference-issue-143992.next.stderr} (80%) create mode 100644 tests/ui/sized-hierarchy/overflow.current.stderr diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 335942d5bcc5..e1d1ad1b3765 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -383,13 +383,6 @@ pub fn sizedness_fast_path<'tcx>( _ => return false, }; - // FIXME(sized_hierarchy): this temporarily reverts the `sized_hierarchy` feature - // while a proper fix for `tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs` - // is pending a proper fix - if !tcx.features().sized_hierarchy() && matches!(sizedness, SizedTraitKind::MetaSized) { - return true; - } - if trait_pred.self_ty().has_trivial_sizedness(tcx, sizedness) { debug!("fast path -- trivial sizedness"); return true; diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs index fd3ed8f18265..55d430a08aad 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.rs @@ -8,8 +8,8 @@ extern "C" { } const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; -//~^ ERROR `extern type` does not have known layout +//~^ ERROR: the size for values of type `Opaque` cannot be known const _ALIGN: usize = unsafe { align_of_val(&4 as *const i32 as *const Opaque) }; -//~^ ERROR `extern type` does not have known layout +//~^ ERROR: the size for values of type `Opaque` cannot be known fn main() {} diff --git a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr index 23f7aaf538ed..825b9e941584 100644 --- a/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr +++ b/tests/ui/consts/const-size_of_val-align_of_val-extern-type.stderr @@ -1,15 +1,39 @@ -error[E0080]: `extern type` does not have known layout - --> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:31 +error[E0277]: the size for values of type `Opaque` cannot be known + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:10:43 | LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_SIZE` failed here + | ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Opaque` + | | + | required by a bound introduced by this call + | + = note: the trait bound `Opaque: MetaSized` is not satisfied +note: required by a bound in `std::intrinsics::size_of_val` + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL +help: consider borrowing here + | +LL | const _SIZE: usize = unsafe { size_of_val(&(&4 as *const i32 as *const Opaque)) }; + | ++ + +LL | const _SIZE: usize = unsafe { size_of_val(&mut (&4 as *const i32 as *const Opaque)) }; + | ++++++ + -error[E0080]: `extern type` does not have known layout - --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32 +error[E0277]: the size for values of type `Opaque` cannot be known + --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:45 | LL | const _ALIGN: usize = unsafe { align_of_val(&4 as *const i32 as *const Opaque) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `_ALIGN` failed here + | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Opaque` + | | + | required by a bound introduced by this call + | + = note: the trait bound `Opaque: MetaSized` is not satisfied +note: required by a bound in `std::intrinsics::align_of_val` + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL +help: consider borrowing here + | +LL | const _ALIGN: usize = unsafe { align_of_val(&(&4 as *const i32 as *const Opaque)) }; + | ++ + +LL | const _ALIGN: usize = unsafe { align_of_val(&mut (&4 as *const i32 as *const Opaque)) }; + | ++++++ + error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/extern-types-size_of_val.rs b/tests/ui/extern/extern-types-size_of_val.rs index 875ae9a535a7..6be33e90178f 100644 --- a/tests/ui/extern/extern-types-size_of_val.rs +++ b/tests/ui/extern/extern-types-size_of_val.rs @@ -1,8 +1,9 @@ -//@ check-pass #![feature(extern_types)] use std::mem::{align_of_val, size_of_val}; +// Check that calls to `size_of_val` and `align_of_val` with extern types are not accepted + extern "C" { type A; } @@ -11,5 +12,7 @@ fn main() { let x: &A = unsafe { &*(1usize as *const A) }; size_of_val(x); + //~^ ERROR: the size for values of type `A` cannot be known align_of_val(x); + //~^ ERROR: the size for values of type `A` cannot be known } diff --git a/tests/ui/extern/extern-types-size_of_val.stderr b/tests/ui/extern/extern-types-size_of_val.stderr new file mode 100644 index 000000000000..44282c3c99a1 --- /dev/null +++ b/tests/ui/extern/extern-types-size_of_val.stderr @@ -0,0 +1,39 @@ +error[E0277]: the size for values of type `A` cannot be known + --> $DIR/extern-types-size_of_val.rs:14:17 + | +LL | size_of_val(x); + | ----------- ^ the trait `MetaSized` is not implemented for `A` + | | + | required by a bound introduced by this call + | + = note: the trait bound `A: MetaSized` is not satisfied +note: required by a bound in `std::mem::size_of_val` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider borrowing here + | +LL | size_of_val(&x); + | + +LL | size_of_val(&mut x); + | ++++ + +error[E0277]: the size for values of type `A` cannot be known + --> $DIR/extern-types-size_of_val.rs:16:18 + | +LL | align_of_val(x); + | ------------ ^ the trait `MetaSized` is not implemented for `A` + | | + | required by a bound introduced by this call + | + = note: the trait bound `A: MetaSized` is not satisfied +note: required by a bound in `std::mem::align_of_val` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +help: consider borrowing here + | +LL | align_of_val(&x); + | + +LL | align_of_val(&mut x); + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/extern-types-unsized.rs b/tests/ui/extern/extern-types-unsized.rs index 94a222a7e7e0..6d6407fb0661 100644 --- a/tests/ui/extern/extern-types-unsized.rs +++ b/tests/ui/extern/extern-types-unsized.rs @@ -27,7 +27,9 @@ fn main() { assert_sized::>(); //~^ ERROR the size for values of type + //~| ERROR the size for values of type `A` cannot be known assert_sized::>>(); //~^ ERROR the size for values of type + //~| ERROR the size for values of type `A` cannot be known } diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr index a587d4dda55c..43dd9800d6d3 100644 --- a/tests/ui/extern/extern-types-unsized.stderr +++ b/tests/ui/extern/extern-types-unsized.stderr @@ -59,8 +59,21 @@ help: consider relaxing the implicit `Sized` restriction LL | fn assert_sized() {} | ++++++++ +error[E0277]: the size for values of type `A` cannot be known + --> $DIR/extern-types-unsized.rs:28:20 + | +LL | assert_sized::>(); + | ^^^^^^ doesn't have a known size + | + = help: the trait `MetaSized` is not implemented for `A` +note: required by a bound in `Bar` + --> $DIR/extern-types-unsized.rs:14:12 + | +LL | struct Bar { + | ^ required by this bound in `Bar` + error[E0277]: the size for values of type `A` cannot be known at compilation time - --> $DIR/extern-types-unsized.rs:31:20 + --> $DIR/extern-types-unsized.rs:32:20 | LL | assert_sized::>>(); | ^^^^^^^^^^^ doesn't have a size known at compile-time @@ -81,6 +94,19 @@ help: consider relaxing the implicit `Sized` restriction LL | fn assert_sized() {} | ++++++++ -error: aborting due to 4 previous errors +error[E0277]: the size for values of type `A` cannot be known + --> $DIR/extern-types-unsized.rs:32:20 + | +LL | assert_sized::>>(); + | ^^^^^^^^^^^ doesn't have a known size + | + = help: the trait `MetaSized` is not implemented for `A` +note: required by a bound in `Bar` + --> $DIR/extern-types-unsized.rs:14:12 + | +LL | struct Bar { + | ^ required by this bound in `Bar` + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/extern/unsized-extern-derefmove.rs b/tests/ui/extern/unsized-extern-derefmove.rs index 39597a12fe11..c02375266ab4 100644 --- a/tests/ui/extern/unsized-extern-derefmove.rs +++ b/tests/ui/extern/unsized-extern-derefmove.rs @@ -7,10 +7,14 @@ extern "C" { } unsafe fn make_device() -> Box { +//~^ ERROR the size for values of type `Device` cannot be known Box::from_raw(0 as *mut _) +//~^ ERROR the size for values of type `Device` cannot be known +//~| ERROR the size for values of type `Device` cannot be known } fn main() { let d: Device = unsafe { *make_device() }; //~^ ERROR the size for values of type `Device` cannot be known +//~| ERROR the size for values of type `Device` cannot be known } diff --git a/tests/ui/extern/unsized-extern-derefmove.stderr b/tests/ui/extern/unsized-extern-derefmove.stderr index c43184d94e17..a9efc2e66e3b 100644 --- a/tests/ui/extern/unsized-extern-derefmove.stderr +++ b/tests/ui/extern/unsized-extern-derefmove.stderr @@ -1,5 +1,43 @@ +error[E0277]: the size for values of type `Device` cannot be known + --> $DIR/unsized-extern-derefmove.rs:9:28 + | +LL | unsafe fn make_device() -> Box { + | ^^^^^^^^^^^ doesn't have a known size + | + = help: the trait `MetaSized` is not implemented for `Device` +note: required by a bound in `Box` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + +error[E0277]: the size for values of type `Device` cannot be known + --> $DIR/unsized-extern-derefmove.rs:11:19 + | +LL | Box::from_raw(0 as *mut _) + | ------------- ^^^^^^^^^^^ the trait `MetaSized` is not implemented for `Device` + | | + | required by a bound introduced by this call + | + = note: the trait bound `Device: MetaSized` is not satisfied +note: required by a bound in `Box::::from_raw` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL +help: consider borrowing here + | +LL | Box::from_raw(&(0 as *mut _)) + | ++ + +LL | Box::from_raw(&mut (0 as *mut _)) + | ++++++ + + +error[E0277]: the size for values of type `Device` cannot be known + --> $DIR/unsized-extern-derefmove.rs:11:5 + | +LL | Box::from_raw(0 as *mut _) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size + | + = help: the trait `MetaSized` is not implemented for `Device` +note: required by a bound in `Box` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + error[E0277]: the size for values of type `Device` cannot be known at compilation time - --> $DIR/unsized-extern-derefmove.rs:14:9 + --> $DIR/unsized-extern-derefmove.rs:17:9 | LL | let d: Device = unsafe { *make_device() }; | ^ doesn't have a size known at compile-time @@ -11,6 +49,16 @@ help: consider borrowing here LL | let d: &Device = unsafe { *make_device() }; | + -error: aborting due to 1 previous error +error[E0277]: the size for values of type `Device` cannot be known + --> $DIR/unsized-extern-derefmove.rs:17:31 + | +LL | let d: Device = unsafe { *make_device() }; + | ^^^^^^^^^^^^^ doesn't have a known size + | + = help: the trait `MetaSized` is not implemented for `Device` +note: required by a bound in `Box` + --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/layout/unconstrained-param-ice-137308.rs b/tests/ui/layout/unconstrained-param-ice-137308.rs index d05e6e1fd3f3..03b7e7599601 100644 --- a/tests/ui/layout/unconstrained-param-ice-137308.rs +++ b/tests/ui/layout/unconstrained-param-ice-137308.rs @@ -17,3 +17,4 @@ impl A for u8 { //~ ERROR: the type parameter `C` is not constrained #[rustc_layout(debug)] struct S([u8; ::B]); //~^ ERROR: the type has an unknown layout +//~| ERROR: type annotations needed diff --git a/tests/ui/layout/unconstrained-param-ice-137308.stderr b/tests/ui/layout/unconstrained-param-ice-137308.stderr index 615c131eb904..82cd1217c490 100644 --- a/tests/ui/layout/unconstrained-param-ice-137308.stderr +++ b/tests/ui/layout/unconstrained-param-ice-137308.stderr @@ -4,12 +4,19 @@ error[E0207]: the type parameter `C` is not constrained by the impl trait, self LL | impl A for u8 { | ^ unconstrained type parameter +error[E0282]: type annotations needed + --> $DIR/unconstrained-param-ice-137308.rs:18:16 + | +LL | struct S([u8; ::B]); + | ^^ cannot infer type for type parameter `C` + error: the type has an unknown layout --> $DIR/unconstrained-param-ice-137308.rs:18:1 | LL | struct S([u8; ::B]); | ^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0207, E0282. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/nll/issue-50716.rs b/tests/ui/nll/issue-50716.rs index 96168ebeaa16..76c6fc5e7b92 100644 --- a/tests/ui/nll/issue-50716.rs +++ b/tests/ui/nll/issue-50716.rs @@ -5,7 +5,7 @@ trait A { type X: ?Sized; } -fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) +fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) //~ ERROR where for<'b> &'b T: A, <&'static T as A>::X: Sized diff --git a/tests/ui/nll/issue-50716.stderr b/tests/ui/nll/issue-50716.stderr index 536f88085ded..edd7fd765dad 100644 --- a/tests/ui/nll/issue-50716.stderr +++ b/tests/ui/nll/issue-50716.stderr @@ -1,3 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/issue-50716.rs:8:27 + | +LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) + | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected trait `<<&'a T as A>::X as MetaSized>` + found trait `<<&'static T as A>::X as MetaSized>` +note: the lifetime `'a` as defined here... + --> $DIR/issue-50716.rs:8:8 + | +LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) + | ^^ + = note: ...does not necessarily outlive the static lifetime + error: lifetime may not live long enough --> $DIR/issue-50716.rs:13:14 | @@ -7,5 +22,6 @@ LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) LL | let _x = *s; | ^^ proving this value is `Sized` requires that `'a` must outlive `'static` -error: aborting due to 1 previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current_sized_hierarchy.stderr b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current.stderr similarity index 80% rename from tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current_sized_hierarchy.stderr rename to tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current.stderr index b904b784df73..cf56f42afc8a 100644 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current_sized_hierarchy.stderr +++ b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/incomplete-inference-issue-143992.rs:30:28 + --> $DIR/incomplete-inference-issue-143992.rs:27:28 | LL | let _x = T::Assoc::new(()); | ------------- ^^ expected `[u32; 1]`, found `()` @@ -7,7 +7,7 @@ LL | let _x = T::Assoc::new(()); | arguments to this function are incorrect | note: associated function defined here - --> $DIR/incomplete-inference-issue-143992.rs:21:8 + --> $DIR/incomplete-inference-issue-143992.rs:18:8 | LL | fn new(r: R) -> R { | ^^^ ---- diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next.stderr similarity index 80% rename from tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr rename to tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next.stderr index b904b784df73..cf56f42afc8a 100644 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr +++ b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/incomplete-inference-issue-143992.rs:30:28 + --> $DIR/incomplete-inference-issue-143992.rs:27:28 | LL | let _x = T::Assoc::new(()); | ------------- ^^ expected `[u32; 1]`, found `()` @@ -7,7 +7,7 @@ LL | let _x = T::Assoc::new(()); | arguments to this function are incorrect | note: associated function defined here - --> $DIR/incomplete-inference-issue-143992.rs:21:8 + --> $DIR/incomplete-inference-issue-143992.rs:18:8 | LL | fn new(r: R) -> R { | ^^^ ---- diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs index b9e65ed28393..a9c01a83bc37 100644 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs +++ b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs @@ -1,12 +1,9 @@ //@ compile-flags: --crate-type=lib -//@ revisions: current next current_sized_hierarchy next_sized_hierarchy +//@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) -//@[current] check-pass -//@[next] check-pass +//@[current] check-fail +//@[next] check-fail //@[next] compile-flags: -Znext-solver -//@[next_sized_hierarchy] compile-flags: -Znext-solver - -#![cfg_attr(any(current_sized_hierarchy, next_sized_hierarchy), feature(sized_hierarchy))] // Test that we avoid incomplete inference when normalizing. Without this, // `Trait`'s implicit `MetaSized` supertrait requires proving `T::Assoc<_>: MetaSized` @@ -28,6 +25,5 @@ where T::Assoc<[u32; 1]>: Clone, { let _x = T::Assoc::new(()); - //[next_sized_hierarchy]~^ ERROR mismatched types - //[current_sized_hierarchy]~^^ ERROR mismatched types +//~^ ERROR: mismatched types } diff --git a/tests/ui/sized-hierarchy/overflow.current.stderr b/tests/ui/sized-hierarchy/overflow.current.stderr new file mode 100644 index 000000000000..da58a6d2f7bf --- /dev/null +++ b/tests/ui/sized-hierarchy/overflow.current.stderr @@ -0,0 +1,45 @@ +error[E0275]: overflow evaluating the requirement `Element: MetaSized` + --> $DIR/overflow.rs:17:16 + | +LL | struct Element(> as ParseTokens>::Output); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: required for `Box` to implement `ParseTokens` + --> $DIR/overflow.rs:13:31 + | +LL | impl ParseTokens for Box { + | - ^^^^^^^^^^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `Box>` to implement `ParseTokens` + +error[E0275]: overflow evaluating the requirement `Box: ParseTokens` + --> $DIR/overflow.rs:19:22 + | +LL | impl ParseTokens for Element { + | ^^^^^^^ + | +note: required for `Box>` to implement `ParseTokens` + --> $DIR/overflow.rs:13:31 + | +LL | impl ParseTokens for Box { + | ----------- ^^^^^^^^^^^ ^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required because it appears within the type `Element` + --> $DIR/overflow.rs:17:8 + | +LL | struct Element(> as ParseTokens>::Output); + | ^^^^^^^ +note: required by a bound in `ParseTokens` + --> $DIR/overflow.rs:10:1 + | +LL | / trait ParseTokens { +LL | | type Output; +LL | | } + | |_^ required by this bound in `ParseTokens` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/sized-hierarchy/overflow.rs b/tests/ui/sized-hierarchy/overflow.rs index f8e5dd5d4029..31c2ca8a4917 100644 --- a/tests/ui/sized-hierarchy/overflow.rs +++ b/tests/ui/sized-hierarchy/overflow.rs @@ -1,13 +1,10 @@ //@ compile-flags: --crate-type=lib //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) -//@[current] check-pass +//@[current] check-fail //@[next] check-pass //@[next] compile-flags: -Znext-solver -// FIXME(sized_hierarchy): this is expected to fail in the old solver when there -// isn't a temporary revert of the `sized_hierarchy` feature - use std::marker::PhantomData; trait ParseTokens { @@ -18,6 +15,8 @@ impl ParseTokens for Box { } struct Element(> as ParseTokens>::Output); +//[current]~^ ERROR: overflow impl ParseTokens for Element { +//[current]~^ ERROR: overflow type Output = (); } diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr index 4934d8bf6fa0..4a87aa3e2f12 100644 --- a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr @@ -17,6 +17,13 @@ LL | impl Trait for T { | ----- ^^^^^^^^ ^ | | | unsatisfied trait bound introduced here +note: required by a bound in `Bound` + --> $DIR/normalizes-to-is-not-productive.rs:8:1 + | +LL | / trait Bound { +LL | | fn method(); +LL | | } + | |_^ required by this bound in `Bound` error[E0277]: the trait bound `Foo: Bound` is not satisfied --> $DIR/normalizes-to-is-not-productive.rs:47:19 diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr index d179c8059623..8d8909625ffc 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr @@ -19,6 +19,23 @@ error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: A` LL | Self::Assoc: A, | ^^^^ +error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: MetaSized` + --> $DIR/normalize-param-env-2.rs:24:22 + | +LL | Self::Assoc: A, + | ^^^^ + | +note: required by a bound in `A` + --> $DIR/normalize-param-env-2.rs:9:1 + | +LL | / trait A { +LL | | type Assoc; +LL | | +LL | | fn f() +... | +LL | | } + | |_^ required by this bound in `A` + error[E0275]: overflow evaluating the requirement `<() as A>::Assoc well-formed` --> $DIR/normalize-param-env-2.rs:24:22 | @@ -46,6 +63,6 @@ LL | where LL | Self::Assoc: A, | ^^^^ required by this bound in `A::f` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr index f5fd9ce9864c..9f7f74f94664 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr @@ -4,6 +4,20 @@ error[E0275]: overflow evaluating the requirement `::Assoc: Trait` LL | ::Assoc: Trait, | ^^^^^ -error: aborting due to 1 previous error +error[E0275]: overflow evaluating the requirement `::Assoc: MetaSized` + --> $DIR/normalize-param-env-4.rs:19:26 + | +LL | ::Assoc: Trait, + | ^^^^^ + | +note: required by a bound in `Trait` + --> $DIR/normalize-param-env-4.rs:7:1 + | +LL | / trait Trait { +LL | | type Assoc; +LL | | } + | |_^ required by this bound in `Trait` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.rs b/tests/ui/traits/resolve-impl-before-constrain-check.rs index 87f9c241e402..00005a720936 100644 --- a/tests/ui/traits/resolve-impl-before-constrain-check.rs +++ b/tests/ui/traits/resolve-impl-before-constrain-check.rs @@ -15,6 +15,7 @@ use foo::*; fn test() -> impl Sized { <() as Callable>::call() +//~^ ERROR type annotations needed } fn main() {} diff --git a/tests/ui/traits/resolve-impl-before-constrain-check.stderr b/tests/ui/traits/resolve-impl-before-constrain-check.stderr index e8e569ba625e..13fbfdb855cb 100644 --- a/tests/ui/traits/resolve-impl-before-constrain-check.stderr +++ b/tests/ui/traits/resolve-impl-before-constrain-check.stderr @@ -4,6 +4,13 @@ error[E0207]: the type parameter `V` is not constrained by the impl trait, self LL | impl Callable for () { | ^ unconstrained type parameter -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/resolve-impl-before-constrain-check.rs:17:6 + | +LL | <() as Callable>::call() + | ^^ cannot infer type for type parameter `V` -For more information about this error, try `rustc --explain E0207`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0207, E0282. +For more information about an error, try `rustc --explain E0207`. From 321a47eb2cce2b10fe65aa3a6cb981813b4386dc Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 17 Jul 2025 09:21:51 +0000 Subject: [PATCH 09/17] trait_sel: sizedness goals prefer alias candidates For sizedness, default and auto trait predicates, now prefer non-param candidates if any exist. As these traits do not have generic parameters, it never makes sense to prefer an non-alias candidate, as there can never be a more permissive candidate. --- compiler/rustc_middle/src/ty/context.rs | 8 + compiler/rustc_middle/src/ty/mod.rs | 2 +- .../src/solve/trait_goals.rs | 36 ++- .../src/traits/select/mod.rs | 29 +- compiler/rustc_type_ir/src/interner.rs | 2 + compiler/rustc_type_ir/src/solve/mod.rs | 24 ++ ...her-ranked-auto-trait-3.assumptions.stderr | 292 +++++++++++++++++ ...-ranked-auto-trait-3.no_assumptions.stderr | 304 +++++++++++++++++- .../async-await/higher-ranked-auto-trait-3.rs | 3 +- .../generic-associated-types/issue-93262.rs | 4 +- .../issue-93262.stderr | 19 ++ ...-method-resolution-opaque-type.next.stderr | 14 + ...e-method-resolution-opaque-type.old.stderr | 2 +- ...rm-before-method-resolution-opaque-type.rs | 6 +- tests/ui/nll/issue-50716.rs | 2 +- tests/ui/nll/issue-50716.stderr | 18 +- ...lete-inference-issue-143992.current.stderr | 17 - ...omplete-inference-issue-143992.next.stderr | 17 - .../incomplete-inference-issue-143992.rs | 4 +- 19 files changed, 722 insertions(+), 81 deletions(-) create mode 100644 tests/ui/async-await/higher-ranked-auto-trait-3.assumptions.stderr create mode 100644 tests/ui/generic-associated-types/issue-93262.stderr create mode 100644 tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr delete mode 100644 tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current.stderr delete mode 100644 tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next.stderr diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3c5c21a7a89c..de2b2e6c64f2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -521,6 +521,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.is_default_trait(def_id) } + fn is_sizedness_trait(self, def_id: DefId) -> bool { + self.is_sizedness_trait(def_id) + } + fn as_lang_item(self, def_id: DefId) -> Option { lang_item_to_solver_lang_item(self.lang_items().from_def_id(def_id)?) } @@ -1787,6 +1791,10 @@ impl<'tcx> TyCtxt<'tcx> { .any(|&default_trait| self.lang_items().get(default_trait) == Some(def_id)) } + pub fn is_sizedness_trait(self, def_id: DefId) -> bool { + matches!(self.as_lang_item(def_id), Some(LangItem::Sized | LangItem::MetaSized)) + } + /// Returns a range of the start/end indices specified with the /// `rustc_layout_scalar_valid_range` attribute. // FIXME(eddyb) this is an awkward spot for this method, maybe move it? diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ce4de6b95e0b..b6adc606b873 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -59,7 +59,7 @@ pub use rustc_type_ir::fast_reject::DeepRejectCtxt; )] use rustc_type_ir::inherent; pub use rustc_type_ir::relate::VarianceDiagInfo; -pub use rustc_type_ir::solve::SizedTraitKind; +pub use rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind}; pub use rustc_type_ir::*; #[allow(hidden_glob_reexports, unused_imports)] use rustc_type_ir::{InferCtxtLike, Interner}; diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index e790ecd595be..5edd281acefc 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -4,7 +4,7 @@ use rustc_type_ir::data_structures::IndexSet; use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::SolverTraitLangItem; -use rustc_type_ir::solve::{CanonicalResponse, SizedTraitKind}; +use rustc_type_ir::solve::{CandidatePreferenceMode, CanonicalResponse, SizedTraitKind}; use rustc_type_ir::{ self as ty, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode, Upcast as _, elaborate, @@ -1355,6 +1355,7 @@ where #[instrument(level = "debug", skip(self), ret)] pub(super) fn merge_trait_candidates( &mut self, + candidate_preference_mode: CandidatePreferenceMode, mut candidates: Vec>, failed_candidate_info: FailedCandidateInfo, ) -> Result<(CanonicalResponse, Option), NoSolution> { @@ -1380,6 +1381,24 @@ where return Ok((candidate.result, Some(TraitGoalProvenVia::Misc))); } + let potential_alias_bound_response = + candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound)).then(|| { + let alias_bounds: Vec<_> = candidates + .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound)) + .collect(); + if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) { + (response, Some(TraitGoalProvenVia::AliasBound)) + } else { + (self.bail_with_ambiguity(&alias_bounds), None) + } + }); + + if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker) + && let Some(alias_bound_response) = potential_alias_bound_response + { + return Ok(alias_bound_response); + } + // If there are non-global where-bounds, prefer where-bounds // (including global ones) over everything else. let has_non_global_where_bounds = candidates @@ -1427,15 +1446,8 @@ where }; } - if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound)) { - let alias_bounds: Vec<_> = candidates - .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound)) - .collect(); - return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) { - Ok((response, Some(TraitGoalProvenVia::AliasBound))) - } else { - Ok((self.bail_with_ambiguity(&alias_bounds), None)) - }; + if let Some(response) = potential_alias_bound_response { + return Ok(response); } self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates); @@ -1470,7 +1482,9 @@ where ) -> Result<(CanonicalResponse, Option), NoSolution> { let (candidates, failed_candidate_info) = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All); - self.merge_trait_candidates(candidates, failed_candidate_info) + let candidate_preference_mode = + CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id()); + self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info) } fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option, NoSolution>> { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index fb4f28412d42..5af16187e585 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -28,8 +28,9 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::TypeErrorToStringExt; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; use rustc_middle::ty::{ - self, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, SizedTraitKind, Ty, TyCtxt, - TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate, may_use_unstable_feature, + self, CandidatePreferenceMode, DeepRejectCtxt, GenericArgsRef, PolyProjectionPredicate, + SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate, + may_use_unstable_feature, }; use rustc_span::{Symbol, sym}; use tracing::{debug, instrument, trace}; @@ -474,7 +475,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } else { let has_non_region_infer = stack.obligation.predicate.has_non_region_infer(); - if let Some(candidate) = self.winnow_candidates(has_non_region_infer, candidates) { + let candidate_preference_mode = + CandidatePreferenceMode::compute(self.tcx(), stack.obligation.predicate.def_id()); + if let Some(candidate) = + self.winnow_candidates(has_non_region_infer, candidate_preference_mode, candidates) + { self.filter_reservation_impls(candidate) } else { Ok(None) @@ -1821,6 +1826,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn winnow_candidates( &mut self, has_non_region_infer: bool, + candidate_preference_mode: CandidatePreferenceMode, mut candidates: Vec>, ) -> Option> { if candidates.len() == 1 { @@ -1874,6 +1880,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> { break; } + let alias_bound = candidates + .iter() + .filter_map(|c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None }) + .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) }); + + if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker) { + match alias_bound { + Some(Some(index)) => return Some(ProjectionCandidate(index)), + Some(None) => {} + None => return None, + } + } + // The next highest priority is for non-global where-bounds. However, while we don't // prefer global where-clauses here, we do bail with ambiguity when encountering both // a global and a non-global where-clause. @@ -1907,10 +1926,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // fairly arbitrary but once again necessary for backwards compatibility. // If there are multiple applicable candidates which don't affect type inference, // choose the one with the lowest index. - let alias_bound = candidates - .iter() - .filter_map(|c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None }) - .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) }); match alias_bound { Some(Some(index)) => return Some(ProjectionCandidate(index)), Some(None) => {} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 4b6349e2f426..023dbd38d911 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -333,6 +333,8 @@ pub trait Interner: fn is_default_trait(self, def_id: Self::TraitId) -> bool; + fn is_sizedness_trait(self, def_id: Self::TraitId) -> bool; + fn as_lang_item(self, def_id: Self::DefId) -> Option; fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option; diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 9d9a8e498478..f155d45bc0a6 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -109,6 +109,30 @@ pub struct QueryInput { impl Eq for QueryInput {} +/// Which trait candidates should be preferred over other candidates? By default, prefer where +/// bounds over alias bounds. For marker traits, prefer alias bounds over where bounds. +#[derive(Clone, Copy, Debug)] +pub enum CandidatePreferenceMode { + /// Prefers where bounds over alias bounds + Default, + /// Prefers alias bounds over where bounds + Marker, +} + +impl CandidatePreferenceMode { + /// Given `trait_def_id`, which candidate preference mode should be used? + pub fn compute(cx: I, trait_id: I::TraitId) -> CandidatePreferenceMode { + let is_sizedness_or_auto_or_default_goal = cx.is_sizedness_trait(trait_id) + || cx.trait_is_auto(trait_id) + || cx.is_default_trait(trait_id); + if is_sizedness_or_auto_or_default_goal { + CandidatePreferenceMode::Marker + } else { + CandidatePreferenceMode::Default + } + } +} + /// Possible ways the given goal can be proven. #[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)] pub enum CandidateSource { diff --git a/tests/ui/async-await/higher-ranked-auto-trait-3.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-3.assumptions.stderr new file mode 100644 index 000000000000..be978f19d7ee --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-3.assumptions.stderr @@ -0,0 +1,292 @@ +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:54:5 + | +LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:54:5 + | +LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:63:5 + | +LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:63:5 + | +LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:40:31 + | +LL | impl IterCaller for UseIter + | ^^^^^^^^^^^^^^^^^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:46:5 + | +LL | type Future1<'cx> = impl Future + Send + 'cx + | ^^^^^^^^^^^^^^^^^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:50:5 + | +LL | type Future2<'cx> = impl Future + Send + 'cx + | ^^^^^^^^^^^^^^^^^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:54:50 + | +LL | fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> + | ^^^^^^^^^^^^^^^^^^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:63:50 + | +LL | fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> + | ^^^^^^^^^^^^^^^^^^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: higher-ranked subtype error + --> $DIR/higher-ranked-auto-trait-3.rs:54:5 + | +LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + +error: higher-ranked subtype error + --> $DIR/higher-ranked-auto-trait-3.rs:54:5 + | +LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:58:9 + | +LL | / async { +LL | | self.fi_1.get_iter(cx).await; +LL | | } + | |_________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:58:9 + | +LL | / async { +LL | | self.fi_1.get_iter(cx).await; +LL | | } + | |_________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: higher-ranked subtype error + --> $DIR/higher-ranked-auto-trait-3.rs:63:5 + | +LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + +error: higher-ranked subtype error + --> $DIR/higher-ranked-auto-trait-3.rs:63:5 + | +LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:67:9 + | +LL | / async { +LL | | self.fi_2.get_iter(cx).await; +LL | | } + | |_________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:67:9 + | +LL | / async { +LL | | self.fi_2.get_iter(cx).await; +LL | | } + | |_________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 17 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr index c5c98ac807ea..1c5aa3af7d1e 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr @@ -1,5 +1,305 @@ error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:66:9 + --> $DIR/higher-ranked-auto-trait-3.rs:54:5 + | +LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:54:5 + | +LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:63:5 + | +LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:63:5 + | +LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:40:31 + | +LL | impl IterCaller for UseIter + | ^^^^^^^^^^^^^^^^^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:46:5 + | +LL | type Future1<'cx> = impl Future + Send + 'cx + | ^^^^^^^^^^^^^^^^^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:50:5 + | +LL | type Future2<'cx> = impl Future + Send + 'cx + | ^^^^^^^^^^^^^^^^^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:54:50 + | +LL | fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> + | ^^^^^^^^^^^^^^^^^^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:63:50 + | +LL | fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> + | ^^^^^^^^^^^^^^^^^^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: higher-ranked subtype error + --> $DIR/higher-ranked-auto-trait-3.rs:54:5 + | +LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + +error: higher-ranked subtype error + --> $DIR/higher-ranked-auto-trait-3.rs:54:5 + | +LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:58:9 + | +LL | / async { +LL | | self.fi_1.get_iter(cx).await; +LL | | } + | |_________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:58:9 + | +LL | / async { +LL | | self.fi_1.get_iter(cx).await; +LL | | } + | |_________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:58:9 + | +LL | / async { +LL | | self.fi_1.get_iter(cx).await; +LL | | } + | |_________^ + | + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: higher-ranked subtype error + --> $DIR/higher-ranked-auto-trait-3.rs:63:5 + | +LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + +error: higher-ranked subtype error + --> $DIR/higher-ranked-auto-trait-3.rs:63:5 + | +LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> +LL | | where +LL | | 's: 'cx, + | |________________^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:67:9 + | +LL | / async { +LL | | self.fi_2.get_iter(cx).await; +LL | | } + | |_________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:67:9 + | +LL | / async { +LL | | self.fi_2.get_iter(cx).await; +LL | | } + | |_________^ + | +note: the lifetime `'cx` defined here... + --> $DIR/higher-ranked-auto-trait-3.rs:43:13 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^^ +note: ...must outlive the lifetime `'s` defined here + --> $DIR/higher-ranked-auto-trait-3.rs:43:9 + | +LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + | ^^ + = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:67:9 | LL | / async { LL | | self.fi_2.get_iter(cx).await; @@ -8,5 +308,5 @@ LL | | } | = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) -error: aborting due to 1 previous error +error: aborting due to 19 previous errors diff --git a/tests/ui/async-await/higher-ranked-auto-trait-3.rs b/tests/ui/async-await/higher-ranked-auto-trait-3.rs index d42d42366805..2ab986a097a6 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-3.rs +++ b/tests/ui/async-await/higher-ranked-auto-trait-3.rs @@ -2,7 +2,8 @@ //@ edition: 2021 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass +//@[assumptions] check-fail +//@[assumptions] known-bug: #110338 //@[no_assumptions] known-bug: #110338 #![feature(impl_trait_in_assoc_type)] diff --git a/tests/ui/generic-associated-types/issue-93262.rs b/tests/ui/generic-associated-types/issue-93262.rs index c4a6f0dbaa07..c964606fef0b 100644 --- a/tests/ui/generic-associated-types/issue-93262.rs +++ b/tests/ui/generic-associated-types/issue-93262.rs @@ -1,4 +1,4 @@ -//@ check-pass +//@ check-fail pub trait Trait { type Assoc<'a> where Self: 'a; @@ -11,7 +11,7 @@ where pub struct Type; -impl Foo for Type +impl Foo for Type //~ ERROR: the parameter type `T` may not live long enough where for<'a> T::Assoc<'a>: Clone {} diff --git a/tests/ui/generic-associated-types/issue-93262.stderr b/tests/ui/generic-associated-types/issue-93262.stderr new file mode 100644 index 000000000000..91d3e65f3de8 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-93262.stderr @@ -0,0 +1,19 @@ +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/issue-93262.rs:14:16 + | +LL | impl Foo for Type + | ^^^^^^ + | | + | the parameter type `T` must be valid for lifetime `'a`... + | ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/issue-93262.rs:9:27 + | +LL | for<'a> T::Assoc<'a>: Clone + | ^^^^^ + = help: consider adding an explicit lifetime bound `T: 'a`... + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr new file mode 100644 index 000000000000..723dd097f9b9 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `>::Out<_>` + --> $DIR/norm-before-method-resolution-opaque-type.rs:25:9 + | +LL | let x = *x; + | ^ + | +help: consider giving `x` an explicit type, where the placeholders `_` are specified + | +LL | let x: <_ as Trait<'static>>::Out<_> = *x; + | +++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr index 79ded34d9cd9..d8b94fd4f7d1 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `*x` which is behind a shared reference - --> $DIR/norm-before-method-resolution-opaque-type.rs:22:13 + --> $DIR/norm-before-method-resolution-opaque-type.rs:25:13 | LL | let x = *x; | ^^ move occurs because `*x` has type `>::Out`, which does not implement the `Copy` trait diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs index f881fcb779fa..55e99171ea63 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs @@ -1,6 +1,9 @@ //@ revisions: old next //@[next] compile-flags: -Znext-solver -//@[next] check-pass + +// In the next solver, the opaque was previously defined by using the where-bound when checking +// whether the alias is `Sized`, constraining the opaque. Instead, the alias-bound is now used, +// which means the opaque is never constrained. #![feature(type_alias_impl_trait)] trait Trait<'a> { @@ -20,6 +23,7 @@ where for<'a> >::Out<()>: Copy, { let x = *x; //[old]~ ERROR: cannot move out of `*x` + //[next]~^ ERROR: type annotations needed todo!(); } diff --git a/tests/ui/nll/issue-50716.rs b/tests/ui/nll/issue-50716.rs index 76c6fc5e7b92..96168ebeaa16 100644 --- a/tests/ui/nll/issue-50716.rs +++ b/tests/ui/nll/issue-50716.rs @@ -5,7 +5,7 @@ trait A { type X: ?Sized; } -fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) //~ ERROR +fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) where for<'b> &'b T: A, <&'static T as A>::X: Sized diff --git a/tests/ui/nll/issue-50716.stderr b/tests/ui/nll/issue-50716.stderr index edd7fd765dad..536f88085ded 100644 --- a/tests/ui/nll/issue-50716.stderr +++ b/tests/ui/nll/issue-50716.stderr @@ -1,18 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/issue-50716.rs:8:27 - | -LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) - | ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch - | - = note: expected trait `<<&'a T as A>::X as MetaSized>` - found trait `<<&'static T as A>::X as MetaSized>` -note: the lifetime `'a` as defined here... - --> $DIR/issue-50716.rs:8:8 - | -LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) - | ^^ - = note: ...does not necessarily outlive the static lifetime - error: lifetime may not live long enough --> $DIR/issue-50716.rs:13:14 | @@ -22,6 +7,5 @@ LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) LL | let _x = *s; | ^^ proving this value is `Sized` requires that `'a` must outlive `'static` -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current.stderr b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current.stderr deleted file mode 100644 index cf56f42afc8a..000000000000 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/incomplete-inference-issue-143992.rs:27:28 - | -LL | let _x = T::Assoc::new(()); - | ------------- ^^ expected `[u32; 1]`, found `()` - | | - | arguments to this function are incorrect - | -note: associated function defined here - --> $DIR/incomplete-inference-issue-143992.rs:18:8 - | -LL | fn new(r: R) -> R { - | ^^^ ---- - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next.stderr b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next.stderr deleted file mode 100644 index cf56f42afc8a..000000000000 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/incomplete-inference-issue-143992.rs:27:28 - | -LL | let _x = T::Assoc::new(()); - | ------------- ^^ expected `[u32; 1]`, found `()` - | | - | arguments to this function are incorrect - | -note: associated function defined here - --> $DIR/incomplete-inference-issue-143992.rs:18:8 - | -LL | fn new(r: R) -> R { - | ^^^ ---- - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs index a9c01a83bc37..44453b65e7cd 100644 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs +++ b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs @@ -1,8 +1,7 @@ +//@ check-pass //@ compile-flags: --crate-type=lib //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) -//@[current] check-fail -//@[next] check-fail //@[next] compile-flags: -Znext-solver // Test that we avoid incomplete inference when normalizing. Without this, @@ -25,5 +24,4 @@ where T::Assoc<[u32; 1]>: Clone, { let _x = T::Assoc::new(()); -//~^ ERROR: mismatched types } From c50aebba78724edd395841f884998ddeddd659d4 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 27 Jun 2025 10:11:28 +0000 Subject: [PATCH 10/17] trait_sel: don't require predicates of aliases hold No longer require that we prove that the predicates of aliases hold when checking the well-formedness of the alias. This permits more uses of GATs and changes the output of yet more tests. --- .../src/traits/select/confirmation.rs | 24 -- ...ranked-auto-trait-14.no_assumptions.stderr | 33 -- .../higher-ranked-auto-trait-14.rs | 3 +- ...-ranked-auto-trait-2.no_assumptions.stderr | 49 --- .../async-await/higher-ranked-auto-trait-2.rs | 3 +- ...her-ranked-auto-trait-3.assumptions.stderr | 292 ---------------- ...-ranked-auto-trait-3.no_assumptions.stderr | 312 ------------------ .../async-await/higher-ranked-auto-trait-3.rs | 4 +- ...-ranked-auto-trait-7.no_assumptions.stderr | 8 - .../async-await/higher-ranked-auto-trait-7.rs | 3 +- .../assoc_type_bounds_sized_used.rs | 3 +- .../assoc_type_bounds_sized_used.stderr | 61 +++- ...ine-param-outlives-2.no_assumptions.stderr | 24 -- ...igher-ranked-coroutine-param-outlives-2.rs | 3 +- ...utine-param-outlives.no_assumptions.stderr | 8 - .../higher-ranked-coroutine-param-outlives.rs | 3 +- .../generic-associated-types/issue-93262.rs | 4 +- .../issue-93262.stderr | 19 -- .../bound-on-assoc-type-projection-1.rs | 21 ++ 19 files changed, 80 insertions(+), 797 deletions(-) delete mode 100644 tests/ui/async-await/higher-ranked-auto-trait-14.no_assumptions.stderr delete mode 100644 tests/ui/async-await/higher-ranked-auto-trait-2.no_assumptions.stderr delete mode 100644 tests/ui/async-await/higher-ranked-auto-trait-3.assumptions.stderr delete mode 100644 tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr delete mode 100644 tests/ui/async-await/higher-ranked-auto-trait-7.no_assumptions.stderr delete mode 100644 tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.no_assumptions.stderr delete mode 100644 tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.no_assumptions.stderr delete mode 100644 tests/ui/generic-associated-types/issue-93262.stderr create mode 100644 tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 708a53f6c650..b537419c715b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -144,8 +144,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, idx: usize, ) -> Result, SelectionError<'tcx>> { - let tcx = self.tcx(); - let placeholder_trait_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref; let placeholder_self_ty = self.infcx.shallow_resolve(placeholder_trait_predicate.self_ty()); @@ -194,28 +192,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_err(|_| SelectionError::Unimplemented)?, ); - // FIXME(compiler-errors): I don't think this is needed. - if let ty::Alias(ty::Projection, alias_ty) = placeholder_self_ty.kind() { - let predicates = tcx.predicates_of(alias_ty.def_id).instantiate_own(tcx, alias_ty.args); - for (predicate, _) in predicates { - let normalized = normalize_with_depth_to( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - predicate, - &mut obligations, - ); - obligations.push(Obligation::with_depth( - self.tcx(), - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - normalized, - )); - } - } - Ok(obligations) } diff --git a/tests/ui/async-await/higher-ranked-auto-trait-14.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-14.no_assumptions.stderr deleted file mode 100644 index b47db2b19ffe..000000000000 --- a/tests/ui/async-await/higher-ranked-auto-trait-14.no_assumptions.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error: implementation of `FnOnce` is not general enough - --> $DIR/higher-ranked-auto-trait-14.rs:20:5 - | -LL | / async move { -LL | | let xs = unique_x.union(&cached) -LL | | // .copied() // works -LL | | .map(|x| *x) // error -LL | | ; -LL | | let blah = val.blah(xs.into_iter()).await; -LL | | } - | |_____^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'0 u32) -> u32` must implement `FnOnce<(&'1 u32,)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `FnOnce<(&u32,)>` - -error: implementation of `FnOnce` is not general enough - --> $DIR/higher-ranked-auto-trait-14.rs:20:5 - | -LL | / async move { -LL | | let xs = unique_x.union(&cached) -LL | | // .copied() // works -LL | | .map(|x| *x) // error -LL | | ; -LL | | let blah = val.blah(xs.into_iter()).await; -LL | | } - | |_____^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'0 u32) -> u32` must implement `FnOnce<(&'1 u32,)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `FnOnce<(&u32,)>` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/async-await/higher-ranked-auto-trait-14.rs b/tests/ui/async-await/higher-ranked-auto-trait-14.rs index 5ed12cd6e38c..ed53d6306c60 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-14.rs +++ b/tests/ui/async-await/higher-ranked-auto-trait-14.rs @@ -1,9 +1,8 @@ // Repro for . +//@ check-pass //@ edition: 2021 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass -//@[no_assumptions] known-bug: #110338 use std::collections::HashSet; use std::future::Future; diff --git a/tests/ui/async-await/higher-ranked-auto-trait-2.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-2.no_assumptions.stderr deleted file mode 100644 index 2fc44412b9da..000000000000 --- a/tests/ui/async-await/higher-ranked-auto-trait-2.no_assumptions.stderr +++ /dev/null @@ -1,49 +0,0 @@ -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-2.rs:16:9 - | -LL | / async move { -LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics -LL | | self.run(t).await; -LL | | } - | |_________^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-2.rs:16:9 - | -LL | / async move { -LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics -LL | | self.run(t).await; -LL | | } - | |_________^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-2.rs:16:9 - | -LL | / async move { -LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics -LL | | self.run(t).await; -LL | | } - | |_________^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-2.rs:16:9 - | -LL | / async move { -LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics -LL | | self.run(t).await; -LL | | } - | |_________^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors - diff --git a/tests/ui/async-await/higher-ranked-auto-trait-2.rs b/tests/ui/async-await/higher-ranked-auto-trait-2.rs index 6c75597265bc..b09b4983de29 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-2.rs +++ b/tests/ui/async-await/higher-ranked-auto-trait-2.rs @@ -1,9 +1,8 @@ // Repro for . +//@ check-pass //@ edition: 2021 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass -//@[no_assumptions] known-bug: #110338 use std::future::Future; diff --git a/tests/ui/async-await/higher-ranked-auto-trait-3.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-3.assumptions.stderr deleted file mode 100644 index be978f19d7ee..000000000000 --- a/tests/ui/async-await/higher-ranked-auto-trait-3.assumptions.stderr +++ /dev/null @@ -1,292 +0,0 @@ -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:54:5 - | -LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:54:5 - | -LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:63:5 - | -LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:63:5 - | -LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:40:31 - | -LL | impl IterCaller for UseIter - | ^^^^^^^^^^^^^^^^^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:46:5 - | -LL | type Future1<'cx> = impl Future + Send + 'cx - | ^^^^^^^^^^^^^^^^^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:50:5 - | -LL | type Future2<'cx> = impl Future + Send + 'cx - | ^^^^^^^^^^^^^^^^^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:54:50 - | -LL | fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> - | ^^^^^^^^^^^^^^^^^^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:63:50 - | -LL | fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> - | ^^^^^^^^^^^^^^^^^^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: higher-ranked subtype error - --> $DIR/higher-ranked-auto-trait-3.rs:54:5 - | -LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - -error: higher-ranked subtype error - --> $DIR/higher-ranked-auto-trait-3.rs:54:5 - | -LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:58:9 - | -LL | / async { -LL | | self.fi_1.get_iter(cx).await; -LL | | } - | |_________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:58:9 - | -LL | / async { -LL | | self.fi_1.get_iter(cx).await; -LL | | } - | |_________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: higher-ranked subtype error - --> $DIR/higher-ranked-auto-trait-3.rs:63:5 - | -LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - -error: higher-ranked subtype error - --> $DIR/higher-ranked-auto-trait-3.rs:63:5 - | -LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:67:9 - | -LL | / async { -LL | | self.fi_2.get_iter(cx).await; -LL | | } - | |_________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:67:9 - | -LL | / async { -LL | | self.fi_2.get_iter(cx).await; -LL | | } - | |_________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 17 previous errors - diff --git a/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr deleted file mode 100644 index 1c5aa3af7d1e..000000000000 --- a/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr +++ /dev/null @@ -1,312 +0,0 @@ -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:54:5 - | -LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:54:5 - | -LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:63:5 - | -LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:63:5 - | -LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:40:31 - | -LL | impl IterCaller for UseIter - | ^^^^^^^^^^^^^^^^^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:46:5 - | -LL | type Future1<'cx> = impl Future + Send + 'cx - | ^^^^^^^^^^^^^^^^^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:50:5 - | -LL | type Future2<'cx> = impl Future + Send + 'cx - | ^^^^^^^^^^^^^^^^^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:54:50 - | -LL | fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> - | ^^^^^^^^^^^^^^^^^^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:63:50 - | -LL | fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> - | ^^^^^^^^^^^^^^^^^^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: higher-ranked subtype error - --> $DIR/higher-ranked-auto-trait-3.rs:54:5 - | -LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - -error: higher-ranked subtype error - --> $DIR/higher-ranked-auto-trait-3.rs:54:5 - | -LL | / fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:58:9 - | -LL | / async { -LL | | self.fi_1.get_iter(cx).await; -LL | | } - | |_________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:58:9 - | -LL | / async { -LL | | self.fi_1.get_iter(cx).await; -LL | | } - | |_________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:58:9 - | -LL | / async { -LL | | self.fi_1.get_iter(cx).await; -LL | | } - | |_________^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: higher-ranked subtype error - --> $DIR/higher-ranked-auto-trait-3.rs:63:5 - | -LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - -error: higher-ranked subtype error - --> $DIR/higher-ranked-auto-trait-3.rs:63:5 - | -LL | / fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> -LL | | where -LL | | 's: 'cx, - | |________________^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:67:9 - | -LL | / async { -LL | | self.fi_2.get_iter(cx).await; -LL | | } - | |_________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:67:9 - | -LL | / async { -LL | | self.fi_2.get_iter(cx).await; -LL | | } - | |_________^ - | -note: the lifetime `'cx` defined here... - --> $DIR/higher-ranked-auto-trait-3.rs:43:13 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^^ -note: ...must outlive the lifetime `'s` defined here - --> $DIR/higher-ranked-auto-trait-3.rs:43:9 - | -LL | for<'s, 'cx> FI1::Future<'s, 'cx>: Send, - | ^^ - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:67:9 - | -LL | / async { -LL | | self.fi_2.get_iter(cx).await; -LL | | } - | |_________^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: aborting due to 19 previous errors - diff --git a/tests/ui/async-await/higher-ranked-auto-trait-3.rs b/tests/ui/async-await/higher-ranked-auto-trait-3.rs index 2ab986a097a6..2b7990d5f3f1 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-3.rs +++ b/tests/ui/async-await/higher-ranked-auto-trait-3.rs @@ -1,10 +1,8 @@ // Repro for . +//@ check-pass //@ edition: 2021 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-fail -//@[assumptions] known-bug: #110338 -//@[no_assumptions] known-bug: #110338 #![feature(impl_trait_in_assoc_type)] diff --git a/tests/ui/async-await/higher-ranked-auto-trait-7.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-7.no_assumptions.stderr deleted file mode 100644 index dcb8075566e6..000000000000 --- a/tests/ui/async-await/higher-ranked-auto-trait-7.no_assumptions.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `S` does not live long enough - --> $DIR/higher-ranked-auto-trait-7.rs:26:5 - | -LL | future::<'a, S, _>(async move { - | ^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/async-await/higher-ranked-auto-trait-7.rs b/tests/ui/async-await/higher-ranked-auto-trait-7.rs index abded5a88d3a..558bd6de4429 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-7.rs +++ b/tests/ui/async-await/higher-ranked-auto-trait-7.rs @@ -1,9 +1,8 @@ // Repro for . +//@ check-pass //@ edition: 2021 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass -//@[no_assumptions] known-bug: #110338 #![allow(dropping_copy_types)] diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs index d59fc1712ea7..8243803c86d7 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs +++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs @@ -9,7 +9,8 @@ trait Bop { fn bop() { let _ = ::Bar::default(); - //~^ ERROR: trait bounds were not satisfied + //~^ ERROR: the size for values of type `T` cannot be known at compilation time + //~| ERROR: the size for values of type `T` cannot be known at compilation time //~| ERROR: the size for values of type `T` cannot be known at compilation time } diff --git a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr index 7b152adea492..fe048c87775a 100644 --- a/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr +++ b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr @@ -24,21 +24,58 @@ help: consider relaxing the implicit `Sized` restriction LL | type Bar: Default + ?Sized | ++++++++ -error[E0599]: the function or associated item `default` exists for associated type `::Bar`, but its trait bounds were not satisfied - --> $DIR/assoc_type_bounds_sized_used.rs:11:30 +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/assoc_type_bounds_sized_used.rs:11:13 | +LL | fn bop() { + | - this type parameter needs to be `Sized` LL | let _ = ::Bar::default(); - | ^^^^^^^ function or associated item cannot be called on `::Bar` due to unsatisfied trait bounds + | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = note: the following trait bounds were not satisfied: - `T: Sized` - which is required by `::Bar: Default` -help: consider restricting the type parameter to satisfy the trait bound +note: required by a bound in `Bop::Bar` + --> $DIR/assoc_type_bounds_sized_used.rs:7:15 | -LL | fn bop() where T: Sized { - | ++++++++++++++ +LL | type Bar: Default + | --- required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bop::Bar` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn bop() { +LL + fn bop() { + | +help: consider relaxing the implicit `Sized` restriction + | +LL | type Bar: Default + ?Sized + | ++++++++ -error: aborting due to 2 previous errors +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/assoc_type_bounds_sized_used.rs:11:13 + | +LL | fn bop() { + | - this type parameter needs to be `Sized` +LL | let _ = ::Bar::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Bop::Bar` + --> $DIR/assoc_type_bounds_sized_used.rs:7:15 + | +LL | type Bar: Default + | --- required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bop::Bar` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn bop() { +LL + fn bop() { + | +help: consider relaxing the implicit `Sized` restriction + | +LL | type Bar: Default + ?Sized + | ++++++++ -Some errors have detailed explanations: E0277, E0599. -For more information about an error, try `rustc --explain E0277`. +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.no_assumptions.stderr b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.no_assumptions.stderr deleted file mode 100644 index 8b62fb6a2547..000000000000 --- a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.no_assumptions.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: lifetime bound not satisfied - --> $DIR/higher-ranked-coroutine-param-outlives-2.rs:14:5 - | -LL | / async { // a coroutine checked for autotrait impl `Send` -LL | | let x = None::>; // a type referencing GAT -LL | | async {}.await; // a yield point -LL | | } - | |_____^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: lifetime bound not satisfied - --> $DIR/higher-ranked-coroutine-param-outlives-2.rs:21:5 - | -LL | / async { // a coroutine checked for autotrait impl `Send` -LL | | let x = None::>; // a type referencing GAT -LL | | async {}.await; // a yield point -LL | | } - | |_____^ - | - = note: this is a known limitation that will be removed in the future (see issue #100013 for more information) - -error: aborting due to 2 previous errors - diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs index a5ed162d62c9..96ff23cbc087 100644 --- a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs +++ b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives-2.rs @@ -1,8 +1,7 @@ +//@ check-pass //@ edition: 2021 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass -//@[no_assumptions] known-bug: #110338 pub trait FutureIterator { type Future<'s, 'cx>: Send diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.no_assumptions.stderr b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.no_assumptions.stderr deleted file mode 100644 index f747ba9a7334..000000000000 --- a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.no_assumptions.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `C` does not live long enough - --> $DIR/higher-ranked-coroutine-param-outlives.rs:21:5 - | -LL | async move { c.connect().await } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs index 5f683bd82fa4..0c7d29d1256a 100644 --- a/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs +++ b/tests/ui/generic-associated-types/higher-ranked-coroutine-param-outlives.rs @@ -1,8 +1,7 @@ +//@ check-pass //@ edition:2018 //@ revisions: assumptions no_assumptions //@[assumptions] compile-flags: -Zhigher-ranked-assumptions -//@[assumptions] check-pass -//@[no_assumptions] known-bug: #110338 use std::future::Future; diff --git a/tests/ui/generic-associated-types/issue-93262.rs b/tests/ui/generic-associated-types/issue-93262.rs index c964606fef0b..c4a6f0dbaa07 100644 --- a/tests/ui/generic-associated-types/issue-93262.rs +++ b/tests/ui/generic-associated-types/issue-93262.rs @@ -1,4 +1,4 @@ -//@ check-fail +//@ check-pass pub trait Trait { type Assoc<'a> where Self: 'a; @@ -11,7 +11,7 @@ where pub struct Type; -impl Foo for Type //~ ERROR: the parameter type `T` may not live long enough +impl Foo for Type where for<'a> T::Assoc<'a>: Clone {} diff --git a/tests/ui/generic-associated-types/issue-93262.stderr b/tests/ui/generic-associated-types/issue-93262.stderr deleted file mode 100644 index 91d3e65f3de8..000000000000 --- a/tests/ui/generic-associated-types/issue-93262.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0311]: the parameter type `T` may not live long enough - --> $DIR/issue-93262.rs:14:16 - | -LL | impl Foo for Type - | ^^^^^^ - | | - | the parameter type `T` must be valid for lifetime `'a`... - | ...so that the type `T` will meet its required lifetime bounds... - | -note: ...that is required by this bound - --> $DIR/issue-93262.rs:9:27 - | -LL | for<'a> T::Assoc<'a>: Clone - | ^^^^^ - = help: consider adding an explicit lifetime bound `T: 'a`... - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0311`. diff --git a/tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs b/tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs new file mode 100644 index 000000000000..4a20ed2cafb1 --- /dev/null +++ b/tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs @@ -0,0 +1,21 @@ +//@ check-pass +//@ compile-flags: --crate-type=lib +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + +use std::marker::PhantomData; + +pub trait ZeroMapKV<'a> { + type Container; +} + +pub trait ZeroFrom<'zf, C: ?Sized> {} + +pub struct ZeroMap<'a, K: ZeroMapKV<'a>>(PhantomData<&'a K>); + +impl<'zf, 's, K> ZeroFrom<'zf, ZeroMap<'s, K>> for ZeroMap<'zf, K> +where + K: for<'b> ZeroMapKV<'b>, + >::Container: ZeroFrom<'zf, >::Container>, +{ +} From 676d9cfa8bc6f2406d0d7ed8cd0d5eae74254bec Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 27 Jun 2025 10:11:28 +0000 Subject: [PATCH 11/17] trait_sel: prefer only nested alias bounds --- compiler/rustc_middle/src/traits/select.rs | 10 +++- .../src/solve/assembly/mod.rs | 17 +++--- .../src/solve/effect_goals.rs | 4 +- .../src/solve/trait_goals.rs | 43 +++++++++------ .../rustc_trait_selection/src/solve/select.rs | 8 ++- .../src/traits/project.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 12 +++-- .../src/traits/select/confirmation.rs | 4 +- .../src/traits/select/mod.rs | 54 +++++++++++++------ compiler/rustc_type_ir/src/solve/mod.rs | 11 +++- .../prefer-non-nested-alias-bound.rs | 30 +++++++++++ 11 files changed, 138 insertions(+), 57 deletions(-) create mode 100644 tests/ui/sized-hierarchy/prefer-non-nested-alias-bound.rs diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index c498e6b3c83d..32a74b335c11 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -6,6 +6,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TypeVisitable}; use rustc_query_system::cache::Cache; +use rustc_type_ir::solve::AliasBoundKind; use self::EvaluationResult::*; use super::{SelectionError, SelectionResult}; @@ -116,8 +117,13 @@ pub enum SelectionCandidate<'tcx> { /// This is a trait matching with a projected type as `Self`, and we found /// an applicable bound in the trait definition. The `usize` is an index - /// into the list returned by `tcx.item_bounds`. - ProjectionCandidate(usize), + /// into the list returned by `tcx.item_bounds` and the `AliasBoundKind` + /// is whether this is candidate from recursion on the self type of a + /// projection. + ProjectionCandidate { + idx: usize, + kind: AliasBoundKind, + }, /// Implementation of a `Fn`-family trait by one of the anonymous types /// generated for an `||` expression. diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index d58c264841c8..c9a42dddac42 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -9,7 +9,7 @@ use derive_where::derive_where; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::SolverTraitLangItem; use rustc_type_ir::search_graph::CandidateHeadUsages; -use rustc_type_ir::solve::SizedTraitKind; +use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind}; use rustc_type_ir::{ self as ty, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, @@ -27,11 +27,6 @@ use crate::solve::{ has_no_inference_or_external_constraints, }; -enum AliasBoundKind { - SelfBounds, - NonSelfBounds, -} - /// A candidate is a possible way to prove a goal. /// /// It consists of both the `source`, which describes how that goal would be proven, @@ -451,7 +446,7 @@ where matches!( c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal) - | CandidateSource::AliasBound + | CandidateSource::AliasBound(_) ) && has_no_inference_or_external_constraints(c.result) }) { @@ -711,7 +706,7 @@ where self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) { candidates.push(Candidate { - source: CandidateSource::AliasBound, + source: CandidateSource::AliasBound(consider_self_bounds), result, head_usages: CandidateHeadUsages::default(), }); @@ -735,7 +730,7 @@ where { candidates.extend(G::probe_and_consider_implied_clause( self, - CandidateSource::AliasBound, + CandidateSource::AliasBound(consider_self_bounds), goal, assumption, [], @@ -750,7 +745,7 @@ where { candidates.extend(G::probe_and_consider_implied_clause( self, - CandidateSource::AliasBound, + CandidateSource::AliasBound(consider_self_bounds), goal, assumption, [], @@ -1030,7 +1025,7 @@ where item_bound.fold_with(&mut ReplaceOpaque { cx: self.cx(), alias_ty, self_ty }); candidates.extend(G::probe_and_match_goal_against_assumption( self, - CandidateSource::AliasBound, + CandidateSource::AliasBound(AliasBoundKind::SelfBounds), goal, assumption, |ecx| { diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 65a5edf6b725..48bd0963c874 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -4,8 +4,8 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::SolverTraitLangItem; -use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::solve::inspect::ProbeKind; +use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind}; use rustc_type_ir::{self as ty, Interner, TypingMode, elaborate}; use tracing::instrument; @@ -96,7 +96,7 @@ where ) { candidates.extend(Self::probe_and_match_goal_against_assumption( ecx, - CandidateSource::AliasBound, + CandidateSource::AliasBound(AliasBoundKind::SelfBounds), goal, clause, |ecx| { diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 5edd281acefc..168921655a39 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -4,7 +4,9 @@ use rustc_type_ir::data_structures::IndexSet; use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::SolverTraitLangItem; -use rustc_type_ir::solve::{CandidatePreferenceMode, CanonicalResponse, SizedTraitKind}; +use rustc_type_ir::solve::{ + AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, SizedTraitKind, +}; use rustc_type_ir::{ self as ty, Interner, Movability, PredicatePolarity, TraitPredicate, TraitRef, TypeVisitableExt as _, TypingMode, Upcast as _, elaborate, @@ -1381,22 +1383,21 @@ where return Ok((candidate.result, Some(TraitGoalProvenVia::Misc))); } - let potential_alias_bound_response = - candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound)).then(|| { - let alias_bounds: Vec<_> = candidates - .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound)) - .collect(); - if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) { - (response, Some(TraitGoalProvenVia::AliasBound)) - } else { - (self.bail_with_ambiguity(&alias_bounds), None) - } - }); - + // Extract non-nested alias bound candidates, will be preferred over where bounds if + // we're proving an auto-trait, sizedness trait or default trait. if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker) - && let Some(alias_bound_response) = potential_alias_bound_response + && candidates.iter().any(|c| { + matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds)) + }) { - return Ok(alias_bound_response); + let alias_bounds: Vec<_> = candidates + .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..))) + .collect(); + return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) { + Ok((response, Some(TraitGoalProvenVia::AliasBound))) + } else { + Ok((self.bail_with_ambiguity(&alias_bounds), None)) + }; } // If there are non-global where-bounds, prefer where-bounds @@ -1446,8 +1447,16 @@ where }; } - if let Some(response) = potential_alias_bound_response { - return Ok(response); + // Next, prefer any alias bound (nested or otherwise). + if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound(_))) { + let alias_bounds: Vec<_> = candidates + .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_))) + .collect(); + return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) { + Ok((response, Some(TraitGoalProvenVia::AliasBound))) + } else { + Ok((self.bail_with_ambiguity(&alias_bounds), None)) + }; } self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates); diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs index 8d01c880f8c5..d7e7ffd5d28c 100644 --- a/compiler/rustc_trait_selection/src/solve/select.rs +++ b/compiler/rustc_trait_selection/src/solve/select.rs @@ -126,7 +126,9 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>( // Prefer dyn candidates over non-dyn candidates. This is necessary to // handle the unsoundness between `impl Any for T` and `dyn Any: Any`. ( - CandidateSource::Impl(_) | CandidateSource::ParamEnv(_) | CandidateSource::AliasBound, + CandidateSource::Impl(_) + | CandidateSource::ParamEnv(_) + | CandidateSource::AliasBound(_), CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }), ) => true, @@ -175,7 +177,9 @@ fn to_selection<'tcx>( }) } CandidateSource::BuiltinImpl(builtin) => ImplSource::Builtin(builtin, nested), - CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => ImplSource::Param(nested), + CandidateSource::ParamEnv(_) | CandidateSource::AliasBound(_) => { + ImplSource::Param(nested) + } CandidateSource::CoherenceUnknowable => { span_bug!(span, "didn't expect to select an unknowable candidate") } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 042d6def84c3..fab5102427c7 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -741,7 +741,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( let mut ambiguous = false; let _ = selcx.for_each_item_bound( obligation.predicate.self_ty(), - |selcx, clause, _| { + |selcx, clause, _, _| { let Some(clause) = clause.as_projection_clause() else { return ControlFlow::Continue(()); }; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 60f1fcb26c00..cb980d5ce8b4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -208,7 +208,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut distinct_normalized_bounds = FxHashSet::default(); let _ = self.for_each_item_bound::( placeholder_trait_predicate.self_ty(), - |selcx, bound, idx| { + |selcx, bound, idx, alias_bound_kind| { let Some(bound) = bound.as_trait_clause() else { return ControlFlow::Continue(()); }; @@ -230,12 +230,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { bound.map_bound(|pred| pred.trait_ref), ) { Ok(None) => { - candidates.vec.push(ProjectionCandidate(idx)); + candidates + .vec + .push(ProjectionCandidate { idx, kind: alias_bound_kind }); } Ok(Some(normalized_trait)) if distinct_normalized_bounds.insert(normalized_trait) => { - candidates.vec.push(ProjectionCandidate(idx)); + candidates + .vec + .push(ProjectionCandidate { idx, kind: alias_bound_kind }); } _ => {} } @@ -825,7 +829,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::Alias(ty::Opaque, alias) => { - if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(_))) { + if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate { .. })) { // We do not generate an auto impl candidate for `impl Trait`s which already // reference our auto trait. // diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index b537419c715b..66311de7446b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -67,7 +67,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Builtin(BuiltinImplSource::Misc, data) } - ProjectionCandidate(idx) => { + ProjectionCandidate { idx, .. } => { let obligations = self.confirm_projection_candidate(obligation, idx)?; ImplSource::Param(obligations) } @@ -150,7 +150,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let candidate_predicate = self .for_each_item_bound( placeholder_self_ty, - |_, clause, clause_idx| { + |_, clause, clause_idx, _| { if clause_idx == idx { ControlFlow::Break(clause) } else { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5af16187e585..9be5d0673f73 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -32,6 +32,7 @@ use rustc_middle::ty::{ SizedTraitKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode, Upcast, elaborate, may_use_unstable_feature, }; +use rustc_next_trait_solver::solve::AliasBoundKind; use rustc_span::{Symbol, sym}; use tracing::{debug, instrument, trace}; @@ -1628,11 +1629,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub(super) fn for_each_item_bound( &mut self, mut self_ty: Ty<'tcx>, - mut for_each: impl FnMut(&mut Self, ty::Clause<'tcx>, usize) -> ControlFlow, + mut for_each: impl FnMut( + &mut Self, + ty::Clause<'tcx>, + usize, + AliasBoundKind, + ) -> ControlFlow, on_ambiguity: impl FnOnce(), ) -> ControlFlow { let mut idx = 0; - let mut in_parent_alias_type = false; + let mut alias_bound_kind = AliasBoundKind::SelfBounds; loop { let (kind, alias_ty) = match *self_ty.kind() { @@ -1648,14 +1654,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // share the same type as `self_ty`. This is because for truly rigid // projections, we will never be able to equate, e.g. `::A` // with `<::A as Tr>::A`. - let relevant_bounds = if in_parent_alias_type { + let relevant_bounds = if matches!(alias_bound_kind, AliasBoundKind::NonSelfBounds) { self.tcx().item_non_self_bounds(alias_ty.def_id) } else { self.tcx().item_self_bounds(alias_ty.def_id) }; for bound in relevant_bounds.instantiate(self.tcx(), alias_ty.args) { - for_each(self, bound, idx)?; + for_each(self, bound, idx, alias_bound_kind)?; idx += 1; } @@ -1665,7 +1671,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return ControlFlow::Continue(()); } - in_parent_alias_type = true; + alias_bound_kind = AliasBoundKind::NonSelfBounds; } } @@ -1880,14 +1886,24 @@ impl<'tcx> SelectionContext<'_, 'tcx> { break; } - let alias_bound = candidates - .iter() - .filter_map(|c| if let ProjectionCandidate(i) = c.candidate { Some(i) } else { None }) - .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) }); - + let mut alias_bounds = candidates.iter().filter_map(|c| { + if let ProjectionCandidate { idx, kind } = c.candidate { + Some((idx, kind)) + } else { + None + } + }); + // Extract non-nested alias bound candidates, will be preferred over where bounds if + // we're proving an auto-trait, sizedness trait or default trait. if matches!(candidate_preference_mode, CandidatePreferenceMode::Marker) { - match alias_bound { - Some(Some(index)) => return Some(ProjectionCandidate(index)), + match alias_bounds + .clone() + .filter_map(|(idx, kind)| (kind == AliasBoundKind::SelfBounds).then_some(idx)) + .try_reduce(|c1, c2| if has_non_region_infer { None } else { Some(c1.min(c2)) }) + { + Some(Some(idx)) => { + return Some(ProjectionCandidate { idx, kind: AliasBoundKind::SelfBounds }); + } Some(None) => {} None => return None, } @@ -1926,8 +1942,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // fairly arbitrary but once again necessary for backwards compatibility. // If there are multiple applicable candidates which don't affect type inference, // choose the one with the lowest index. - match alias_bound { - Some(Some(index)) => return Some(ProjectionCandidate(index)), + match alias_bounds.try_reduce(|(c1, k1), (c2, k2)| { + if has_non_region_infer { + None + } else if c1 < c2 { + Some((c1, k1)) + } else { + Some((c2, k2)) + } + }) { + Some(Some((idx, kind))) => return Some(ProjectionCandidate { idx, kind }), Some(None) => {} None => return None, } @@ -2016,7 +2040,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Non-global param candidates have already been handled, global // where-bounds get ignored. ParamCandidate(_) | ImplCandidate(_) => true, - ProjectionCandidate(_) | ObjectCandidate(_) => unreachable!(), + ProjectionCandidate { .. } | ObjectCandidate(_) => unreachable!(), }) { return Some(ImplCandidate(def_id)); } else { diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index f155d45bc0a6..1e0263b232f4 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -189,7 +189,7 @@ pub enum CandidateSource { /// let _y = x.clone(); /// } /// ``` - AliasBound, + AliasBound(AliasBoundKind), /// A candidate that is registered only during coherence to represent some /// yet-unknown impl that could be produced downstream without violating orphan /// rules. @@ -207,6 +207,15 @@ pub enum ParamEnvSource { Global, } +#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +pub enum AliasBoundKind { + /// Alias bound from the self type of a projection + SelfBounds, + // Alias bound having recursed on the self type of a projection + NonSelfBounds, +} + #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] #[cfg_attr( feature = "nightly", diff --git a/tests/ui/sized-hierarchy/prefer-non-nested-alias-bound.rs b/tests/ui/sized-hierarchy/prefer-non-nested-alias-bound.rs new file mode 100644 index 000000000000..affef2e61482 --- /dev/null +++ b/tests/ui/sized-hierarchy/prefer-non-nested-alias-bound.rs @@ -0,0 +1,30 @@ +//@ check-pass +//@ compile-flags: --crate-type=lib +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Since #120752, also get alias-bound candidates from a nested self-type, so prefering +// alias-bound over where-bound candidates can be incorrect. This test checks that case and that +// we prefer non-nested alias-bound candidates over where-bound candidates over nested alias-bound +// candidates. + +trait OtherTrait<'a> { + type Assoc: ?Sized; +} + +trait Trait +where + >::Assoc: Sized, +{ + type Assoc: for<'a> OtherTrait<'a>; +} + +fn impls_sized() {} +fn foo<'a, T>() +where + T: Trait, + for<'hr> >::Assoc: Sized, +{ + impls_sized::<>::Assoc>(); +} From 519d6cd364c69a918221932fa10c1be5163dda88 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 15 Oct 2025 09:40:32 +0100 Subject: [PATCH 12/17] core: relax supertrait of `Destruct` --- library/core/src/marker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 4b767d8d6221..5fd0611a1843 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1057,7 +1057,7 @@ marker_impls! { #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] #[rustc_deny_explicit_impl] #[rustc_do_not_implement_via_object] -pub const trait Destruct {} +pub const trait Destruct: PointeeSized {} /// A marker for tuple types. /// From de67ea37a7f81a7209568f841e860a35d1d806c6 Mon Sep 17 00:00:00 2001 From: apiraino Date: Thu, 9 Oct 2025 16:41:07 +0200 Subject: [PATCH 13/17] Update t-compiler beta nomination Zulip msg --- triagebot.toml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index a04f8d280723..d7e86505dd91 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -742,13 +742,15 @@ message_on_reopen = "PR #{number} has been reopened. Pinging @*T-rustdoc*." [notify-zulip."beta-nominated".compiler] required_labels = ["T-compiler"] zulip_stream = 474880 # #t-compiler/backports -topic = "#{number}: beta-nominated" +topic = "#{number}: beta-backport nomination" message_on_add = [ """\ -@**channel** PR #{number} "{title}" has been nominated for beta backport. +PR #{number} "{title}" fixes a regression. +{recipients}, please evaluate nominating this PR for backport. +The following poll is a vibe-check and not binding. """, """\ -/poll Approve beta backport of #{number}? +/poll Should #{number} be beta backported? approve decline don't know From 68080de4e39bdfa41fa0657f94579860e19cb2f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 15 Oct 2025 15:47:44 +0000 Subject: [PATCH 14/17] ignore boring locals when explaining borrow due to drop Polonius liveness has to contain boring locals, and we ignore them in diagnostics to match NLL diagnostics, since they doesn't contain boring locals. We ignored these when explaining why a loan contained a point due to a use of a live var, but not when it contained a point due to a drop of a live var. --- compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs | 4 ++-- .../polonius/lending-iterator-sanity-checks.polonius.stderr | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 638d89f5bcbd..6bcfa9d8bf9a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -687,7 +687,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { } } - Some(Cause::DropVar(local, location)) => { + Some(Cause::DropVar(local, location)) if !is_local_boring(local) => { let mut should_note_order = false; if self.local_name(local).is_some() && let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place @@ -705,7 +705,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { } } - Some(Cause::LiveVar(..)) | None => { + Some(Cause::LiveVar(..) | Cause::DropVar(..)) | None => { // Here, under NLL: no cause was found. Under polonius: no cause was found, or a // boring local was found, which we ignore like NLLs do to match its diagnostics. if let Some(region) = self.to_error_region_vid(borrow_region_vid) { diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr b/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr index bf8546b63bf3..fa201b89048a 100644 --- a/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr +++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr @@ -1,13 +1,15 @@ error[E0499]: cannot borrow `*t` as mutable more than once at a time --> $DIR/lending-iterator-sanity-checks.rs:19:19 | +LL | fn use_live(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)> { + | - let's call the lifetime of this reference `'1` LL | let Some(i) = t.next() else { return None }; | - first mutable borrow occurs here LL | let Some(j) = t.next() else { return None }; | ^ second mutable borrow occurs here ... -LL | } - | - first borrow might be used here, when `i` is dropped and runs the destructor for type `::Item<'_>` +LL | Some((i, j)) + | ------------ returning this value requires that `*t` is borrowed for `'1` error[E0499]: cannot borrow `*t` as mutable more than once at a time --> $DIR/lending-iterator-sanity-checks.rs:31:13 From b5906362ddb30a96c5d2077815ed584611eddf7f Mon Sep 17 00:00:00 2001 From: Scott Schafer Date: Wed, 15 Oct 2025 10:07:17 -0600 Subject: [PATCH 15/17] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 81c3f77a4673..367fd9f21375 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 81c3f77a467359c8be6bc747dc93ec66a6e4ce11 +Subproject commit 367fd9f213750cd40317803dd0a5a3ce3f0c676d From 804af9945702fd5db27a4a95c412a8474f0f97cf Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 15 Oct 2025 10:24:22 +0200 Subject: [PATCH 16/17] miri: use allocator_shim_contents codegen helper --- compiler/rustc_ast/src/expand/allocator.rs | 17 ++ compiler/rustc_codegen_llvm/src/allocator.rs | 16 +- compiler/rustc_codegen_ssa/src/base.rs | 1 + src/tools/miri/src/lib.rs | 1 + src/tools/miri/src/machine.rs | 39 +++ src/tools/miri/src/shims/alloc.rs | 115 +++++++-- src/tools/miri/src/shims/foreign_items.rs | 235 +++++-------------- 7 files changed, 218 insertions(+), 206 deletions(-) diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index c200921e5f80..332ad50d927f 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -31,10 +31,23 @@ pub enum AllocatorTy { Usize, } +/// Some allocator methods are known to the compiler: they act more like +/// intrinsics/language primitives than library-defined functions. +/// FIXME: ideally this would be derived from attributes like `#[rustc_allocator]`, +/// so we don't have two sources of truth. +#[derive(Copy, Clone, Debug)] +pub enum SpecialAllocatorMethod { + Alloc, + AllocZeroed, + Dealloc, + Realloc, +} + /// A method that will be codegened in the allocator shim. #[derive(Copy, Clone)] pub struct AllocatorMethod { pub name: Symbol, + pub special: Option, pub inputs: &'static [AllocatorMethodInput], pub output: AllocatorTy, } @@ -47,11 +60,13 @@ pub struct AllocatorMethodInput { pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[ AllocatorMethod { name: sym::alloc, + special: Some(SpecialAllocatorMethod::Alloc), inputs: &[AllocatorMethodInput { name: "layout", ty: AllocatorTy::Layout }], output: AllocatorTy::ResultPtr, }, AllocatorMethod { name: sym::dealloc, + special: Some(SpecialAllocatorMethod::Dealloc), inputs: &[ AllocatorMethodInput { name: "ptr", ty: AllocatorTy::Ptr }, AllocatorMethodInput { name: "layout", ty: AllocatorTy::Layout }, @@ -60,6 +75,7 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[ }, AllocatorMethod { name: sym::realloc, + special: Some(SpecialAllocatorMethod::Realloc), inputs: &[ AllocatorMethodInput { name: "ptr", ty: AllocatorTy::Ptr }, AllocatorMethodInput { name: "layout", ty: AllocatorTy::Layout }, @@ -69,6 +85,7 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[ }, AllocatorMethod { name: sym::alloc_zeroed, + special: Some(SpecialAllocatorMethod::AllocZeroed), inputs: &[AllocatorMethodInput { name: "layout", ty: AllocatorTy::Layout }], output: AllocatorTy::ResultPtr, }, diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index a7e83f65151a..de0b85ebb63b 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -1,13 +1,13 @@ use libc::c_uint; use rustc_ast::expand::allocator::{ - AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name, + AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, SpecialAllocatorMethod, + default_fn_name, global_fn_name, }; use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{DebugInfo, OomStrategy}; -use rustc_span::sym; use rustc_symbol_mangling::mangle_internal_symbol; use crate::attributes::llfn_attrs_from_instance; @@ -65,12 +65,12 @@ pub(crate) unsafe fn codegen( let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name)); let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name)); - let alloc_attr_flag = match method.name { - sym::alloc => CodegenFnAttrFlags::ALLOCATOR, - sym::dealloc => CodegenFnAttrFlags::DEALLOCATOR, - sym::realloc => CodegenFnAttrFlags::REALLOCATOR, - sym::alloc_zeroed => CodegenFnAttrFlags::ALLOCATOR_ZEROED, - _ => CodegenFnAttrFlags::empty(), + let alloc_attr_flag = match method.special { + Some(SpecialAllocatorMethod::Alloc) => CodegenFnAttrFlags::ALLOCATOR, + Some(SpecialAllocatorMethod::Dealloc) => CodegenFnAttrFlags::DEALLOCATOR, + Some(SpecialAllocatorMethod::Realloc) => CodegenFnAttrFlags::REALLOCATOR, + Some(SpecialAllocatorMethod::AllocZeroed) => CodegenFnAttrFlags::ALLOCATOR_ZEROED, + None => CodegenFnAttrFlags::empty(), }; let mut attrs = CodegenFnAttrs::new(); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 1a79038d1fcd..ecb1750ddfd3 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -669,6 +669,7 @@ pub fn allocator_shim_contents(tcx: TyCtxt<'_>, kind: AllocatorKind) -> Vec { pub(crate) pthread_rwlock_sanity: Cell, pub(crate) pthread_condvar_sanity: Cell, + /// (Foreign) symbols that are synthesized as part of the allocator shim: the key indicates the + /// name of the symbol being synthesized; the value indicates whether this should invoke some + /// other symbol or whether this has special allocator semantics. + pub(crate) allocator_shim_symbols: FxHashMap>, /// Cache for `mangle_internal_symbol`. pub(crate) mangle_internal_symbol_cache: FxHashMap<&'static str, String>, @@ -819,6 +826,7 @@ impl<'tcx> MiriMachine<'tcx> { pthread_mutex_sanity: Cell::new(false), pthread_rwlock_sanity: Cell::new(false), pthread_condvar_sanity: Cell::new(false), + allocator_shim_symbols: Self::allocator_shim_symbols(tcx), mangle_internal_symbol_cache: Default::default(), force_intrinsic_fallback: config.force_intrinsic_fallback, float_nondet: config.float_nondet, @@ -827,6 +835,36 @@ impl<'tcx> MiriMachine<'tcx> { } } + fn allocator_shim_symbols( + tcx: TyCtxt<'tcx>, + ) -> FxHashMap> { + use rustc_codegen_ssa::base::allocator_shim_contents; + + // codegen uses `allocator_kind_for_codegen` here, but that's only needed to deal with + // dylibs which we do not support. + let Some(kind) = tcx.allocator_kind(()) else { + return Default::default(); + }; + let methods = allocator_shim_contents(tcx, kind); + let mut symbols = FxHashMap::default(); + for method in methods { + let from_name = Symbol::intern(&mangle_internal_symbol( + tcx, + &allocator::global_fn_name(method.name), + )); + let to = match method.special { + Some(special) => Either::Right(special), + None => + Either::Left(Symbol::intern(&mangle_internal_symbol( + tcx, + &allocator::default_fn_name(method.name), + ))), + }; + symbols.try_insert(from_name, to).unwrap(); + } + symbols + } + pub(crate) fn late_init( ecx: &mut MiriInterpCx<'tcx>, config: &MiriConfig, @@ -992,6 +1030,7 @@ impl VisitProvenance for MiriMachine<'_> { pthread_mutex_sanity: _, pthread_rwlock_sanity: _, pthread_condvar_sanity: _, + allocator_shim_symbols: _, mangle_internal_symbol_cache: _, force_intrinsic_fallback: _, float_nondet: _, diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs index f05c5fbbe1d4..f498a21c9f90 100644 --- a/src/tools/miri/src/shims/alloc.rs +++ b/src/tools/miri/src/shims/alloc.rs @@ -1,5 +1,8 @@ -use rustc_abi::{Align, Size}; -use rustc_ast::expand::allocator::AllocatorKind; +use rustc_abi::{Align, AlignFromBytesError, CanonAbi, Size}; +use rustc_ast::expand::allocator::SpecialAllocatorMethod; +use rustc_middle::ty::Ty; +use rustc_span::Symbol; +use rustc_target::callconv::FnAbi; use crate::*; @@ -54,30 +57,100 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Align::from_bytes(prev_power_of_two(size)).unwrap() } - /// Emulates calling the internal __rust_* allocator functions - fn emulate_allocator( + /// Check some basic requirements for this allocation request: + /// non-zero size, power-of-two alignment. + fn check_rust_alloc_request(&self, size: u64, align: u64) -> InterpResult<'tcx> { + let this = self.eval_context_ref(); + if size == 0 { + throw_ub_format!("creating allocation with size 0"); + } + if size > this.max_size_of_val().bytes() { + throw_ub_format!("creating an allocation larger than half the address space"); + } + if let Err(e) = Align::from_bytes(align) { + match e { + AlignFromBytesError::TooLarge(_) => { + throw_unsup_format!( + "creating allocation with alignment {align} exceeding rustc's maximum \ + supported value" + ); + } + AlignFromBytesError::NotPowerOfTwo(_) => { + throw_ub_format!("creating allocation with non-power-of-two alignment {align}"); + } + } + } + + interp_ok(()) + } + + fn rust_special_allocator_method( &mut self, - default: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx>, - ) -> InterpResult<'tcx, EmulateItemResult> { + method: SpecialAllocatorMethod, + link_name: Symbol, + abi: &FnAbi<'tcx, Ty<'tcx>>, + args: &[OpTy<'tcx>], + dest: &PlaceTy<'tcx>, + ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let Some(allocator_kind) = this.tcx.allocator_kind(()) else { - // in real code, this symbol does not exist without an allocator - return interp_ok(EmulateItemResult::NotSupported); - }; + match method { + SpecialAllocatorMethod::Alloc | SpecialAllocatorMethod::AllocZeroed => { + let [size, align] = + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; + let size = this.read_target_usize(size)?; + let align = this.read_target_usize(align)?; - match allocator_kind { - AllocatorKind::Global => { - // When `#[global_allocator]` is used, `__rust_*` is defined by the macro expansion - // of this attribute. As such we have to call an exported Rust function, - // and not execute any Miri shim. Somewhat unintuitively doing so is done - // by returning `NotSupported`, which triggers the `lookup_exported_symbol` - // fallback case in `emulate_foreign_item`. - interp_ok(EmulateItemResult::NotSupported) + this.check_rust_alloc_request(size, align)?; + + let ptr = this.allocate_ptr( + Size::from_bytes(size), + Align::from_bytes(align).unwrap(), + MiriMemoryKind::Rust.into(), + if matches!(method, SpecialAllocatorMethod::AllocZeroed) { + AllocInit::Zero + } else { + AllocInit::Uninit + }, + )?; + + this.write_pointer(ptr, dest) } - AllocatorKind::Default => { - default(this)?; - interp_ok(EmulateItemResult::NeedsReturn) + SpecialAllocatorMethod::Dealloc => { + let [ptr, old_size, align] = + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; + let ptr = this.read_pointer(ptr)?; + let old_size = this.read_target_usize(old_size)?; + let align = this.read_target_usize(align)?; + + // No need to check old_size/align; we anyway check that they match the allocation. + this.deallocate_ptr( + ptr, + Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())), + MiriMemoryKind::Rust.into(), + ) + } + SpecialAllocatorMethod::Realloc => { + let [ptr, old_size, align, new_size] = + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; + let ptr = this.read_pointer(ptr)?; + let old_size = this.read_target_usize(old_size)?; + let align = this.read_target_usize(align)?; + let new_size = this.read_target_usize(new_size)?; + // No need to check old_size; we anyway check that they match the allocation. + + this.check_rust_alloc_request(new_size, align)?; + + let align = Align::from_bytes(align).unwrap(); + let new_ptr = this.reallocate_ptr( + ptr, + Some((Size::from_bytes(old_size), align)), + Size::from_bytes(new_size), + align, + MiriMemoryKind::Rust.into(), + AllocInit::Uninit, + )?; + this.write_pointer(new_ptr, dest) } } } diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 26692e519a0b..74818cf0740b 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -2,8 +2,9 @@ use std::collections::hash_map::Entry; use std::io::Write; use std::path::Path; -use rustc_abi::{Align, AlignFromBytesError, CanonAbi, Size}; -use rustc_ast::expand::allocator::AllocatorKind; +use rustc_abi::{Align, CanonAbi, Size}; +use rustc_ast::expand::allocator::NO_ALLOC_SHIM_IS_UNSTABLE; +use rustc_data_structures::either::Either; use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::CrateNum; @@ -11,6 +12,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::AllocInit; use rustc_middle::ty::{Instance, Ty}; use rustc_middle::{mir, ty}; +use rustc_session::config::OomStrategy; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; @@ -50,31 +52,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> { let this = self.eval_context_mut(); - // Some shims forward to other MIR bodies. - match link_name.as_str() { - // This allocator function has forwarding shims synthesized during normal codegen - // (see `allocator_shim_contents`); this is where we emulate that behavior. - // FIXME should use global_fn_name, but mangle_internal_symbol requires a static str. - name if name == this.mangle_internal_symbol("__rust_alloc_error_handler") => { - // Forward to the right symbol that implements this function. - let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else { - // in real code, this symbol does not exist without an allocator - throw_unsup_format!( - "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" - ); - }; - if handler_kind == AllocatorKind::Default { - let name = - Symbol::intern(this.mangle_internal_symbol("__rdl_alloc_error_handler")); + // Handle allocator shim. + if let Some(shim) = this.machine.allocator_shim_symbols.get(&link_name) { + match *shim { + Either::Left(other_fn) => { let handler = this - .lookup_exported_symbol(name)? + .lookup_exported_symbol(other_fn)? .expect("missing alloc error handler symbol"); return interp_ok(Some(handler)); } - // Fall through to the `lookup_exported_symbol` below which should find - // a `__rust_alloc_error_handler`. + Either::Right(special) => { + this.rust_special_allocator_method(special, link_name, abi, args, dest)?; + this.return_to_block(ret)?; + return interp_ok(None); + } } - _ => {} } // FIXME: avoid allocating memory @@ -254,33 +246,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { - /// Check some basic requirements for this allocation request: - /// non-zero size, power-of-two alignment. - fn check_rustc_alloc_request(&self, size: u64, align: u64) -> InterpResult<'tcx> { - let this = self.eval_context_ref(); - if size == 0 { - throw_ub_format!("creating allocation with size 0"); - } - if size > this.max_size_of_val().bytes() { - throw_ub_format!("creating an allocation larger than half the address space"); - } - if let Err(e) = Align::from_bytes(align) { - match e { - AlignFromBytesError::TooLarge(_) => { - throw_unsup_format!( - "creating allocation with alignment {align} exceeding rustc's maximum \ - supported value" - ); - } - AlignFromBytesError::NotPowerOfTwo(_) => { - throw_ub_format!("creating allocation with non-power-of-two alignment {align}"); - } - } - } - - interp_ok(()) - } - fn emulate_foreign_item_inner( &mut self, link_name: Symbol, @@ -340,7 +305,51 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Here we dispatch all the shims for foreign functions. If you have a platform specific // shim, add it to the corresponding submodule. match link_name.as_str() { + // Magic functions Rust emits (and not as part of the allocator shim). + name if name == this.mangle_internal_symbol(NO_ALLOC_SHIM_IS_UNSTABLE) => { + // This is a no-op shim that only exists to prevent making the allocator shims + // instantly stable. + let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; + } + name if name == this.mangle_internal_symbol(OomStrategy::SYMBOL) => { + // Gets the value of the `oom` option. + let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; + let val = this.tcx.sess.opts.unstable_opts.oom.should_panic(); + this.write_int(val, dest)?; + } + // Miri-specific extern functions + "miri_alloc" => { + let [size, align] = + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; + let size = this.read_target_usize(size)?; + let align = this.read_target_usize(align)?; + + this.check_rust_alloc_request(size, align)?; + + let ptr = this.allocate_ptr( + Size::from_bytes(size), + Align::from_bytes(align).unwrap(), + MiriMemoryKind::Miri.into(), + AllocInit::Uninit, + )?; + + this.write_pointer(ptr, dest)?; + } + "miri_dealloc" => { + let [ptr, old_size, align] = + this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; + let ptr = this.read_pointer(ptr)?; + let old_size = this.read_target_usize(old_size)?; + let align = this.read_target_usize(align)?; + + // No need to check old_size/align; we anyway check that they match the allocation. + this.deallocate_ptr( + ptr, + Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())), + MiriMemoryKind::Miri.into(), + )?; + } "miri_start_unwind" => { let [payload] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; @@ -492,7 +501,6 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } } - // GenMC mode: Assume statements block the current thread when their condition is false. "miri_genmc_assume" => { let [condition] = @@ -579,133 +587,6 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } - // Rust allocation - name if name == this.mangle_internal_symbol("__rust_alloc") || name == "miri_alloc" => { - let default = |ecx: &mut MiriInterpCx<'tcx>| { - // Only call `check_shim` when `#[global_allocator]` isn't used. When that - // macro is used, we act like no shim exists, so that the exported function can run. - let [size, align] = - ecx.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; - let size = ecx.read_target_usize(size)?; - let align = ecx.read_target_usize(align)?; - - ecx.check_rustc_alloc_request(size, align)?; - - let memory_kind = match link_name.as_str() { - "miri_alloc" => MiriMemoryKind::Miri, - _ => MiriMemoryKind::Rust, - }; - - let ptr = ecx.allocate_ptr( - Size::from_bytes(size), - Align::from_bytes(align).unwrap(), - memory_kind.into(), - AllocInit::Uninit, - )?; - - ecx.write_pointer(ptr, dest) - }; - - match link_name.as_str() { - "miri_alloc" => { - default(this)?; - return interp_ok(EmulateItemResult::NeedsReturn); - } - _ => return this.emulate_allocator(default), - } - } - name if name == this.mangle_internal_symbol("__rust_alloc_zeroed") => { - return this.emulate_allocator(|this| { - // See the comment for `__rust_alloc` why `check_shim` is only called in the - // default case. - let [size, align] = - this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; - let size = this.read_target_usize(size)?; - let align = this.read_target_usize(align)?; - - this.check_rustc_alloc_request(size, align)?; - - let ptr = this.allocate_ptr( - Size::from_bytes(size), - Align::from_bytes(align).unwrap(), - MiriMemoryKind::Rust.into(), - AllocInit::Zero, - )?; - this.write_pointer(ptr, dest) - }); - } - name if name == this.mangle_internal_symbol("__rust_dealloc") - || name == "miri_dealloc" => - { - let default = |ecx: &mut MiriInterpCx<'tcx>| { - // See the comment for `__rust_alloc` why `check_shim` is only called in the - // default case. - let [ptr, old_size, align] = - ecx.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; - let ptr = ecx.read_pointer(ptr)?; - let old_size = ecx.read_target_usize(old_size)?; - let align = ecx.read_target_usize(align)?; - - let memory_kind = match link_name.as_str() { - "miri_dealloc" => MiriMemoryKind::Miri, - _ => MiriMemoryKind::Rust, - }; - - // No need to check old_size/align; we anyway check that they match the allocation. - ecx.deallocate_ptr( - ptr, - Some((Size::from_bytes(old_size), Align::from_bytes(align).unwrap())), - memory_kind.into(), - ) - }; - - match link_name.as_str() { - "miri_dealloc" => { - default(this)?; - return interp_ok(EmulateItemResult::NeedsReturn); - } - _ => return this.emulate_allocator(default), - } - } - name if name == this.mangle_internal_symbol("__rust_realloc") => { - return this.emulate_allocator(|this| { - // See the comment for `__rust_alloc` why `check_shim` is only called in the - // default case. - let [ptr, old_size, align, new_size] = - this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; - let ptr = this.read_pointer(ptr)?; - let old_size = this.read_target_usize(old_size)?; - let align = this.read_target_usize(align)?; - let new_size = this.read_target_usize(new_size)?; - // No need to check old_size; we anyway check that they match the allocation. - - this.check_rustc_alloc_request(new_size, align)?; - - let align = Align::from_bytes(align).unwrap(); - let new_ptr = this.reallocate_ptr( - ptr, - Some((Size::from_bytes(old_size), align)), - Size::from_bytes(new_size), - align, - MiriMemoryKind::Rust.into(), - AllocInit::Uninit, - )?; - this.write_pointer(new_ptr, dest) - }); - } - name if name == this.mangle_internal_symbol("__rust_no_alloc_shim_is_unstable_v2") => { - // This is a no-op shim that only exists to prevent making the allocator shims instantly stable. - let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; - } - name if name - == this.mangle_internal_symbol("__rust_alloc_error_handler_should_panic_v2") => - { - // Gets the value of the `oom` option. - let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?; - let val = this.tcx.sess.opts.unstable_opts.oom.should_panic(); - this.write_int(val, dest)?; - } - // C memory handling functions "memcmp" => { let [left, right, n] = From 87e0f43c563b9efc02f62a0e9c30acea0d83f7dd Mon Sep 17 00:00:00 2001 From: Diggory Blake Date: Wed, 15 Oct 2025 21:15:41 +0100 Subject: [PATCH 17/17] Revert unintentional whitespace changes to rustfmt-excluded file --- src/tools/miri/src/bin/log/tracing_chrome.rs | 56 +++++++-------- src/tools/miri/src/intrinsics/simd.rs | 76 ++++++++++---------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src/tools/miri/src/bin/log/tracing_chrome.rs b/src/tools/miri/src/bin/log/tracing_chrome.rs index f4bff76c2029..85b4de62a5ec 100644 --- a/src/tools/miri/src/bin/log/tracing_chrome.rs +++ b/src/tools/miri/src/bin/log/tracing_chrome.rs @@ -523,16 +523,16 @@ where } }, TraceStyle::Async => Some( - span.scope() - .from_root() - .take(1) - .next() - .unwrap_or(span) - .id() - .into_u64() + span.scope() + .from_root() + .take(1) + .next() + .unwrap_or(span) + .id() + .into_u64() .cast_signed() // the comment above explains the cast ), - } + } } fn enter_span(&self, span: SpanRef, ts: f64, tid: usize, out: &Sender) { @@ -567,11 +567,11 @@ where Some(thread_data) => (thread_data, false), None => { let tid = self.max_tid.fetch_add(1, Ordering::SeqCst); - let out = self.out.lock().unwrap().clone(); + let out = self.out.lock().unwrap().clone(); let start = TracingChromeInstant::setup_for_thread_and_start(tid); *thread_data = Some(ThreadData { tid, out, start }); (thread_data.as_mut().unwrap(), true) - } + } }; start.with_elapsed_micros_subtracting_tracing(|ts| { @@ -583,7 +583,7 @@ where let _ignored = out.send(Message::NewThread(*tid, name)); } f(ts, *tid, out); - }); + }); }); } } @@ -605,15 +605,15 @@ where fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) { if self.include_args { self.with_elapsed_micros_subtracting_tracing(|_, _, _| { - let span = ctx.span(id).unwrap(); - let mut exts = span.extensions_mut(); + let span = ctx.span(id).unwrap(); + let mut exts = span.extensions_mut(); - let args = exts.get_mut::(); + let args = exts.get_mut::(); - if let Some(args) = args { - let args = Arc::make_mut(&mut args.args); - values.record(&mut JsonVisitor { object: args }); - } + if let Some(args) = args { + let args = Arc::make_mut(&mut args.args); + values.record(&mut JsonVisitor { object: args }); + } }); } } @@ -636,16 +636,16 @@ where fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) { self.with_elapsed_micros_subtracting_tracing(|ts, tid, out| { - if self.include_args { - let mut args = Object::new(); - attrs.record(&mut JsonVisitor { object: &mut args }); - ctx.span(id).unwrap().extensions_mut().insert(ArgsWrapper { - args: Arc::new(args), - }); - } - if let TraceStyle::Threaded = self.trace_style { - return; - } + if self.include_args { + let mut args = Object::new(); + attrs.record(&mut JsonVisitor { object: &mut args }); + ctx.span(id).unwrap().extensions_mut().insert(ArgsWrapper { + args: Arc::new(args), + }); + } + if let TraceStyle::Threaded = self.trace_style { + return; + } self.enter_span(ctx.span(id).expect("Span not found."), ts, tid, out); }); diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs index bf7834422a81..1e7366b5a826 100644 --- a/src/tools/miri/src/intrinsics/simd.rs +++ b/src/tools/miri/src/intrinsics/simd.rs @@ -38,47 +38,47 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { for i in 0..dest_len { let op = this.read_immediate(&this.project_index(&op, i)?)?; let dest = this.project_index(&dest, i)?; - let ty::Float(float_ty) = op.layout.ty.kind() else { - span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name) - }; - // Using host floats except for sqrt (but it's fine, these operations do not - // have guaranteed precision). + let ty::Float(float_ty) = op.layout.ty.kind() else { + span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name) + }; + // Using host floats except for sqrt (but it's fine, these operations do not + // have guaranteed precision). let val = match float_ty { - FloatTy::F16 => unimplemented!("f16_f128"), - FloatTy::F32 => { - let f = op.to_scalar().to_f32()?; + FloatTy::F16 => unimplemented!("f16_f128"), + FloatTy::F32 => { + let f = op.to_scalar().to_f32()?; let res = match intrinsic_name { - "fsqrt" => math::sqrt(f), - "fsin" => f.to_host().sin().to_soft(), - "fcos" => f.to_host().cos().to_soft(), - "fexp" => f.to_host().exp().to_soft(), - "fexp2" => f.to_host().exp2().to_soft(), - "flog" => f.to_host().ln().to_soft(), - "flog2" => f.to_host().log2().to_soft(), - "flog10" => f.to_host().log10().to_soft(), - _ => bug!(), - }; - let res = this.adjust_nan(res, &[f]); - Scalar::from(res) - } - FloatTy::F64 => { - let f = op.to_scalar().to_f64()?; - let res = match intrinsic_name { - "fsqrt" => math::sqrt(f), - "fsin" => f.to_host().sin().to_soft(), - "fcos" => f.to_host().cos().to_soft(), - "fexp" => f.to_host().exp().to_soft(), - "fexp2" => f.to_host().exp2().to_soft(), - "flog" => f.to_host().ln().to_soft(), - "flog2" => f.to_host().log2().to_soft(), - "flog10" => f.to_host().log10().to_soft(), - _ => bug!(), - }; - let res = this.adjust_nan(res, &[f]); - Scalar::from(res) - } - FloatTy::F128 => unimplemented!("f16_f128"), + "fsqrt" => math::sqrt(f), + "fsin" => f.to_host().sin().to_soft(), + "fcos" => f.to_host().cos().to_soft(), + "fexp" => f.to_host().exp().to_soft(), + "fexp2" => f.to_host().exp2().to_soft(), + "flog" => f.to_host().ln().to_soft(), + "flog2" => f.to_host().log2().to_soft(), + "flog10" => f.to_host().log10().to_soft(), + _ => bug!(), }; + let res = this.adjust_nan(res, &[f]); + Scalar::from(res) + } + FloatTy::F64 => { + let f = op.to_scalar().to_f64()?; + let res = match intrinsic_name { + "fsqrt" => math::sqrt(f), + "fsin" => f.to_host().sin().to_soft(), + "fcos" => f.to_host().cos().to_soft(), + "fexp" => f.to_host().exp().to_soft(), + "fexp2" => f.to_host().exp2().to_soft(), + "flog" => f.to_host().ln().to_soft(), + "flog2" => f.to_host().log2().to_soft(), + "flog10" => f.to_host().log10().to_soft(), + _ => bug!(), + }; + let res = this.adjust_nan(res, &[f]); + Scalar::from(res) + } + FloatTy::F128 => unimplemented!("f16_f128"), + }; this.write_scalar(val, &dest)?; }