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_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_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_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_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/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/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 { #[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_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2f60a9119cbe..394747f81581 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] @@ -1423,7 +1427,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_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 218f0ef5458c..c1dbf904c6fa 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) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d14bc600f2f1..6167b0d63a9a 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -393,7 +393,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_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_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_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 4d1fcaeda5e2..0af7fe808ef9 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() { 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 e790ecd595be..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::{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, @@ -1355,6 +1357,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 +1383,23 @@ where return Ok((candidate.result, Some(TraitGoalProvenVia::Misc))); } + // 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) + && candidates.iter().any(|c| { + matches!(c.source, CandidateSource::AliasBound(AliasBoundKind::SelfBounds)) + }) + { + 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 // (including global ones) over everything else. let has_non_global_where_bounds = candidates @@ -1427,9 +1447,10 @@ where }; } - if candidates.iter().any(|c| matches!(c.source, CandidateSource::AliasBound)) { + // 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)) + .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))) @@ -1470,7 +1491,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_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 491d13dc9c07..970d16313584 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -216,8 +216,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/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, } 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 708a53f6c650..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) } @@ -144,15 +144,13 @@ 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()); 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 { @@ -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/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index fb4f28412d42..9be5d0673f73 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -28,9 +28,11 @@ 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_next_trait_solver::solve::AliasBoundKind; use rustc_span::{Symbol, sym}; use tracing::{debug, instrument, trace}; @@ -474,7 +476,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) @@ -1623,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() { @@ -1643,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; } @@ -1660,7 +1671,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return ControlFlow::Continue(()); } - in_parent_alias_type = true; + alias_bound_kind = AliasBoundKind::NonSelfBounds; } } @@ -1821,6 +1832,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 +1886,29 @@ impl<'tcx> SelectionContext<'_, 'tcx> { break; } + 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_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, + } + } + // 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,12 +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. - 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)), + 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, } @@ -2001,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_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/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..1e0263b232f4 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 { @@ -165,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. @@ -183,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/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. /// 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/library/std/src/sync/nonpoison/rwlock.rs b/library/std/src/sync/nonpoison/rwlock.rs index 568c7f386847..dc5d9479ba5a 100644 --- a/library/std/src/sync/nonpoison/rwlock.rs +++ b/library/std/src/sync/nonpoison/rwlock.rs @@ -700,7 +700,6 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { /// /// ``` /// #![feature(nonpoison_rwlock)] - /// #![feature(rwlock_downgrade)] /// /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard}; /// @@ -719,7 +718,6 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { /// /// ``` /// #![feature(nonpoison_rwlock)] - /// #![feature(rwlock_downgrade)] /// /// use std::sync::Arc; /// use std::sync::nonpoison::{RwLock, RwLockWriteGuard}; @@ -752,8 +750,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 e3a72c73bf4e..fe51d8975e42 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 23112e102844..20e34c9aa6bd 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_condvar)] diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2fd9fe95dd58..481395ffb836 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/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 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()) 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)?; } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 8b85e9e3dd65..1206859d1cdc 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -53,6 +53,7 @@ extern crate rustc_abi; extern crate rustc_apfloat; extern crate rustc_ast; +extern crate rustc_codegen_ssa; extern crate rustc_const_eval; extern crate rustc_data_structures; extern crate rustc_errors; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index b9785b85eb83..fadbdf5cea99 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -12,6 +12,8 @@ use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; use rustc_abi::{Align, ExternAbi, Size}; use rustc_apfloat::{Float, FloatConvert}; +use rustc_ast::expand::allocator::{self, SpecialAllocatorMethod}; +use rustc_data_structures::either::Either; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[allow(unused)] use rustc_data_structures::static_assert_size; @@ -27,6 +29,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::config::InliningThreshold; use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::{Span, SpanData, Symbol}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::callconv::FnAbi; use crate::alloc_addresses::EvalContextExt; @@ -652,6 +655,10 @@ pub struct MiriMachine<'tcx> { 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] = 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.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr deleted file mode 100644 index c5c98ac807ea..000000000000 --- a/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error: lifetime bound not satisfied - --> $DIR/higher-ranked-auto-trait-3.rs:66: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 1 previous error - 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..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,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 #![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/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/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 + 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/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/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/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/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/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 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>, +{ +} 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_sized_hierarchy.stderr deleted file mode 100644 index b904b784df73..000000000000 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current_sized_hierarchy.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/incomplete-inference-issue-143992.rs:30: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:21: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_sized_hierarchy.stderr b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr deleted file mode 100644 index b904b784df73..000000000000 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/incomplete-inference-issue-143992.rs:30: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:21: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 b9e65ed28393..44453b65e7cd 100644 --- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs +++ b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs @@ -1,12 +1,8 @@ +//@ check-pass //@ 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 //@[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 +24,4 @@ where T::Assoc<[u32; 1]>: Clone, { let _x = T::Assoc::new(()); - //[next_sized_hierarchy]~^ ERROR mismatched types - //[current_sized_hierarchy]~^^ 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/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>(); +} 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 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`. diff --git a/triagebot.toml b/triagebot.toml index f185648e7cc7..605145fa004f 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -738,13 +738,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